mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-05-16 22:03:05 +08:00
Add supply-chain advisory source refresh
This commit is contained in:
committed by
Affaan Mustafa
parent
2d46c00763
commit
a8e3bcb00f
157
tests/ci/supply-chain-advisory-sources.test.js
Normal file
157
tests/ci/supply-chain-advisory-sources.test.js
Normal file
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Validate the supply-chain advisory source refresh report.
|
||||
*/
|
||||
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const { spawnSync } = require('child_process');
|
||||
|
||||
const SCRIPT_PATH = path.join(
|
||||
__dirname,
|
||||
'..',
|
||||
'..',
|
||||
'scripts',
|
||||
'ci',
|
||||
'supply-chain-advisory-sources.js',
|
||||
);
|
||||
|
||||
const {
|
||||
DEFAULT_ADVISORY_SOURCES,
|
||||
buildAdvisorySourceReport,
|
||||
} = require(SCRIPT_PATH);
|
||||
|
||||
async function test(name, fn) {
|
||||
try {
|
||||
await fn();
|
||||
console.log(` ✓ ${name}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.log(` ✗ ${name}`);
|
||||
console.log(` Error: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function run() {
|
||||
console.log('\n=== Testing supply-chain advisory source refresh ===\n');
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
if (await test('default sources cover the active npm and PyPI campaign', async () => {
|
||||
const ids = DEFAULT_ADVISORY_SOURCES.map(source => source.id);
|
||||
for (const requiredId of [
|
||||
'tanstack-postmortem',
|
||||
'github-ghsa-g7cv-rxg3-hmpx',
|
||||
'stepsecurity-mini-shai-hulud',
|
||||
'openai-tanstack-response',
|
||||
'socket-node-ipc',
|
||||
'cisa-npm-compromise',
|
||||
]) {
|
||||
assert.ok(ids.includes(requiredId), `Missing advisory source ${requiredId}`);
|
||||
}
|
||||
|
||||
const ecosystemCoverage = new Set(DEFAULT_ADVISORY_SOURCES.flatMap(source => source.ecosystems));
|
||||
assert.ok(ecosystemCoverage.has('npm'));
|
||||
assert.ok(ecosystemCoverage.has('PyPI'));
|
||||
assert.ok(ecosystemCoverage.has('AI developer tooling'));
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (await test('offline report emits passing coverage checks and Linear-ready ITO-57 payload', async () => {
|
||||
const report = await buildAdvisorySourceReport({
|
||||
generatedAt: '2026-05-16T00:00:00.000Z',
|
||||
refresh: false,
|
||||
});
|
||||
|
||||
assert.strictEqual(report.schema_version, 'ecc.supply-chain-advisory-sources.v1');
|
||||
assert.strictEqual(report.ready, true);
|
||||
assert.strictEqual(report.refresh.enabled, false);
|
||||
assert.ok(report.sources.length >= 8);
|
||||
assert.ok(report.checks.every(check => check.status === 'pass'));
|
||||
assert.strictEqual(report.linear.status.issueId, 'ITO-57');
|
||||
assert.match(report.linear.status.summary, /advisory sources current/i);
|
||||
assert.match(report.linear.status.remaining, /Linear status/i);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (await test('refresh mode records per-source live check results', async () => {
|
||||
const calls = [];
|
||||
const report = await buildAdvisorySourceReport({
|
||||
generatedAt: '2026-05-16T00:00:00.000Z',
|
||||
refresh: true,
|
||||
fetchSource: async source => {
|
||||
calls.push(source.id);
|
||||
return {
|
||||
ok: true,
|
||||
statusCode: 200,
|
||||
finalUrl: source.url,
|
||||
checkedAt: '2026-05-16T00:00:00.000Z',
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(
|
||||
calls.sort(),
|
||||
DEFAULT_ADVISORY_SOURCES.filter(source => source.refresh !== false).map(source => source.id).sort(),
|
||||
);
|
||||
assert.strictEqual(report.refresh.enabled, true);
|
||||
assert.strictEqual(report.refresh.ok, true);
|
||||
assert.ok(report.sources.every(source => source.refreshStatus.status === 'ok'));
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (await test('refresh errors are captured as evidence without breaking offline source coverage', async () => {
|
||||
const report = await buildAdvisorySourceReport({
|
||||
generatedAt: '2026-05-16T00:00:00.000Z',
|
||||
refresh: true,
|
||||
fetchSource: async source => ({
|
||||
ok: source.id !== 'socket-node-ipc',
|
||||
statusCode: source.id === 'socket-node-ipc' ? 403 : 200,
|
||||
error: source.id === 'socket-node-ipc' ? 'forbidden' : null,
|
||||
finalUrl: source.url,
|
||||
checkedAt: '2026-05-16T00:00:00.000Z',
|
||||
}),
|
||||
});
|
||||
|
||||
const socketSource = report.sources.find(source => source.id === 'socket-node-ipc');
|
||||
assert.strictEqual(report.ready, true);
|
||||
assert.strictEqual(report.refresh.ok, false);
|
||||
assert.strictEqual(socketSource.refreshStatus.status, 'warning');
|
||||
assert.match(socketSource.refreshStatus.error, /forbidden/);
|
||||
assert.ok(report.checks.some(check => check.id === 'advisory-refresh' && check.status === 'warn'));
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (await test('CLI JSON can be written as a scheduled workflow artifact', async () => {
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-advisory-sources-'));
|
||||
const outputPath = path.join(tempDir, 'advisory-sources.json');
|
||||
try {
|
||||
const result = spawnSync('node', [
|
||||
SCRIPT_PATH,
|
||||
'--json',
|
||||
'--generated-at',
|
||||
'2026-05-16T00:00:00.000Z',
|
||||
'--write',
|
||||
outputPath,
|
||||
], {
|
||||
encoding: 'utf8',
|
||||
shell: process.platform === 'win32',
|
||||
});
|
||||
|
||||
assert.strictEqual(result.status, 0, result.stderr);
|
||||
const parsed = JSON.parse(fs.readFileSync(outputPath, 'utf8'));
|
||||
assert.strictEqual(parsed.schema_version, 'ecc.supply-chain-advisory-sources.v1');
|
||||
assert.strictEqual(parsed.ready, true);
|
||||
assert.ok(parsed.linear.status.evidence.length >= 3);
|
||||
} finally {
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
console.log(`\nPassed: ${passed}`);
|
||||
console.log(`Failed: ${failed}`);
|
||||
|
||||
process.exit(failed > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
run();
|
||||
@@ -58,9 +58,13 @@ function run() {
|
||||
if (test('runs IOC fixtures, emits JSON report, and uploads the artifact', () => {
|
||||
assert.match(source, /node tests\/ci\/scan-supply-chain-iocs\.test\.js/);
|
||||
assert.match(source, /node scripts\/ci\/scan-supply-chain-iocs\.js --json > artifacts\/supply-chain-ioc-report\.json/);
|
||||
assert.match(source, /node tests\/ci\/supply-chain-advisory-sources\.test\.js/);
|
||||
assert.match(source, /node scripts\/ci\/supply-chain-advisory-sources\.js --refresh --json > artifacts\/supply-chain-advisory-sources\.json/);
|
||||
assert.match(source, /node scripts\/ci\/validate-workflow-security\.js/);
|
||||
assert.match(source, /uses: actions\/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a/);
|
||||
assert.match(source, /name: supply-chain-ioc-report/);
|
||||
assert.match(source, /artifacts\/supply-chain-ioc-report\.json/);
|
||||
assert.match(source, /artifacts\/supply-chain-advisory-sources\.json/);
|
||||
assert.match(source, /retention-days: 14/);
|
||||
})) passed++; else failed++;
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ function buildExpectedPublishPaths(repoRoot) {
|
||||
"scripts/ecc.js",
|
||||
"scripts/catalog.js",
|
||||
"scripts/ci/scan-supply-chain-iocs.js",
|
||||
"scripts/ci/supply-chain-advisory-sources.js",
|
||||
"scripts/consult.js",
|
||||
"scripts/claw.js",
|
||||
"scripts/discussion-audit.js",
|
||||
@@ -124,6 +125,7 @@ function main() {
|
||||
for (const requiredPath of [
|
||||
"scripts/catalog.js",
|
||||
"scripts/ci/scan-supply-chain-iocs.js",
|
||||
"scripts/ci/supply-chain-advisory-sources.js",
|
||||
"scripts/consult.js",
|
||||
"scripts/discussion-audit.js",
|
||||
"scripts/operator-readiness-dashboard.js",
|
||||
|
||||
@@ -39,7 +39,8 @@ function seedRepo(rootDir, overrides = {}) {
|
||||
'observability:ready': 'node scripts/observability-readiness.js',
|
||||
'operator:dashboard': 'node scripts/operator-readiness-dashboard.js',
|
||||
'platform:audit': 'node scripts/platform-audit.js',
|
||||
'security:ioc-scan': 'node scripts/ci/scan-supply-chain-iocs.js'
|
||||
'security:ioc-scan': 'node scripts/ci/scan-supply-chain-iocs.js',
|
||||
'security:advisory-sources': 'node scripts/ci/supply-chain-advisory-sources.js'
|
||||
}
|
||||
}, null, 2),
|
||||
'scripts/operator-readiness-dashboard.js': 'operator dashboard generator',
|
||||
@@ -74,9 +75,9 @@ function seedRepo(rootDir, overrides = {}) {
|
||||
'docs/stale-pr-salvage-ledger.md': 'Manual review tail',
|
||||
'docs/architecture/progress-sync-contract.md': 'GitHub PRs/issues/discussions Linear project local handoff repo roadmap scripts/work-items.js',
|
||||
'docs/architecture/observability-readiness.md': 'observability-readiness.js',
|
||||
'docs/security/supply-chain-incident-response.md': 'TanStack Mini Shai-Hulud node-ipc scan-supply-chain-iocs.js',
|
||||
'docs/security/supply-chain-incident-response.md': 'TanStack Mini Shai-Hulud node-ipc scan-supply-chain-iocs.js supply-chain-advisory-sources.js',
|
||||
'docs/releases/2.0.0-rc.1/publication-evidence-2026-05-15.md': 'TanStack Mini Shai-Hulud Node IPC follow-up node-ipc IOC scan',
|
||||
'.github/workflows/supply-chain-watch.yml': 'name: Supply-Chain Watch'
|
||||
'.github/workflows/supply-chain-watch.yml': 'name: Supply-Chain Watch supply-chain-advisory-sources.js supply-chain-advisory-sources.json'
|
||||
};
|
||||
|
||||
for (const [relativePath, content] of Object.entries({ ...files, ...overrides })) {
|
||||
|
||||
@@ -35,6 +35,7 @@ function seedRepo(rootDir, overrides = {}) {
|
||||
'operator:dashboard': 'node scripts/operator-readiness-dashboard.js',
|
||||
'observability:ready': 'node scripts/observability-readiness.js',
|
||||
'security:ioc-scan': 'node scripts/ci/scan-supply-chain-iocs.js',
|
||||
'security:advisory-sources': 'node scripts/ci/supply-chain-advisory-sources.js',
|
||||
'harness:audit': 'node scripts/harness-audit.js'
|
||||
}
|
||||
}, null, 2),
|
||||
@@ -55,7 +56,8 @@ function seedRepo(rootDir, overrides = {}) {
|
||||
'TanStack',
|
||||
'Mini Shai-Hulud',
|
||||
'node-ipc',
|
||||
'scan-supply-chain-iocs.js'
|
||||
'scan-supply-chain-iocs.js',
|
||||
'supply-chain-advisory-sources.js'
|
||||
].join('\n'),
|
||||
'docs/releases/2.0.0-rc.1/publication-evidence-2026-05-15.md': [
|
||||
'TanStack',
|
||||
|
||||
Reference in New Issue
Block a user