mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-05-16 05:43:05 +08:00
Add scheduled supply-chain watch workflow
This commit is contained in:
committed by
Affaan Mustafa
parent
6887f2952d
commit
6951b8d5d2
57
.github/workflows/supply-chain-watch.yml
vendored
Normal file
57
.github/workflows/supply-chain-watch.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
name: Supply-Chain Watch
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '17 */6 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
ioc-watch:
|
||||
name: IOC watch
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: '20.x'
|
||||
|
||||
- name: Install dependencies without lifecycle scripts
|
||||
run: npm ci --ignore-scripts
|
||||
|
||||
- name: Verify registry signatures and advisories
|
||||
run: |
|
||||
npm audit signatures
|
||||
npm audit --audit-level=high
|
||||
|
||||
- name: Validate IOC scanner fixtures
|
||||
run: node tests/ci/scan-supply-chain-iocs.test.js
|
||||
|
||||
- name: Generate IOC report
|
||||
run: |
|
||||
mkdir -p artifacts
|
||||
node scripts/ci/scan-supply-chain-iocs.js --json > artifacts/supply-chain-ioc-report.json
|
||||
|
||||
- name: Validate workflow hardening rules
|
||||
run: node scripts/ci/validate-workflow-security.js
|
||||
|
||||
- name: Upload IOC report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: supply-chain-ioc-report
|
||||
path: artifacts/supply-chain-ioc-report.json
|
||||
retention-days: 14
|
||||
@@ -13,7 +13,7 @@ clean checkout.
|
||||
| Issue queue | Current | 0 open issues across checked repos |
|
||||
| Discussions | Current | 58 main-repo discussions; 0 need maintainer touch; 0 answerable discussions missing accepted answers |
|
||||
| Local worktree | Current with caveat | `main...origin/main`; unrelated `?? docs/drafts/` ignored |
|
||||
| Security sweep | Current with follow-up | IOC scan, audits, and package-manager hardening completed |
|
||||
| Security sweep | Current with follow-up | IOC scan, audits, package-manager hardening, and scheduled watch workflow completed |
|
||||
| Linear roadmap | Current with follow-up | `ECC Platform Roadmap`, ITO-44 through ITO-59 |
|
||||
| ECC 2.0 publication | Not complete | Release, npm, plugin, and announcement gates pending |
|
||||
| AgentShield enterprise depth | In progress | AgentShield #86 merged; live IOC loop still pending |
|
||||
@@ -29,7 +29,7 @@ Run these from `everything-claude-code` unless a row says otherwise.
|
||||
| Platform audit | `node scripts/platform-audit.js --json --allow-untracked docs/drafts/` | `ready: true`; open PRs 0/20; open issues 0/20; discussions needing maintainer touch 0; answerable discussions missing accepted answers 0; blocking dirty files 0 |
|
||||
| Discussion audit | `node scripts/discussion-audit.js --json --repo affaan-m/everything-claude-code` | `ready: true`; 58 discussions sampled; 0 need maintainer touch; 0 answerable discussions missing accepted answers |
|
||||
| Main repo status | `git status --short --branch` | `## main...origin/main`; `?? docs/drafts/` remains unrelated |
|
||||
| Main commit | `git rev-parse HEAD` | `c0f8c3bc813360f29e9f2b66bcae7e977cd03327` |
|
||||
| Main commit | `git rev-parse HEAD` | `6887f2952d193cff10b3eb79af7765555d8ca9f5` |
|
||||
| Main repo PRs/issues | GitHub connector and `gh` readback | 0 open PRs; 0 open issues |
|
||||
| AgentShield PRs/issues | GitHub connector and `gh` readback | 0 open PRs; 0 open issues |
|
||||
| ECC Tools PRs/issues | Local `gh pr list` and `gh issue list` | 0 open PRs; 0 open issues |
|
||||
@@ -37,7 +37,8 @@ Run these from `everything-claude-code` unless a row says otherwise.
|
||||
| Supply-chain IOC scan | `node scripts/ci/scan-supply-chain-iocs.js --root <ECC-workspace> --home` | Passed; 1241 files inspected |
|
||||
| IOC unit tests | `node tests/ci/scan-supply-chain-iocs.test.js` | 15/15 passed |
|
||||
| Dead-man switch persistence sweep | Process, LaunchAgent, and known payload filename sweep for Mini Shai-Hulud markers | No matches |
|
||||
| Workflow security gate | `node scripts/ci/validate-workflow-security.js` | Passed; 7 workflow files inspected |
|
||||
| Workflow security gate | `node scripts/ci/validate-workflow-security.js` | Passed; 8 workflow files inspected |
|
||||
| Supply-chain watch workflow | `.github/workflows/supply-chain-watch.yml` | Scheduled every 6 hours; emits `supply-chain-ioc-report.json` |
|
||||
| npm signatures and audit | `npm audit signatures && npm audit --audit-level=moderate` in main, AgentShield, ECC Tools | 0 vulnerabilities in each checked package |
|
||||
|
||||
## Prompt-To-Artifact Checklist
|
||||
@@ -94,9 +95,9 @@ Still-open lanes:
|
||||
should not spend more time closing nonexistent PRs/issues.
|
||||
- The discussion queue is current and repeatable through `discussion:audit`.
|
||||
ITO-59 remains open only for recurring Linear/status synchronization.
|
||||
- The Mini Shai-Hulud/TanStack protection pass is strong enough for current
|
||||
local protection, but ITO-57 remains open until incident response and IOC
|
||||
updates become a durable workflow.
|
||||
- The Mini Shai-Hulud/TanStack protection pass now has a durable scheduled
|
||||
watch workflow. ITO-57 remains open for advisory-source refresh automation
|
||||
and Linear status synchronization.
|
||||
- The release is still blocked by publication, package, plugin, billing, and
|
||||
announcement gates. Passing `platform:audit` alone is not proof that ECC 2.0
|
||||
is publishable.
|
||||
@@ -107,7 +108,7 @@ Still-open lanes:
|
||||
markdown artifact.
|
||||
2. Run `platform:audit` and `discussion:audit` from the final release commit
|
||||
before recording publication evidence.
|
||||
3. Continue ITO-57 by turning emergency hardening into documented incident
|
||||
response and scanner update workflow.
|
||||
3. Continue ITO-57 by adding advisory-source refresh automation and Linear
|
||||
status synchronization for the scheduled supply-chain watch.
|
||||
4. Resume release/publication lanes ITO-45, ITO-46, and ITO-56 only after the
|
||||
readiness dashboard can be refreshed from commands.
|
||||
|
||||
@@ -81,6 +81,21 @@ node tests/run-all.js
|
||||
If a search hit appears only in documentation examples, note it in the release
|
||||
evidence but do not rotate credentials for a docs-only reference.
|
||||
|
||||
## Durable Watch Workflow
|
||||
|
||||
ECC also runs `.github/workflows/supply-chain-watch.yml` every six hours and on
|
||||
manual dispatch. The workflow is read-only, disables checkout credential
|
||||
persistence, installs with `npm ci --ignore-scripts`, verifies npm registry
|
||||
signatures, runs the IOC scanner fixtures, emits
|
||||
`supply-chain-ioc-report.json`, and re-validates GitHub Actions hardening rules.
|
||||
|
||||
Treat a failed scheduled watch as a release blocker until an operator confirms
|
||||
whether the failure is a newly reported advisory, a stale scanner fixture, a
|
||||
registry-signature issue, or a workflow hardening regression. If the scanner
|
||||
needs new indicators, update `scripts/ci/scan-supply-chain-iocs.js`, add fixture
|
||||
coverage in `tests/ci/scan-supply-chain-iocs.test.js`, refresh this runbook, and
|
||||
attach the latest JSON artifact to the release evidence.
|
||||
|
||||
## Immediate Response
|
||||
|
||||
If ECC or a maintainer machine installed a known-bad package version:
|
||||
|
||||
73
tests/ci/supply-chain-watch-workflow.test.js
Normal file
73
tests/ci/supply-chain-watch-workflow.test.js
Normal file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Validate the scheduled supply-chain watch workflow contract.
|
||||
*/
|
||||
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const WORKFLOW_PATH = path.join(
|
||||
__dirname,
|
||||
'..',
|
||||
'..',
|
||||
'.github',
|
||||
'workflows',
|
||||
'supply-chain-watch.yml',
|
||||
);
|
||||
|
||||
function test(name, fn) {
|
||||
try {
|
||||
fn();
|
||||
console.log(` ✓ ${name}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.log(` ✗ ${name}`);
|
||||
console.log(` Error: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function run() {
|
||||
console.log('\n=== Testing supply-chain watch workflow ===\n');
|
||||
|
||||
const source = fs.readFileSync(WORKFLOW_PATH, 'utf8');
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
if (test('runs on schedule and manual dispatch', () => {
|
||||
assert.match(source, /schedule:\r?\n\s+- cron: '17 \*\/6 \* \* \*'/);
|
||||
assert.match(source, /workflow_dispatch:/);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('uses read-only permissions and non-persisting checkout credentials', () => {
|
||||
assert.match(source, /permissions:\r?\n\s+contents: read/);
|
||||
assert.doesNotMatch(source, /^\s+[A-Za-z-]+:\s*write\b/m);
|
||||
assert.match(source, /uses: actions\/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd/);
|
||||
assert.match(source, /persist-credentials: false/);
|
||||
assert.doesNotMatch(source, /id-token:\s*write/);
|
||||
assert.doesNotMatch(source, /actions\/cache@/);
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('installs without lifecycle scripts and verifies registry signatures', () => {
|
||||
assert.match(source, /npm ci --ignore-scripts/);
|
||||
assert.match(source, /npm audit signatures/);
|
||||
assert.match(source, /npm audit --audit-level=high/);
|
||||
})) passed++; else failed++;
|
||||
|
||||
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 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, /retention-days: 14/);
|
||||
})) passed++; else failed++;
|
||||
|
||||
console.log(`\nPassed: ${passed}`);
|
||||
console.log(`Failed: ${failed}`);
|
||||
|
||||
process.exit(failed > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
run();
|
||||
Reference in New Issue
Block a user