Implements 7 additional architectural enforcement mechanisms: ✅ Prohibited Terms Detection (inst_016/017/018): - scripts/check-prohibited-terms.js - Scans for absolute assurance terms ("guarantee", "100% secure") - Detects maturity claims without evidence ("production-ready", "battle-tested") - Checks statistics require citation or [NEEDS VERIFICATION] - Integrated into .git/hooks/pre-commit (Check 2) ✅ Credential Exposure Prevention (inst_069/070): - scripts/check-credential-exposure.js - Detects real API keys, secrets, passwords in documentation - Validates example credentials use proper patterns (EXAMPLE/REDACTED) - CRITICAL: Runs first in pre-commit (Check 0) ✅ Confidential Document Protection (inst_012/015): - scripts/check-confidential-docs.js - Prevents deployment of internal/session-handoff documents - Scans filenames and content for [CONFIDENTIAL]/[INTERNAL] markers - Integrated into scripts/deploy.sh pre-flight checks ✅ Enhanced Pre-Commit Hook: Now runs 4 checks in order: 0. Credential exposure (CRITICAL) 1. CSP compliance 2. Prohibited terms 3. Test requirements ✅ Enhanced Deployment Script: - Added confidential document check to deploy.sh - Scans public/ and docs/ before deployment - Blocks deployment if confidential markers found ✅ Updated Enforcement Map: - Added all new mechanisms to audit-enforcement.js - Updated inst_008_CONSOLIDATED mapping - New mappings: inst_012, inst_015, inst_016, inst_017, inst_018, inst_069, inst_070 📊 Enforcement Progress: - Wave 1: 11/39 imperative instructions enforced (28%) - Wave 2: 18/39 imperative instructions enforced (46%) - Improvement: +7 instructions = +64% increase - Remaining gaps: 21/39 (54%) 🎯 Next Priority Gaps: - inst_013/043/045: API security validation - inst_019: Context pressure comprehensive accounting - inst_025: Deployment file mapping - inst_039/040: Batch operation verification - inst_079/080/081: Values/principles (process-based) 🔒 Security Posture: - CRITICAL security checks now run first (credential exposure) - All text files scanned before commit - All deployment candidates scanned before rsync 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
167 lines
5 KiB
JavaScript
Executable file
167 lines
5 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
/**
|
|
* Prohibited Terms Scanner - Enforces inst_016, inst_017, inst_018
|
|
*
|
|
* Scans files for prohibited language that violates governance rules
|
|
*/
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const { execSync } = require('child_process');
|
|
|
|
// inst_017: Prohibited absolute assurance terms
|
|
const PROHIBITED_ABSOLUTE_TERMS = [
|
|
/\bguarantee(s|d)?\b/i,
|
|
/\bensures?\s+(100%|complete|total|absolute)/i,
|
|
/\beliminates?\s+all\b/i,
|
|
/\bcompletely\s+(prevents?|eliminates?|removes?)\b/i,
|
|
/\bnever\s+fails?\b/i,
|
|
/\b100%\s+(safe|secure|reliable|accurate)\b/i,
|
|
/\babsolutely\s+(prevents?|guarantees?)\b/i
|
|
];
|
|
|
|
// inst_018: Prohibited maturity claims without evidence
|
|
const PROHIBITED_MATURITY_CLAIMS = [
|
|
/\b(production-ready|battle-tested|enterprise-proven)\b/i,
|
|
/\bvalidated\s+by\s+\d+\s+(companies|organizations|teams)\b/i,
|
|
/\bwidely\s+adopted\b/i,
|
|
/\bmarket\s+(leader|validated)\b/i,
|
|
/\bcustomer\s+base\s+of\b/i
|
|
];
|
|
|
|
// inst_016: Requires citation or [NEEDS VERIFICATION]
|
|
const STATS_PATTERNS = [
|
|
/\d+%\s+(improvement|increase|reduction|faster|better)/i,
|
|
/\d+x\s+(faster|better|more)/i,
|
|
/ROI\s+of\s+\d+/i,
|
|
/reduces?\s+(cost|time|effort)\s+by\s+\d+/i
|
|
];
|
|
|
|
function checkFile(filePath) {
|
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
const lines = content.split('\n');
|
|
const violations = [];
|
|
|
|
lines.forEach((line, idx) => {
|
|
const lineNum = idx + 1;
|
|
|
|
// Check inst_017: Absolute assurance terms
|
|
PROHIBITED_ABSOLUTE_TERMS.forEach(pattern => {
|
|
if (pattern.test(line)) {
|
|
violations.push({
|
|
file: filePath,
|
|
line: lineNum,
|
|
type: 'inst_017',
|
|
severity: 'HIGH',
|
|
text: line.trim(),
|
|
rule: 'Prohibited absolute assurance term detected'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Check inst_018: Maturity claims
|
|
PROHIBITED_MATURITY_CLAIMS.forEach(pattern => {
|
|
if (pattern.test(line)) {
|
|
violations.push({
|
|
file: filePath,
|
|
line: lineNum,
|
|
type: 'inst_018',
|
|
severity: 'HIGH',
|
|
text: line.trim(),
|
|
rule: 'Prohibited maturity claim without evidence'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Check inst_016: Statistics without citation
|
|
STATS_PATTERNS.forEach(pattern => {
|
|
if (pattern.test(line)) {
|
|
// Check if line has citation or [NEEDS VERIFICATION]
|
|
if (!line.includes('[') && !line.includes('(source:') && !line.includes('Citation:')) {
|
|
violations.push({
|
|
file: filePath,
|
|
line: lineNum,
|
|
type: 'inst_016',
|
|
severity: 'MEDIUM',
|
|
text: line.trim(),
|
|
rule: 'Statistic without citation or [NEEDS VERIFICATION] marker'
|
|
});
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
return violations;
|
|
}
|
|
|
|
function scanFiles(files) {
|
|
const allViolations = [];
|
|
|
|
files.forEach(file => {
|
|
if (!fs.existsSync(file)) return;
|
|
|
|
// Only scan text files (markdown, HTML, text)
|
|
const ext = path.extname(file).toLowerCase();
|
|
if (!['.md', '.html', '.txt', '.json'].includes(ext)) return;
|
|
|
|
const violations = checkFile(file);
|
|
allViolations.push(...violations);
|
|
});
|
|
|
|
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.error('Not in a git repository or no staged files');
|
|
process.exit(0);
|
|
}
|
|
} else {
|
|
files = args;
|
|
}
|
|
|
|
if (files.length === 0) {
|
|
console.log('✅ No files to scan');
|
|
process.exit(0);
|
|
}
|
|
|
|
console.log(`\n🔍 Scanning ${files.length} file(s) for prohibited terms...\n`);
|
|
|
|
const violations = scanFiles(files);
|
|
|
|
if (violations.length === 0) {
|
|
console.log('✅ No prohibited terms detected\n');
|
|
process.exit(0);
|
|
}
|
|
|
|
// Report violations
|
|
console.log(`❌ Found ${violations.length} violation(s):\n`);
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
|
|
|
|
violations.forEach(v => {
|
|
console.log(`${v.severity === 'HIGH' ? '🔴' : '🟡'} ${v.file}:${v.line}`);
|
|
console.log(` Rule: ${v.type} - ${v.rule}`);
|
|
console.log(` Text: ${v.text.substring(0, 80)}${v.text.length > 80 ? '...' : ''}`);
|
|
console.log('');
|
|
});
|
|
|
|
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
|
|
console.log('Fix violations before committing/deploying:\n');
|
|
console.log(' inst_016: Add citation or [NEEDS VERIFICATION] to statistics');
|
|
console.log(' inst_017: Replace absolute terms with evidence-based language');
|
|
console.log(' inst_018: Remove maturity claims or add documented evidence\n');
|
|
|
|
process.exit(1);
|
|
}
|
|
|
|
main();
|