feat(iace): complete CE risk assessment — LLM tech-file generation, multi-format export, TipTap editor
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 36s
CI/CD / test-python-backend-compliance (push) Successful in 33s
CI/CD / test-python-document-crawler (push) Successful in 24s
CI/CD / test-python-dsms-gateway (push) Successful in 21s
CI/CD / validate-canonical-controls (push) Successful in 13s
CI/CD / Deploy (push) Successful in 2s

Phase 1: Fix completeness gates G23 (require verified/rejected mitigations) and G09 (audit trail check)
Phase 2: LLM-based tech-file section generation with 19 German prompts and RAG enrichment
Phase 3: Multi-format document export (PDF/Excel/DOCX/Markdown/JSON)
Phase 4: Company profile → IACE data flow with auto component/classification creation
Phase 5: TipTap WYSIWYG editor replacing textarea for tech-file sections
Phase 6: User journey tests, developer portal API reference, updated documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-16 12:50:53 +01:00
parent 5adb1c5f16
commit 6d2de9b897
16 changed files with 5828 additions and 161 deletions

View File

@@ -33,7 +33,7 @@ func TestCompletenessCheck_EmptyContext(t *testing.T) {
// With nil project, most gates fail. However, some auto-pass:
// G06 (AI classification): auto-passes when HasAI=false
// G22 (critical/high mitigated): auto-passes when no critical/high assessments exist
// G23 (mitigations verified): auto-passes when no mitigations with status "implemented"
// G23 (mitigations verified): auto-passes when no mitigations (empty list)
// G42 (AI documents): auto-passes when HasAI=false
// That gives 4 required gates passing even with empty context.
if result.PassedRequired != 4 {
@@ -89,7 +89,8 @@ func TestCompletenessCheck_MinimalValidProject(t *testing.T) {
{ID: uuid.New(), ProjectID: projectID, SectionType: "risk_assessment_report"},
{ID: uuid.New(), ProjectID: projectID, SectionType: "hazard_log_combined"},
},
HasAI: false,
HasAI: false,
PatternMatchingPerformed: true,
}
result := checker.Check(ctx)
@@ -376,11 +377,11 @@ func TestCompletenessCheck_G23_MitigationsVerified(t *testing.T) {
wantG23Passed: false,
},
{
name: "planned mitigations pass G23 (not yet implemented)",
name: "planned mitigations fail G23 (not yet verified)",
mitigations: []Mitigation{
{HazardID: hazardID, Status: MitigationStatusPlanned},
},
wantG23Passed: true,
wantG23Passed: false,
},
{
name: "rejected mitigations pass G23",
@@ -390,12 +391,20 @@ func TestCompletenessCheck_G23_MitigationsVerified(t *testing.T) {
wantG23Passed: true,
},
{
name: "mix of verified planned rejected passes G23",
name: "mix of verified planned rejected fails G23",
mitigations: []Mitigation{
{HazardID: hazardID, Status: MitigationStatusVerified},
{HazardID: hazardID, Status: MitigationStatusPlanned},
{HazardID: hazardID, Status: MitigationStatusRejected},
},
wantG23Passed: false,
},
{
name: "mix of verified and rejected passes G23",
mitigations: []Mitigation{
{HazardID: hazardID, Status: MitigationStatusVerified},
{HazardID: hazardID, Status: MitigationStatusRejected},
},
wantG23Passed: true,
},
}
@@ -422,6 +431,48 @@ func TestCompletenessCheck_G23_MitigationsVerified(t *testing.T) {
}
}
func TestCompletenessCheck_G09_PatternMatchingPerformed(t *testing.T) {
checker := NewCompletenessChecker()
tests := []struct {
name string
performed bool
wantG09Passed bool
}{
{
name: "pattern matching not performed fails G09",
performed: false,
wantG09Passed: false,
},
{
name: "pattern matching performed passes G09",
performed: true,
wantG09Passed: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := &CompletenessContext{
Project: &Project{MachineName: "Test"},
PatternMatchingPerformed: tt.performed,
}
result := checker.Check(ctx)
for _, g := range result.Gates {
if g.ID == "G09" {
if g.Passed != tt.wantG09Passed {
t.Errorf("G09 Passed = %v, want %v", g.Passed, tt.wantG09Passed)
}
return
}
}
t.Error("G09 gate not found in results")
})
}
}
func TestCompletenessCheck_G24_ResidualRiskAccepted(t *testing.T) {
checker := NewCompletenessChecker()