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:
Sacha Al Himdani
2026-03-16 19:24:34 +01:00
parent d8670d2412
commit cf1dadc0b5
25 changed files with 663 additions and 233 deletions

View File

@@ -68,10 +68,12 @@ type (
Dark string `json:"dark"`
} `json:"logo,omitempty"`
Controls []struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
BestPractice *bool `json:"best_practice,omitempty"`
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
BestPractice *bool `json:"best_practice,omitempty"`
Implemented string `json:"implemented,omitempty"`
NotImplementedJustification *string `json:"not_implemented_justification,omitempty"`
} `json:"controls"`
}
}
@@ -573,16 +575,26 @@ func (s FrameworkService) Import(
if control.BestPractice != nil {
bestPractice = *control.BestPractice
}
implemented := coredata.ControlImplementationState(control.Implemented)
if !implemented.IsValid() {
implemented = coredata.ControlImplementationStateImplemented
}
var notImplementedJustification *string
if implemented == coredata.ControlImplementationStateNotImplemented {
notImplementedJustification = control.NotImplementedJustification
}
control := &coredata.Control{
ID: controlID,
FrameworkID: frameworkID,
OrganizationID: organization.ID,
SectionTitle: control.ID,
Name: control.Name,
Description: &description,
BestPractice: bestPractice,
CreatedAt: now,
UpdatedAt: now,
ID: controlID,
FrameworkID: frameworkID,
OrganizationID: organization.ID,
SectionTitle: control.ID,
Name: control.Name,
Description: &description,
BestPractice: bestPractice,
Implemented: implemented,
NotImplementedJustification: notImplementedJustification,
CreatedAt: now,
UpdatedAt: now,
}
if err := control.Insert(ctx, tx, s.svc.scope); err != nil {