Files
wehub-resource-sync 23f7624596
ADR-166 MCP Bridge Security Lock / Static-source security lock (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / Compose default binds loopback + Mongo has auth (push) Failing after 2s
CodeQL Advanced / Analyze (rust) (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / plugin-agent-federation bindHost default (push) Failing after 1s
ADR-166 MCP Bridge Security Lock / Runtime behavior — 401 + terminal gate + fail-closed (push) Failing after 4s
business-pods-smoke / smoke (push) Failing after 1s
all-plugins-smoke / smoke-all (push) Failing after 2s
CI/CD Pipeline / Security & Code Quality (push) Failing after 1s
CI/CD Pipeline / Test Suite (ubuntu-latest) (push) Failing after 1s
CI/CD Pipeline / Build & Package (macos-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (ubuntu-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (windows-latest) (push) Has been skipped
CI/CD Pipeline / Documentation & Examples (push) Failing after 1s
Clone Tracker (14-day rolling) / Snapshot clones for ruflo ecosystem (push) Failing after 1s
CodeQL Advanced / Analyze (actions) (push) Failing after 1s
CodeQL Advanced / Analyze (javascript-typescript) (push) Failing after 1s
federation-peer-rust / stable-noop (push) Failing after 1s
metaharness-ci / score (push) Failing after 1s
metaharness-ci / router-compat (push) Failing after 0s
metaharness-ci / similarity-tests (push) Failing after 0s
no-agentbbs-smoke / smoke-without-agentbbs (push) Failing after 1s
V3 CI/CD Pipeline / Build V3 (windows-latest) (push) Has been skipped
codex-integration-audit / Codex integration audit (push) Failing after 1s
helpers-manifest-guard / guard (push) Failing after 1s
🔗 Cross-Agent Integration Tests / 🤝 Agent Coordination Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🧠 Memory Sharing Integration (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🛡️ Fault Tolerance Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / ⚡ Performance Integration Tests (push) Has been skipped
metaharness-ci / mcp-scan (push) Failing after 1s
metaharness-ci / eject-dryrun (push) Failing after 1s
metaharness-ci / metaharness-real-data (push) Failing after 0s
no-cli-optdep-bloat-2561 / guard (push) Failing after 1s
no-metaharness-smoke / smoke-without-metaharness (push) Failing after 1s
no-phantom-agentic-flow-subpath / guard (push) Failing after 1s
🔄 Automated Rollback Manager / 🚨 Failure Detection (push) Failing after 1s
V3 CI/CD Pipeline / Plugin hooks smoke / ubuntu-latest / Node 22 (push) Failing after 1s
V3 CI/CD Pipeline / ruflo-graph-intelligence build + test smoke (#2044, ADR-123) (push) Failing after 1s
CVE Audit Gate / Audit root (critical-blocking) (push) Failing after 2s
cost-tracker-smoke / smoke (push) Failing after 3s
oia-audit-weekly / audit (push) Failing after 2s
ruflo-agent-smoke / ruflo-agent structural smoke (push) Failing after 1s
📊 Status Badges Update / 📊 Update Status Badges (push) Failing after 1s
V3 CI/CD Pipeline / Static regression guards (#2267 YAML + (push) Failing after 1s
V3 CI/CD Pipeline / Test V3 Packages (push) Failing after 0s
V3 CI/CD Pipeline / agent_execute provider routing smoke (#2042) (push) Failing after 0s
CVE Audit Gate / Audit v3 (critical-blocking) (push) Failing after 1s
federation-peer-rust / stable-native (push) Failing after 2s
🔗 Cross-Agent Integration Tests / 🚀 Integration Test Setup (push) Failing after 2s
neural-trader-smoke / runtime-smoke (push) Failing after 1s
V3 CI/CD Pipeline / Build V3 (macos-latest) (push) Has been skipped
V3 CI/CD Pipeline / Build V3 (ubuntu-latest) (push) Has been skipped
V3 CI/CD Pipeline / Type Check V3 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 24 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 22 (push) Failing after 2s
V3 CI/CD Pipeline / browser rvf create flag smoke (#2015) (push) Failing after 0s
V3 CI/CD Pipeline / Dependency review (#2046) (push) Has been skipped
V3 CI/CD Pipeline / Supply-chain audit (#2046) (push) Failing after 0s
V3 CI/CD Pipeline / witness marker drift smoke (#2021) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader portfolio CG smoke (#2068, ADR-126 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader backtest signing smoke (#2068, ADR-126 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / kg-extract type-import classification smoke (#2049) (push) Failing after 0s
V3 CI/CD Pipeline / witness verify precondition smoke (#1880) (push) Failing after 2s
V3 CI/CD Pipeline / neural-trader pipeline risk-gate smoke (#2068, ADR-126 Phase 5) (push) Failing after 0s
V3 CI/CD Pipeline / neural-trader feature attribution smoke (#2068, ADR-126 Phase 6) (push) Failing after 0s
V3 CI/CD Pipeline / plugin-registry signature verification smoke (#1922, CWE-347) (push) Failing after 4s
V3 CI/CD Pipeline / memory stats legacy-DB smoke (#2120) (push) Failing after 4s
V3 CI/CD Pipeline / github deprecated actions smoke (#2089, ADR-127 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / graph query + pathfinder smoke (ADR-130 P2+P5) (push) Has been skipped
V3 CI/CD Pipeline / graph trajectory hooks smoke (ADR-130 P3) (push) Has been skipped
V3 CI/CD Pipeline / graph plugin adapter smoke (ADR-130 P4) (push) Has been skipped
V3 CI/CD Pipeline / graph benchmark (ADR-130 P6) (push) Has been skipped
V3 CI/CD Pipeline / statusline generator delegation smoke (#2195) (push) Failing after 1s
V3 CI/CD Pipeline / wizard init regression guard (#2206 (push) Failing after 1s
V3 CI/CD Pipeline / memory no-stray-db smoke (ADR-125 P7) (push) Failing after 1s
V3 CI/CD Pipeline / github-safe injection smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github actions pin smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github attribution opt-in smoke (#2089, ADR-127 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / pre-bash hook safety smoke (#2017) (push) Failing after 1s
V3 CI/CD Pipeline / Memory import smoke / ubuntu-latest (push) Failing after 0s
V3 CI/CD Pipeline / MCP protocol smoke / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / ruvllm WASM auto-init smoke (#2086) (push) Failing after 4s
V3 CI/CD Pipeline / MCP paired-tool round-trip smoke (#1889) (push) Failing after 1s
V3 CI/CD Pipeline / Plugin package install-safety (#1902/#1903/#1904) (push) Failing after 1s
V3 CI/CD Pipeline / Tool description discoverability (ADR-112) (push) Failing after 3s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (22) (push) Failing after 1s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (24) (push) Failing after 1s
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Vector-index dimension audit (#1947) (push) Failing after 0s
V3 CI/CD Pipeline / Hook-command install safety (#1921) (push) Failing after 1s
V3 CI/CD Pipeline / ToolOutputGuardrail smoke (ADR-131, (push) Failing after 1s
V3 CI/CD Pipeline / init-bundle invariants smoke (#2095, ADR-128 Phase 5) (push) Failing after 1s
V3 CI/CD Pipeline / wasm provider bridge smoke (ADR-129 P1) (push) Failing after 2s
V3 CI/CD Pipeline / wasm gallery CRUD smoke (ADR-129 P3) (push) Failing after 1s
V3 CI/CD Pipeline / wasm plugin bridge smoke (ADR-129 P4) (push) Failing after 0s
V3 CI/CD Pipeline / wasm compose smoke (ADR-129 P2) (push) Failing after 4s
V3 CI/CD Pipeline / graph schema smoke (ADR-130 P1) (push) Failing after 0s
Validate Marketplace / validate (push) Failing after 1s
🔍 Verification Pipeline / 🚀 Setup Verification (push) Failing after 1s
🔍 Verification Pipeline / 🛡️ Security Verification (push) Has been skipped
🔍 Verification Pipeline / 📝 Code Quality (push) Has been skipped
🔍 Verification Pipeline / 🧪 Test Verification (${{ matrix.os }}, Node ${{ matrix.node }}) (push) Has been skipped
🔍 Verification Pipeline / 🏗️ Build Verification (push) Has been skipped
🔍 Verification Pipeline / 📚 Documentation Verification (push) Has been skipped
CVE Audit Gate / High-severity report (warn only) (push) Has been cancelled
🔄 Automated Rollback Manager / 🔄 Execute Rollback (push) Has been cancelled
🔄 Automated Rollback Manager / ✅ Post-Rollback Verification (push) Has been cancelled
🔄 Automated Rollback Manager / 📊 Rollback Monitoring (push) Has been cancelled
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / windows-latest (push) Has been cancelled
🔄 Automated Rollback Manager / ⏳ Manual Rollback Approval (push) Has been cancelled
V3 CI/CD Pipeline / MCP protocol smoke / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Memory import smoke / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / ubuntu-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Publish to npm (alpha) (push) Has been cancelled
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / macos-latest / Node 22 (push) Has been cancelled
V3 CI/CD Pipeline / Plugin hooks smoke / macos-latest / Node 22 (push) Has been cancelled
CI/CD Pipeline / Deploy & Release (push) Has been cancelled
CI/CD Pipeline / CI Status (push) Has been cancelled
🔗 Cross-Agent Integration Tests / 📊 Integration Test Report (push) Has been cancelled
🔄 Automated Rollback Manager / 🔍 Pre-Rollback Validation (push) Has been cancelled
🔍 Verification Pipeline / ⚡ Performance Verification (push) Has been cancelled
🔍 Verification Pipeline / 📊 Verification Report (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:02:19 +08:00

346 lines
9.9 KiB
TypeScript

#!/usr/bin/env npx tsx
/**
* Plugin Registry Publisher
*
* Publishes the plugin registry to IPFS via Pinata and updates IPNS pointer.
*
* Setup:
* 1. Create Pinata account at https://pinata.cloud
* 2. Generate API keys (JWT)
* 3. Set environment variables:
* - PINATA_JWT: Your Pinata JWT token
* - REGISTRY_PRIVATE_KEY: Ed25519 private key (hex) for signing
*
* Usage:
* npx tsx scripts/publish-registry.ts
* npx tsx scripts/publish-registry.ts --dry-run
* npx tsx scripts/publish-registry.ts --registry ./custom-registry.json
*/
import * as fs from 'fs';
import * as path from 'path';
import * as crypto from 'crypto';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Types
interface PluginEntry {
id: string;
name: string;
displayName: string;
description: string;
version: string;
cid?: string;
size: number;
checksum: string;
author: {
id: string;
displayName: string;
verified: boolean;
};
license: string;
categories: string[];
tags: string[];
downloads: number;
rating: number;
lastUpdated: string;
minClaudeFlowVersion: string;
type: string;
hooks: string[];
commands: string[];
permissions: string[];
exports: string[];
verified: boolean;
trustLevel: string;
}
interface PluginRegistry {
version: string;
type: 'plugins';
updatedAt: string;
ipnsName: string;
plugins: PluginEntry[];
categories: Array<{ id: string; name: string; description: string; pluginCount: number }>;
totalPlugins: number;
totalDownloads: number;
featured: string[];
trending: string[];
newest: string[];
official: string[];
registrySignature?: string;
registryPublicKey?: string;
}
interface PinataResponse {
IpfsHash: string;
PinSize: number;
Timestamp: string;
}
// Configuration
const PINATA_API_URL = 'https://api.pinata.cloud';
const DEFAULT_REGISTRY_PATH = path.join(__dirname, '../src/plugins/store/registry.json');
// Parse command line arguments
const args = process.argv.slice(2);
const isDryRun = args.includes('--dry-run');
const registryPathArg = args.find(a => a.startsWith('--registry='));
const registryPath = registryPathArg
? registryPathArg.split('=')[1]
: DEFAULT_REGISTRY_PATH;
/**
* Fetch npm stats for a package
*/
async function fetchNpmStats(packageName: string): Promise<{ downloads: number; version: string } | null> {
try {
const downloadsUrl = `https://api.npmjs.org/downloads/point/last-week/${encodeURIComponent(packageName)}`;
const downloadsRes = await fetch(downloadsUrl, { signal: AbortSignal.timeout(5000) });
if (!downloadsRes.ok) return null;
const downloadsData = await downloadsRes.json() as { downloads?: number };
const packageUrl = `https://registry.npmjs.org/${encodeURIComponent(packageName)}/latest`;
const packageRes = await fetch(packageUrl, { signal: AbortSignal.timeout(5000) });
let version = 'unknown';
if (packageRes.ok) {
const packageData = await packageRes.json() as { version?: string };
version = packageData.version || 'unknown';
}
return {
downloads: downloadsData.downloads || 0,
version,
};
} catch {
return null;
}
}
/**
* Sign registry with Ed25519
*/
async function signRegistry(registry: PluginRegistry, privateKeyHex: string): Promise<{
signature: string;
publicKey: string;
}> {
const ed = await import('@noble/ed25519');
const privateKey = Buffer.from(privateKeyHex, 'hex');
const publicKey = await ed.getPublicKeyAsync(privateKey);
// Create a copy without signature fields for signing
const registryToSign = { ...registry };
delete registryToSign.registrySignature;
delete registryToSign.registryPublicKey;
const message = JSON.stringify(registryToSign);
const signature = await ed.signAsync(
new TextEncoder().encode(message),
privateKey
);
return {
signature: Buffer.from(signature).toString('hex'),
publicKey: `ed25519:${Buffer.from(publicKey).toString('hex')}`,
};
}
/**
* Pin JSON to IPFS via Pinata
*/
async function pinToIPFS(data: unknown, name: string, jwt: string): Promise<PinataResponse> {
const response = await fetch(`${PINATA_API_URL}/pinning/pinJSONToIPFS`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${jwt}`,
},
body: JSON.stringify({
pinataContent: data,
pinataMetadata: {
name,
keyvalues: {
type: 'plugin-registry',
publishedAt: new Date().toISOString(),
},
},
pinataOptions: {
cidVersion: 1,
},
}),
});
if (!response.ok) {
const error = await response.text();
throw new Error(`Pinata error: ${response.status} - ${error}`);
}
return response.json() as Promise<PinataResponse>;
}
/**
* Generate a demo registry from npm packages
*/
async function generateRegistry(): Promise<PluginRegistry> {
console.log('📦 Fetching npm stats for plugins...');
const officialPackages = [
'@claude-flow/plugin-agentic-qe',
'@claude-flow/plugin-prime-radiant',
'@claude-flow/plugin-gastown-bridge',
'@claude-flow/security',
'@claude-flow/claims',
'@claude-flow/embeddings',
'@claude-flow/neural',
'@claude-flow/performance',
'@claude-flow/plugins',
];
const plugins: PluginEntry[] = [];
const now = new Date().toISOString();
for (const pkg of officialPackages) {
console.log(` Fetching ${pkg}...`);
const stats = await fetchNpmStats(pkg);
plugins.push({
id: pkg,
name: pkg,
displayName: pkg.replace('@claude-flow/plugin-', '').replace('@claude-flow/', ''),
description: `Official Claude Flow plugin: ${pkg}`,
version: stats?.version || '0.0.0',
size: 100000,
checksum: `sha256:${crypto.randomBytes(32).toString('hex')}`,
author: {
id: 'claude-flow-team',
displayName: 'Claude Flow Team',
verified: true,
},
license: 'MIT',
categories: ['official'],
tags: [pkg.split('/').pop() || ''],
downloads: stats?.downloads || 0,
rating: 0,
lastUpdated: now,
minClaudeFlowVersion: '3.0.0',
type: 'integration',
hooks: [],
commands: [],
permissions: ['memory', 'filesystem'],
exports: [],
verified: true,
trustLevel: 'official',
});
}
const totalDownloads = plugins.reduce((sum, p) => sum + p.downloads, 0);
return {
version: '1.0.0',
type: 'plugins',
updatedAt: now,
ipnsName: '', // Will be set after publishing
plugins,
categories: [
{ id: 'official', name: 'Official', description: 'Official Claude Flow plugins', pluginCount: plugins.length },
],
totalPlugins: plugins.length,
totalDownloads,
featured: plugins.slice(0, 3).map(p => p.id),
trending: plugins.sort((a, b) => b.downloads - a.downloads).slice(0, 3).map(p => p.id),
newest: plugins.slice(-3).map(p => p.id),
official: plugins.map(p => p.id),
};
}
/**
* Main publish function
*/
async function main() {
console.log('🚀 Plugin Registry Publisher\n');
// Check environment
const jwt = process.env.PINATA_JWT;
const privateKey = process.env.REGISTRY_PRIVATE_KEY;
if (!jwt) {
console.error('❌ PINATA_JWT environment variable is required');
console.log('\nGet your JWT from https://pinata.cloud/keys');
process.exit(1);
}
// Load or generate registry
let registry: PluginRegistry;
if (fs.existsSync(registryPath)) {
console.log(`📄 Loading registry from ${registryPath}`);
const content = fs.readFileSync(registryPath, 'utf-8');
registry = JSON.parse(content);
} else {
console.log('📄 Generating registry from npm packages...');
registry = await generateRegistry();
}
// Update timestamp
registry.updatedAt = new Date().toISOString();
console.log(`\n📊 Registry Stats:`);
console.log(` Plugins: ${registry.plugins.length}`);
console.log(` Total Downloads: ${registry.totalDownloads.toLocaleString()}`);
console.log(` Updated: ${registry.updatedAt}`);
// Sign registry if private key is available
if (privateKey) {
console.log('\n🔐 Signing registry with Ed25519...');
const { signature, publicKey } = await signRegistry(registry, privateKey);
registry.registrySignature = signature;
registry.registryPublicKey = publicKey;
console.log(` Public Key: ${publicKey.slice(0, 30)}...`);
} else {
console.log('\n⚠️ No REGISTRY_PRIVATE_KEY set, skipping signature');
}
if (isDryRun) {
console.log('\n🔍 Dry run - would publish:');
console.log(JSON.stringify(registry, null, 2).slice(0, 1000) + '...');
return;
}
// Pin to IPFS
console.log('\n📌 Pinning to IPFS via Pinata...');
try {
const result = await pinToIPFS(registry, 'claude-flow-plugin-registry', jwt);
console.log('\n✅ Published successfully!');
console.log(` CID: ${result.IpfsHash}`);
console.log(` Size: ${(result.PinSize / 1024).toFixed(2)} KB`);
console.log(`\n🌐 Gateway URLs:`);
console.log(` https://gateway.pinata.cloud/ipfs/${result.IpfsHash}`);
console.log(` https://ipfs.io/ipfs/${result.IpfsHash}`);
console.log(` https://cloudflare-ipfs.com/ipfs/${result.IpfsHash}`);
console.log(` https://dweb.link/ipfs/${result.IpfsHash}`);
// Save CID for reference
const cidFile = path.join(__dirname, '../.registry-cid');
fs.writeFileSync(cidFile, result.IpfsHash);
console.log(`\n💾 CID saved to ${cidFile}`);
// Update discovery.ts config (manual step reminder)
console.log('\n📝 Next steps:');
console.log(' 1. Update DEFAULT_PLUGIN_STORE_CONFIG in discovery.ts with the new CID');
console.log(' 2. If using IPNS, update the IPNS pointer via Pinata dashboard');
console.log(' 3. Test with: npx claude-flow@latest plugins list');
} catch (error) {
console.error('\n❌ Publish failed:', error);
process.exit(1);
}
}
// Run
main().catch(console.error);