Add implemented state and justification to controls
Introduce `implemented` enum (IMPLEMENTED/NOT_IMPLEMENTED) and `not_implemented_justification` (nullable text) fields on the Control entity across all API surfaces (GraphQL, MCP, CLI), database, frontend, and SOA export. The database stores implementation state as a PostgreSQL enum `control_implementation_state`. Controls default to IMPLEMENTED during migration. The SOA list and PDF export show implementation status alongside applicability, with "-" for non-applicable controls. Justification columns are renamed for clarity: "Justification for non-applicability" and "Justification for non-implementation". Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -64,6 +64,7 @@ func TestControl_Create(t *testing.T) {
|
||||
"name": "Information Security Policies",
|
||||
"description": "Policies for information security",
|
||||
"bestPractice": true,
|
||||
"implemented": "IMPLEMENTED",
|
||||
},
|
||||
}, &result)
|
||||
require.NoError(t, err)
|
||||
@@ -269,6 +270,7 @@ func TestControl_RequiredFields(t *testing.T) {
|
||||
"description": "Test",
|
||||
"sectionTitle": "Section 1",
|
||||
"bestPractice": true,
|
||||
"implemented": "IMPLEMENTED",
|
||||
},
|
||||
},
|
||||
wantError: true,
|
||||
@@ -281,6 +283,7 @@ func TestControl_RequiredFields(t *testing.T) {
|
||||
"description": "Test",
|
||||
"sectionTitle": "Section 1",
|
||||
"bestPractice": true,
|
||||
"implemented": "IMPLEMENTED",
|
||||
},
|
||||
},
|
||||
wantError: true,
|
||||
@@ -293,6 +296,7 @@ func TestControl_RequiredFields(t *testing.T) {
|
||||
"name": "Test Control",
|
||||
"description": "Test",
|
||||
"bestPractice": true,
|
||||
"implemented": "IMPLEMENTED",
|
||||
},
|
||||
},
|
||||
wantError: true,
|
||||
@@ -305,6 +309,7 @@ func TestControl_RequiredFields(t *testing.T) {
|
||||
"name": "Test Control",
|
||||
"sectionTitle": "Section 1",
|
||||
"bestPractice": true,
|
||||
"implemented": "IMPLEMENTED",
|
||||
},
|
||||
},
|
||||
wantError: true,
|
||||
@@ -317,6 +322,20 @@ func TestControl_RequiredFields(t *testing.T) {
|
||||
"name": "Test Control",
|
||||
"description": "Test",
|
||||
"sectionTitle": "Section 1",
|
||||
"implemented": "IMPLEMENTED",
|
||||
},
|
||||
},
|
||||
wantError: true,
|
||||
},
|
||||
{
|
||||
name: "Missing implemented should fail",
|
||||
variables: map[string]any{
|
||||
"input": map[string]any{
|
||||
"frameworkId": frameworkID,
|
||||
"name": "Test Control",
|
||||
"description": "Test",
|
||||
"sectionTitle": "Section 1",
|
||||
"bestPractice": true,
|
||||
},
|
||||
},
|
||||
wantError: true,
|
||||
@@ -404,6 +423,7 @@ func TestControl_OmittableDescription(t *testing.T) {
|
||||
"description": "Initial description",
|
||||
"sectionTitle": "Section 1",
|
||||
"bestPractice": true,
|
||||
"implemented": "IMPLEMENTED",
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
@@ -568,6 +588,7 @@ func TestControl_SubResolvers(t *testing.T) {
|
||||
"description": "Test description",
|
||||
"sectionTitle": "Section 1",
|
||||
"bestPractice": true,
|
||||
"implemented": "IMPLEMENTED",
|
||||
},
|
||||
}, &controlResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -83,6 +83,7 @@ func TestControlMeasureMapping_CreateDelete(t *testing.T) {
|
||||
"description": "Test control for mapping",
|
||||
"sectionTitle": "Section 1",
|
||||
"bestPractice": true,
|
||||
"implemented": "IMPLEMENTED",
|
||||
},
|
||||
}, &createControlResult)
|
||||
require.NoError(t, err)
|
||||
@@ -362,6 +363,7 @@ func TestControlDocumentMapping_CreateDelete(t *testing.T) {
|
||||
"description": "Test control",
|
||||
"sectionTitle": "Section 1",
|
||||
"bestPractice": true,
|
||||
"implemented": "IMPLEMENTED",
|
||||
},
|
||||
}, &createControlResult)
|
||||
require.NoError(t, err)
|
||||
@@ -503,6 +505,7 @@ func TestControlAuditMapping_CreateDelete(t *testing.T) {
|
||||
"description": "Test control",
|
||||
"sectionTitle": "Section 1",
|
||||
"bestPractice": true,
|
||||
"implemented": "IMPLEMENTED",
|
||||
},
|
||||
}, &createControlResult)
|
||||
require.NoError(t, err)
|
||||
@@ -640,6 +643,7 @@ func TestControlSnapshotMapping_CreateDelete(t *testing.T) {
|
||||
"description": "Test control",
|
||||
"sectionTitle": "Section 1",
|
||||
"bestPractice": true,
|
||||
"implemented": "IMPLEMENTED",
|
||||
},
|
||||
}, &createControlResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -384,7 +384,7 @@ func TestRBAC(t *testing.T) {
|
||||
client: owner,
|
||||
query: createControlMutation,
|
||||
variables: func() map[string]any {
|
||||
return map[string]any{"input": map[string]any{"frameworkId": frameworkID, "name": factory.SafeName("Control"), "description": "Test", "sectionTitle": factory.SafeName("Section Owner"), "bestPractice": true}}
|
||||
return map[string]any{"input": map[string]any{"frameworkId": frameworkID, "name": factory.SafeName("Control"), "description": "Test", "sectionTitle": factory.SafeName("Section Owner"), "bestPractice": true, "implemented": "IMPLEMENTED"}}
|
||||
},
|
||||
shouldAllow: true,
|
||||
},
|
||||
@@ -394,7 +394,7 @@ func TestRBAC(t *testing.T) {
|
||||
client: admin,
|
||||
query: createControlMutation,
|
||||
variables: func() map[string]any {
|
||||
return map[string]any{"input": map[string]any{"frameworkId": frameworkID, "name": factory.SafeName("Control"), "description": "Test", "sectionTitle": factory.SafeName("Section Admin"), "bestPractice": true}}
|
||||
return map[string]any{"input": map[string]any{"frameworkId": frameworkID, "name": factory.SafeName("Control"), "description": "Test", "sectionTitle": factory.SafeName("Section Admin"), "bestPractice": true, "implemented": "IMPLEMENTED"}}
|
||||
},
|
||||
shouldAllow: true,
|
||||
},
|
||||
@@ -404,7 +404,7 @@ func TestRBAC(t *testing.T) {
|
||||
client: viewer,
|
||||
query: createControlMutation,
|
||||
variables: func() map[string]any {
|
||||
return map[string]any{"input": map[string]any{"frameworkId": frameworkID, "name": factory.SafeName("Control"), "description": "Test", "sectionTitle": factory.SafeName("Section Viewer"), "bestPractice": true}}
|
||||
return map[string]any{"input": map[string]any{"frameworkId": frameworkID, "name": factory.SafeName("Control"), "description": "Test", "sectionTitle": factory.SafeName("Section Viewer"), "bestPractice": true, "implemented": "IMPLEMENTED"}}
|
||||
},
|
||||
shouldAllow: false,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user