Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion scripts/workflow-registry-audit.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const REPOSITORY_WORKFLOW_PREFIX = ".github/workflows/";
const EXPECTED_REPOSITORY = "ContextualWisdomLab/noema";
const LOWERCASE_SHA_40 = /^[0-9a-f]{40}$/;
const PERCENT_ENCODING = /%[0-9a-f]{2}/i;
const MAX_DIAGNOSTIC_DETAIL_LENGTH = 2048;
Expand Down Expand Up @@ -252,6 +253,14 @@ function classifyRecord(
*/
export function classifyWorkflowRegistry(input) {
const failures = [];

if (input?.repository !== EXPECTED_REPOSITORY) {
failures.push({
code: "repository_identity_invalid",
detail: `Workflow registry evidence must be bound to exact repository ${EXPECTED_REPOSITORY}.`,
});
}

const trackedWorkflowPathsProblem = workflowPathInventoryFailure(
input?.trackedWorkflowPaths,
"tracked_workflow_paths_invalid",
Expand Down Expand Up @@ -307,12 +316,19 @@ export function classifyWorkflowRegistry(input) {
}

const firstPathById = new Map();
const firstIdByPath = new Map();
for (const record of workflows) {
if (!Number.isSafeInteger(record?.id) || typeof record?.path !== "string") {
continue;
}
const firstPath = firstPathById.get(record.id);
if (firstPath !== undefined && firstPath !== record.path) {
if (firstPath === record.path) {
failures.push({
code: "workflow_record_duplicate",
workflow_id: record.id,
detail: `Workflow registry repeated id ${record.id} for path ${record.path}; duplicate records cannot prove a complete registry snapshot.`,
});
} else if (firstPath !== undefined) {
failures.push({
code: "workflow_id_reused",
workflow_id: record.id,
Expand All @@ -321,6 +337,17 @@ export function classifyWorkflowRegistry(input) {
} else {
firstPathById.set(record.id, record.path);
}

const firstId = firstIdByPath.get(record.path);
if (firstId === undefined) {
firstIdByPath.set(record.path, record.id);
} else if (firstId !== record.id) {
failures.push({
code: "workflow_path_reused",
workflow_id: record.id,
detail: `Workflow path ${record.path} is associated with conflicting ids ${firstId} and ${record.id}.`,
});
}
}

const classified = workflows.map((record) =>
Expand Down Expand Up @@ -395,6 +422,24 @@ function collectionFailure({ repository, observedAt, defaultBranchSha, error })
*/
export async function collectWorkflowRegistryAudit(input) {
const observedAt = input.now();
if (input.repository !== EXPECTED_REPOSITORY) {
return {
schema_version: 1,
repository_full_name: input.repository ?? null,
default_branch_sha: null,
observed_at: observedAt,
pagination_receipts: [],
status: "FAIL",
failures: [
{
code: "repository_identity_invalid",
detail: `Workflow registry evidence must be bound to exact repository ${EXPECTED_REPOSITORY}.`,
},
],
workflows: [],
};
}

let initialBranch;
let workflowPages;
let activePullRequestWorkflowPaths;
Expand Down
13 changes: 9 additions & 4 deletions test/workflow-registry-audit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ describe("workflow registry audit", () => {
);
});

it("allows duplicate observations of the same id/path without inventing reuse", () => {
it("fails closed when the same workflow id/path is repeated", () => {
const duplicate = workflow({ id: 710, path: ".github/workflows/ci.yml" });
const result = classifyWorkflowRegistry({
repository: "ContextualWisdomLab/noema",
Expand All @@ -311,8 +311,13 @@ describe("workflow registry audit", () => {
pagination: completePagination(2),
});

expect(result.status).toBe("PASS");
expect(result.failures).toEqual([]);
expect(result.status).toBe("FAIL");
expect(result.failures).toContainEqual(
expect.objectContaining({
code: "workflow_record_duplicate",
workflow_id: 710,
}),
);
});

it("rejects branch identity that is not exact lowercase 40-hex", () => {
Expand Down Expand Up @@ -452,4 +457,4 @@ describe("workflow registry audit", () => {
NO_COLOR: "1",
});
});
});
});
47 changes: 47 additions & 0 deletions test/workflow-registry-collector-repository-binding.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { describe, expect, it, vi } from "vitest";
import { collectWorkflowRegistryAudit } from "../scripts/workflow-registry-audit.mjs";

describe("workflow registry collector repository binding", () => {
it.each([
"ContextualWisdomLab/other",
"contextualwisdomlab/noema",
" ContextualWisdomLab/noema ",
null,
])("refuses repository %j before any GitHub collection call", async (repository) => {
const resolveDefaultBranch = vi.fn(async () => ({
sha: "1fbe857a5cf52b5af31e2db5e4676876289e3e23",
workflowPaths: [".github/workflows/ci.yml"],
}));
const listWorkflowPage = vi.fn(async () => ({
totalCount: 0,
workflows: [],
hasNext: false,
}));
const listActivePullRequestWorkflowPaths = vi.fn(async () => []);

const result = await collectWorkflowRegistryAudit({
repository,
resolveDefaultBranch,
listWorkflowPage,
listActivePullRequestWorkflowPaths,
now: () => "2026-08-13T15:45:00.000Z",
});

expect(result).toMatchObject({
repository_full_name: repository,
default_branch_sha: null,
status: "FAIL",
failures: [
{
code: "repository_identity_invalid",
detail:
"Workflow registry evidence must be bound to exact repository ContextualWisdomLab/noema.",
},
],
workflows: [],
});
expect(resolveDefaultBranch).not.toHaveBeenCalled();
expect(listWorkflowPage).not.toHaveBeenCalled();
expect(listActivePullRequestWorkflowPaths).not.toHaveBeenCalled();
});
});
60 changes: 60 additions & 0 deletions test/workflow-registry-duplicate-records.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { describe, expect, it } from "vitest";
import { classifyWorkflowRegistry } from "../scripts/workflow-registry-audit.mjs";

describe("workflow registry duplicate record integrity", () => {
it("fails closed when pagination repeats the same workflow identity", () => {
const workflow = {
id: 42,
path: ".github/workflows/ci.yml",
state: "active",
};

const result = classifyWorkflowRegistry({
repository: "ContextualWisdomLab/noema",
defaultBranchSha: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
observedAt: "2026-08-14T00:00:00.000Z",
workflows: [workflow, { ...workflow }],
trackedWorkflowPaths: [workflow.path],
activePullRequestWorkflowPaths: [],
pagination: {
totalCount: 2,
receipts: [{ page: 1, itemCount: 2, hasNext: false }],
},
});

expect(result.status).toBe("FAIL");
expect(result.failures).toContainEqual({
code: "workflow_record_duplicate",
workflow_id: 42,
detail:
"Workflow registry repeated id 42 for path .github/workflows/ci.yml; duplicate records cannot prove a complete registry snapshot.",
});
});

it("fails closed when different workflow identities claim the same repository path", () => {
const workflowPath = ".github/workflows/ci.yml";
const result = classifyWorkflowRegistry({
repository: "ContextualWisdomLab/noema",
defaultBranchSha: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
observedAt: "2026-08-14T00:00:00.000Z",
workflows: [
{ id: 42, path: workflowPath, state: "active" },
{ id: 43, path: workflowPath, state: "active" },
],
trackedWorkflowPaths: [workflowPath],
activePullRequestWorkflowPaths: [],
pagination: {
totalCount: 2,
receipts: [{ page: 1, itemCount: 2, hasNext: false }],
},
});

expect(result.status).toBe("FAIL");
expect(result.failures).toContainEqual({
code: "workflow_path_reused",
workflow_id: 43,
detail:
"Workflow path .github/workflows/ci.yml is associated with conflicting ids 42 and 43.",
});
});
});
32 changes: 32 additions & 0 deletions test/workflow-registry-repository-binding.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { describe, expect, it } from "vitest";
import { classifyWorkflowRegistry } from "../scripts/workflow-registry-audit.mjs";

const validInput = {
defaultBranchSha: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
observedAt: "2026-08-13T15:00:00.000Z",
workflows: [],
trackedWorkflowPaths: [],
activePullRequestWorkflowPaths: [],
pagination: { totalCount: 0, receipts: [] },
};

describe("workflow registry repository binding", () => {
it.each([
"ContextualWisdomLab/other",
"contextualwisdomlab/noema",
" ContextualWisdomLab/noema ",
null,
])(
"rejects evidence bound to %s",
(repository) => {
const result = classifyWorkflowRegistry({ ...validInput, repository });

expect(result.status).toBe("FAIL");
expect(result.failures).toContainEqual({
code: "repository_identity_invalid",
detail:
"Workflow registry evidence must be bound to exact repository ContextualWisdomLab/noema.",
});
},
);
});
Loading