59 lines
2.1 KiB
C++
59 lines
2.1 KiB
C++
#pragma once
|
|
// Step 603: Compliance Operational Readiness
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "ScoreClampUtil.h"
|
|
#include "ValidationErrorUtil.h"
|
|
|
|
struct ComplianceReadinessSnapshot {
|
|
int controlsCovered = 0;
|
|
int artifactCount = 0;
|
|
int signedAttestations = 0;
|
|
int expiringSoon = 0;
|
|
int approvedExceptions = 0;
|
|
int openRunbooks = 0;
|
|
};
|
|
|
|
class ComplianceOperationalReadiness {
|
|
public:
|
|
static bool validateInput(const ComplianceReadinessSnapshot& s, std::string* error) {
|
|
if (!error) return false;
|
|
error->clear();
|
|
if (s.controlsCovered < 0) return failWith(error, "controls_covered_invalid");
|
|
if (s.artifactCount < 0) return failWith(error, "artifact_count_invalid");
|
|
if (s.signedAttestations < 0) return failWith(error, "signed_attestations_invalid");
|
|
if (s.expiringSoon < 0) return failWith(error, "expiring_soon_invalid");
|
|
if (s.approvedExceptions < 0) return failWith(error, "approved_exceptions_invalid");
|
|
if (s.openRunbooks < 0) return failWith(error, "open_runbooks_invalid");
|
|
return true;
|
|
}
|
|
|
|
static int readinessScore(const ComplianceReadinessSnapshot& s) {
|
|
int score = s.controlsCovered * 5 +
|
|
s.artifactCount * 2 +
|
|
s.signedAttestations * 4 +
|
|
s.approvedExceptions * 2 -
|
|
s.expiringSoon * 3 -
|
|
s.openRunbooks * 4;
|
|
return clampToPercent(score);
|
|
}
|
|
|
|
static std::vector<std::string> blockingFindings(const ComplianceReadinessSnapshot& s) {
|
|
std::vector<std::string> findings;
|
|
if (s.controlsCovered == 0) findings.push_back("controls_uncovered");
|
|
if (s.artifactCount == 0) findings.push_back("artifacts_missing");
|
|
if (s.signedAttestations == 0) findings.push_back("attestations_missing");
|
|
if (s.expiringSoon > 0) findings.push_back("attestations_expiring");
|
|
if (s.openRunbooks > 0) findings.push_back("incidents_open");
|
|
return findings;
|
|
}
|
|
|
|
static bool releaseEligible(const ComplianceReadinessSnapshot& s) {
|
|
return blockingFindings(s).empty();
|
|
}
|
|
|
|
private:
|
|
};
|