tractatus/scripts/check-confidential-docs.js
TheFlow e7efdc7810 feat(governance): second wave enforcement - 64% improvement (28% → 46%)
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>
2025-10-25 13:26:33 +13:00

153 lines
4.1 KiB
JavaScript
Executable file

#!/usr/bin/env node
/**
* Confidential Document Scanner - Enforces inst_012, inst_015
* Prevents deployment of internal/confidential documents
*/
const fs = require('fs');
const path = require('path');
// File patterns that indicate confidential/internal documents
const CONFIDENTIAL_PATTERNS = [
/session[-_]?handoff/i,
/phase[-_]?planning/i,
/cost[-_]?estimate/i,
/infrastructure[-_]?plan/i,
/progress[-_]?report/i,
/cover[-_]?letter/i,
/testing[-_]?checklist/i,
/internal/i,
/confidential/i,
/private/i,
/draft/i,
/wip[-_]/i, // work in progress
/todo/i
];
// Content markers that indicate confidential information
const CONFIDENTIAL_CONTENT_MARKERS = [
/\[INTERNAL\]/i,
/\[CONFIDENTIAL\]/i,
/\[DRAFT\]/i,
/\[DO NOT PUBLISH\]/i,
/\[WIP\]/i,
/CONFIDENTIAL:/i,
/INTERNAL ONLY:/i
];
function checkFilePath(filePath) {
const basename = path.basename(filePath);
for (const pattern of CONFIDENTIAL_PATTERNS) {
if (pattern.test(basename) || pattern.test(filePath)) {
return {
confidential: true,
reason: `Filename matches confidential pattern: ${pattern.source}`
};
}
}
return { confidential: false };
}
function checkFileContent(filePath) {
try {
const content = fs.readFileSync(filePath, 'utf8');
const lines = content.split('\n');
for (let i = 0; i < Math.min(20, lines.length); i++) {
for (const marker of CONFIDENTIAL_CONTENT_MARKERS) {
if (marker.test(lines[i])) {
return {
confidential: true,
reason: `Content contains confidential marker at line ${i+1}: ${marker.source}`,
line: i + 1,
text: lines[i].trim()
};
}
}
}
return { confidential: false };
} catch (err) {
// Can't read file (binary, etc.) - check by path only
return { confidential: false };
}
}
function scanFile(filePath) {
// Skip non-document files
const ext = path.extname(filePath).toLowerCase();
if (!['.md', '.txt', '.pdf', '.doc', '.docx', '.html'].includes(ext)) {
return null;
}
// Check filename
const pathCheck = checkFilePath(filePath);
if (pathCheck.confidential) {
return { file: filePath, ...pathCheck };
}
// Check content
const contentCheck = checkFileContent(filePath);
if (contentCheck.confidential) {
return { file: filePath, ...contentCheck };
}
return null;
}
function main() {
const args = process.argv.slice(2);
if (args.length === 0) {
console.log('Usage: check-confidential-docs.js <file1> [file2] ...');
console.log('');
console.log('Scans files to prevent deployment of internal/confidential documents');
process.exit(0);
}
console.log(`\n🔍 Scanning ${args.length} file(s) for confidential markers...\n`);
const findings = [];
args.forEach(file => {
if (!fs.existsSync(file)) return;
const result = scanFile(file);
if (result) {
findings.push(result);
}
});
if (findings.length === 0) {
console.log('✅ No confidential documents detected\n');
process.exit(0);
}
// Report findings
console.log(`❌ Found ${findings.length} confidential document(s):\n`);
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
findings.forEach(f => {
console.log(`🔴 ${f.file}`);
console.log(` Reason: ${f.reason}`);
if (f.text) {
console.log(` Line ${f.line}: ${f.text.substring(0, 60)}...`);
}
console.log('');
});
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
console.log('⚠️ DEPLOYMENT BLOCKED (inst_012/inst_015)\n');
console.log('These documents are marked confidential/internal.');
console.log('');
console.log('Actions:');
console.log(' 1. Remove confidential markers if approved for public release');
console.log(' 2. Move to a non-public directory');
console.log(' 3. Get explicit human approval before deploying\n');
process.exit(1);
}
main();