Implements 4 additional architectural enforcement mechanisms: ✅ All Command Detection (inst_040) - .claude/hooks/all-command-detector.js ✅ Deployment Structure Validation (inst_025) - scripts/verify-deployment-structure.js ✅ File Permissions Check (inst_020_CONSOLIDATED) - scripts/check-file-permissions.js ✅ Environment Variable Standards (inst_026) - scripts/check-env-var-standards.js 📊 Progress: 22/39 enforced (56%), +4 from wave 2, 17 gaps remaining 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
111 lines
3.2 KiB
JavaScript
Executable file
111 lines
3.2 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
/**
|
|
* Environment Variable Standards Checker - Enforces inst_026
|
|
* Ensures correct environment variable naming (CLAUDE_API_KEY not ANTHROPIC_API_KEY)
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const { execSync } = require('child_process');
|
|
|
|
function checkFile(filePath) {
|
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
const lines = content.split('\n');
|
|
const violations = [];
|
|
|
|
lines.forEach((line, idx) => {
|
|
// Check for ANTHROPIC_API_KEY usage
|
|
// Check for ANTHROPIC_API_KEY usage (skip comments and documentation)
|
|
if (line.includes('ANTHROPIC_API_KEY') && // OK: SELF-CHECK
|
|
!line.trim().startsWith('//') &&
|
|
!line.trim().startsWith('*') &&
|
|
!line.includes('// OK:') &&
|
|
!line.includes('Wrong:') &&
|
|
!line.includes('CLAUDE_API_KEY')) {
|
|
violations.push({
|
|
file: filePath,
|
|
line: idx + 1,
|
|
text: line.trim(),
|
|
type: 'wrong_env_var',
|
|
message: 'Should use CLAUDE_API_KEY instead of ANTHROPIC_API_KEY (inst_026)'
|
|
});
|
|
}
|
|
});
|
|
|
|
return violations;
|
|
}
|
|
|
|
function scanFiles(files) {
|
|
const allViolations = [];
|
|
|
|
files.forEach(file => {
|
|
if (!fs.existsSync(file)) return;
|
|
|
|
const ext = path.extname(file).toLowerCase();
|
|
if (!['.js', '.ts', '.env'].includes(ext)) return;
|
|
|
|
if (file.includes('node_modules')) return;
|
|
|
|
try {
|
|
const violations = checkFile(file);
|
|
allViolations.push(...violations);
|
|
} catch (err) {
|
|
// Skip unreadable files
|
|
}
|
|
});
|
|
|
|
return allViolations;
|
|
}
|
|
|
|
function main() {
|
|
const args = process.argv.slice(2);
|
|
|
|
let files = [];
|
|
if (args.length === 0) {
|
|
// Scan staged git files
|
|
try {
|
|
const staged = execSync('git diff --cached --name-only --diff-filter=ACM', {
|
|
encoding: 'utf8'
|
|
});
|
|
files = staged.trim().split('\n').filter(f => f.length > 0);
|
|
} catch (err) {
|
|
console.log('⚠️ Not in git repository');
|
|
process.exit(0);
|
|
}
|
|
} else {
|
|
files = args;
|
|
}
|
|
|
|
if (files.length === 0) {
|
|
console.log('✅ No files to scan');
|
|
process.exit(0);
|
|
}
|
|
|
|
console.log(`\n🔍 Environment Variable Standards Check (inst_026)\n`);
|
|
|
|
const violations = scanFiles(files);
|
|
|
|
if (violations.length === 0) {
|
|
console.log('✅ Environment variable standards correct\n');
|
|
process.exit(0);
|
|
}
|
|
|
|
console.log(`❌ Found ${violations.length} violation(s):\n`);
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
|
|
|
|
violations.forEach(v => {
|
|
console.log(`🔴 ${v.file}:${v.line}`);
|
|
console.log(` ${v.message}`);
|
|
console.log(` Line: ${v.text.substring(0, 80)}`);
|
|
console.log('');
|
|
});
|
|
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
|
|
console.log('Fix: Replace ANTHROPIC_API_KEY with CLAUDE_API_KEY\n');
|
|
console.log('Correct: process.env.CLAUDE_API_KEY');
|
|
console.log('Wrong: process.env.ANTHROPIC_API_KEY\n'); // OK: EXAMPLE
|
|
|
|
process.exit(1);
|
|
}
|
|
|
|
main();
|