tractatus/scripts/check-env-var-standards.js
TheFlow 35348e3a8e feat(governance): third wave enforcement - 22% improvement (46% → 56%)
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>
2025-10-25 13:38:18 +13:00

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();