123 config_ = std::make_unique<PolicyConfig>();
128 std::vector<std::string> lines = absl::StrSplit(yaml_content,
'\n');
129 bool in_policies =
false;
130 std::string current_policy_type;
131 std::string current_policy_name;
133 for (
const auto& line : lines) {
134 std::string trimmed = std::string(absl::StripAsciiWhitespace(line));
137 if (trimmed.empty() || trimmed[0] ==
'#')
141 if (absl::StartsWith(trimmed,
"version:")) {
142 std::vector<std::string> parts = absl::StrSplit(trimmed,
':');
143 if (parts.size() >= 2) {
144 config_->version = std::string(absl::StripAsciiWhitespace(parts[1]));
146 }
else if (absl::StartsWith(trimmed,
"enabled:")) {
147 std::vector<std::string> parts = absl::StrSplit(trimmed,
':');
148 if (parts.size() >= 2) {
149 std::string value = std::string(absl::StripAsciiWhitespace(parts[1]));
150 config_->enabled = (value ==
"true");
152 }
else if (trimmed ==
"policies:") {
154 }
else if (in_policies && absl::StartsWith(trimmed,
"- name:")) {
156 std::vector<std::string> parts = absl::StrSplit(trimmed,
':');
157 if (parts.size() >= 2) {
158 current_policy_name = std::string(absl::StripAsciiWhitespace(parts[1]));
160 }
else if (in_policies && absl::StartsWith(trimmed,
"type:")) {
161 std::vector<std::string> parts = absl::StrSplit(trimmed,
':');
162 if (parts.size() >= 2) {
163 current_policy_type = std::string(absl::StripAsciiWhitespace(parts[1]));
166 if (current_policy_type ==
"change_constraint") {
168 constraint.
name = current_policy_name;
171 constraint.
message =
"Change scope exceeded";
172 config_->change_constraints.push_back(constraint);
173 }
else if (current_policy_type ==
"forbidden_range") {
175 range.
name = current_policy_name;
176 range.
ranges.push_back(std::make_tuple(0xFFB0, 0xFFFF,
"ROM header"));
177 range.
message =
"Cannot modify protected region";
178 config_->forbidden_ranges.push_back(range);
179 }
else if (current_policy_type ==
"test_requirement") {
181 test.
name = current_policy_name;
182 test.
test_suites.push_back(std::make_pair(
"smoke_test", 1.0));
183 test.
message =
"Required tests must pass";
184 config_->test_requirements.push_back(test);
185 }
else if (current_policy_type ==
"review_requirement") {
187 review.
name = current_policy_name;
188 review.
message =
"Manual review required";
189 config_->review_requirements.push_back(review);
197 return absl::OkStatus();
201 return absl::OkStatus();
246 auto proposal_result = registry.GetProposal(std::string(proposal_id));
248 if (!proposal_result.ok()) {
252 const auto& proposal = proposal_result.value();
254 for (
const auto& policy :
config_->change_constraints) {
259 if (policy.max_bytes_changed > 0 &&
260 proposal.bytes_changed > policy.max_bytes_changed) {
263 violation.
severity = policy.severity;
265 absl::StrFormat(
"%s: %d bytes changed (limit: %d)", policy.message,
266 proposal.bytes_changed, policy.max_bytes_changed);
268 absl::StrFormat(
"Proposal changed %d bytes", proposal.bytes_changed);
273 if (policy.max_commands_executed > 0 &&
274 proposal.commands_executed > policy.max_commands_executed) {
277 violation.
severity = policy.severity;
278 violation.
message = absl::StrFormat(
279 "%s: %d commands executed (limit: %d)", policy.message,
280 proposal.commands_executed, policy.max_commands_executed);
281 violation.
details = absl::StrFormat(
"Proposal executed %d commands",
282 proposal.commands_executed);
304 auto proposal_result = registry.GetProposal(std::string(proposal_id));
306 if (!proposal_result.ok()) {
310 const auto& proposal = proposal_result.value();
312 for (
const auto& policy :
config_->review_requirements) {
317 for (
const auto& condition : policy.conditions) {
318 bool condition_met =
false;
321 if (absl::StrContains(condition.if_clause,
"bytes_changed")) {
323 if (absl::StrContains(condition.if_clause,
">")) {
324 std::vector<std::string> parts =
325 absl::StrSplit(condition.if_clause,
'>');
326 if (parts.size() == 2) {
328 if (absl::SimpleAtoi(absl::StripAsciiWhitespace(parts[1]),
330 condition_met = (proposal.bytes_changed > threshold);
334 }
else if (absl::StrContains(condition.if_clause,
"commands_executed")) {
335 if (absl::StrContains(condition.if_clause,
">")) {
336 std::vector<std::string> parts =
337 absl::StrSplit(condition.if_clause,
'>');
338 if (parts.size() == 2) {
340 if (absl::SimpleAtoi(absl::StripAsciiWhitespace(parts[1]),
342 condition_met = (proposal.commands_executed > threshold);
351 violation.
severity = policy.severity;
353 condition.message.empty() ? policy.message : condition.message;
355 absl::StrFormat(
"Condition met: %s → %s", condition.if_clause,
356 condition.then_clause);