Skip to content
31 changes: 29 additions & 2 deletions scripts/lib/main-governance-audit.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const REQUIRED_MAIN_CHECK_NAMES = Object.freeze([
]);

function normalized(value) {
return String(value ?? "").trim();
return typeof value === "string" ? value.trim() : "";
}

function positiveInteger(value) {
Expand All @@ -33,6 +33,25 @@ function rulesOfType(rules, type) {
return rules.filter((rule) => normalized(rule?.type) === type);
}

function observedWorkflowControls(rules) {
return rulesOfType(rules, "workflows").flatMap((rule) => {
const workflows = ruleParameters(rule).workflows;
if (!Array.isArray(workflows)) {
return [];
}
return workflows.map((workflow) => ({
repository_id: positiveInteger(workflow?.repository_id)
? workflow.repository_id
: null,
path: normalized(workflow?.path) || "unknown",
ref: normalized(workflow?.ref) || "unknown",
ruleset_id: positiveInteger(rule?.ruleset_id) ? rule.ruleset_id : null,
ruleset_source_type: normalized(rule?.ruleset_source_type) || "unknown",
ruleset_source: normalized(rule?.ruleset_source) || "unknown",
}));
});
}

export function evaluateMainGovernanceRules(rules) {
const checks = [];
const failures = [];
Expand All @@ -44,7 +63,12 @@ export function evaluateMainGovernanceRules(rules) {
false,
"Active main rules must be supplied as an array.",
);
return { status: "FAIL", checks, failures };
return {
status: "FAIL",
checks,
failures,
observed_controls: { required_workflows: [] },
};
}

const pullRequestRules = rulesOfType(rules, "pull_request");
Expand Down Expand Up @@ -190,5 +214,8 @@ export function evaluateMainGovernanceRules(rules) {
status: failures.length === 0 ? "PASS" : "FAIL",
checks,
failures,
observed_controls: {
required_workflows: observedWorkflowControls(rules),
},
};
}
3 changes: 3 additions & 0 deletions scripts/main-governance-audit.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ function appendSummary(report) {
`- Status: **${report.status}**`,
`- Active rules: ${report.active_rule_count}`,
`- Ruleset sources: ${report.rule_sources.length}`,
`- Observed required workflows: ${report.observed_controls.required_workflows.length}`,
`- Failures: ${report.failures.length}`,
];
if (report.failures.length > 0) {
Expand All @@ -204,6 +205,7 @@ function buildReport(repository, rules, evaluation) {
active_rule_count: rules.length,
active_rule_types: [...new Set(rules.map((rule) => bound(rule?.type, 100) || "unknown"))].sort(),
rule_sources: collectRuleSources(rules),
observed_controls: evaluation.observed_controls,
checks: evaluation.checks,
failures: evaluation.failures,
limitations: [
Expand Down Expand Up @@ -239,6 +241,7 @@ export function main() {
active_rule_count: 0,
active_rule_types: [],
rule_sources: [],
observed_controls: { required_workflows: [] },
checks: [],
failures: [
{
Expand Down
9 changes: 9 additions & 0 deletions test/main-governance-audit-script.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,15 @@ describe("main governance audit GitHub adapter", () => {
expect(script).not.toContain("JSON.stringify(process.env");
});

it("propagates observed required-workflow evidence into the durable report and summary", () => {
const script = readFileSync("scripts/main-governance-audit.mjs", "utf8");

expect(script).toContain("observed_controls: evaluation.observed_controls");
expect(script).toContain("Observed required workflows");
expect(script).toContain("report.observed_controls.required_workflows.length");
expect(script).toContain('observed_controls: { required_workflows: [] }');
});

it("fails closed when the capability, audit, or collection do not pass", () => {
const script = readFileSync("scripts/main-governance-audit.mjs", "utf8");

Expand Down
104 changes: 104 additions & 0 deletions test/main-governance-observed-workflows.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { describe, expect, it } from "vitest";
import { evaluateMainGovernanceRules } from "../scripts/lib/main-governance-audit.mjs";

describe("observed main governance controls", () => {
it("records an enforced workflow without promoting missing target governance to PASS", () => {
const result = evaluateMainGovernanceRules([
{
type: "workflows",
ruleset_id: 18_794_436,
ruleset_source_type: "Organization",
ruleset_source: "ContextualWisdomLab",
parameters: {
do_not_enforce_on_create: false,
workflows: [
{
repository_id: 1_274_066_402,
path: ".github/workflows/security-scan.yml",
ref: "refs/heads/main",
},
],
},
},
]);

expect(result.status).toBe("FAIL");
expect(result.observed_controls).toEqual({
required_workflows: [
{
repository_id: 1_274_066_402,
path: ".github/workflows/security-scan.yml",
ref: "refs/heads/main",
ruleset_id: 18_794_436,
ruleset_source_type: "Organization",
ruleset_source: "ContextualWisdomLab",
},
],
});
expect(result.failures.map((failure) => failure.code)).toContain("pull_request_rule_missing");
});

it("normalizes malformed workflow entries into bounded unknown evidence instead of inventing authority", () => {
const result = evaluateMainGovernanceRules([
{
type: "workflows",
ruleset_id: 18_794_436,
ruleset_source_type: "Organization",
ruleset_source: "ContextualWisdomLab",
parameters: { workflows: [null, { repository_id: -1, path: "", ref: null }] },
},
]);

expect(result.observed_controls.required_workflows).toEqual([
{
repository_id: null,
path: "unknown",
ref: "unknown",
ruleset_id: 18_794_436,
ruleset_source_type: "Organization",
ruleset_source: "ContextualWisdomLab",
},
{
repository_id: null,
path: "unknown",
ref: "unknown",
ruleset_id: 18_794_436,
ruleset_source_type: "Organization",
ruleset_source: "ContextualWisdomLab",
},
]);
expect(result.status).toBe("FAIL");
});

it("rejects object and array workflow identity fields instead of stringifying them", () => {
const result = evaluateMainGovernanceRules([
{
type: "workflows",
ruleset_id: -1,
ruleset_source_type: { kind: "Organization" },
ruleset_source: ["ContextualWisdomLab"],
parameters: {
workflows: [
{
repository_id: -1,
path: { fake: ".github/workflows/security-scan.yml" },
ref: ["refs/heads/main"],
},
],
},
},
]);

expect(result.observed_controls.required_workflows).toEqual([
{
repository_id: null,
path: "unknown",
ref: "unknown",
ruleset_id: null,
ruleset_source_type: "unknown",
ruleset_source: "unknown",
},
]);
expect(result.status).toBe("FAIL");
});
});
Loading