@hatem427/code-guard-ci 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.husky/pre-commit +27 -0
- package/LICENSE +21 -0
- package/README.md +646 -0
- package/config/angular.config.ts +223 -0
- package/config/guidelines.config.ts +229 -0
- package/config/nextjs.config.ts +160 -0
- package/config/react.config.ts +330 -0
- package/dist/config/angular.config.d.ts +15 -0
- package/dist/config/angular.config.d.ts.map +1 -0
- package/dist/config/angular.config.js +187 -0
- package/dist/config/angular.config.js.map +1 -0
- package/dist/config/guidelines.config.d.ts +63 -0
- package/dist/config/guidelines.config.d.ts.map +1 -0
- package/dist/config/guidelines.config.js +167 -0
- package/dist/config/guidelines.config.js.map +1 -0
- package/dist/config/nextjs.config.d.ts +18 -0
- package/dist/config/nextjs.config.d.ts.map +1 -0
- package/dist/config/nextjs.config.js +133 -0
- package/dist/config/nextjs.config.js.map +1 -0
- package/dist/config/react.config.d.ts +15 -0
- package/dist/config/react.config.d.ts.map +1 -0
- package/dist/config/react.config.js +287 -0
- package/dist/config/react.config.js.map +1 -0
- package/dist/scripts/auto-fix.d.ts +16 -0
- package/dist/scripts/auto-fix.d.ts.map +1 -0
- package/dist/scripts/auto-fix.js +130 -0
- package/dist/scripts/auto-fix.js.map +1 -0
- package/dist/scripts/cli.d.ts +17 -0
- package/dist/scripts/cli.d.ts.map +1 -0
- package/dist/scripts/cli.js +255 -0
- package/dist/scripts/cli.js.map +1 -0
- package/dist/scripts/delete-bypass-logs.d.ts +17 -0
- package/dist/scripts/delete-bypass-logs.d.ts.map +1 -0
- package/dist/scripts/delete-bypass-logs.js +242 -0
- package/dist/scripts/delete-bypass-logs.js.map +1 -0
- package/dist/scripts/generate-doc.d.ts +18 -0
- package/dist/scripts/generate-doc.d.ts.map +1 -0
- package/dist/scripts/generate-doc.js +300 -0
- package/dist/scripts/generate-doc.js.map +1 -0
- package/dist/scripts/generate-pr-checklist.d.ts +20 -0
- package/dist/scripts/generate-pr-checklist.d.ts.map +1 -0
- package/dist/scripts/generate-pr-checklist.js +276 -0
- package/dist/scripts/generate-pr-checklist.js.map +1 -0
- package/dist/scripts/precommit-check.d.ts +23 -0
- package/dist/scripts/precommit-check.d.ts.map +1 -0
- package/dist/scripts/precommit-check.js +331 -0
- package/dist/scripts/precommit-check.js.map +1 -0
- package/dist/scripts/set-admin-password.d.ts +14 -0
- package/dist/scripts/set-admin-password.d.ts.map +1 -0
- package/dist/scripts/set-admin-password.js +116 -0
- package/dist/scripts/set-admin-password.js.map +1 -0
- package/dist/scripts/set-bypass-password.d.ts +11 -0
- package/dist/scripts/set-bypass-password.d.ts.map +1 -0
- package/dist/scripts/set-bypass-password.js +106 -0
- package/dist/scripts/set-bypass-password.js.map +1 -0
- package/dist/scripts/utils/auto-fixer.d.ts +28 -0
- package/dist/scripts/utils/auto-fixer.d.ts.map +1 -0
- package/dist/scripts/utils/auto-fixer.js +177 -0
- package/dist/scripts/utils/auto-fixer.js.map +1 -0
- package/dist/scripts/utils/bypass-manager.d.ts +101 -0
- package/dist/scripts/utils/bypass-manager.d.ts.map +1 -0
- package/dist/scripts/utils/bypass-manager.js +496 -0
- package/dist/scripts/utils/bypass-manager.js.map +1 -0
- package/dist/scripts/utils/code-analyzer.d.ts +34 -0
- package/dist/scripts/utils/code-analyzer.d.ts.map +1 -0
- package/dist/scripts/utils/code-analyzer.js +323 -0
- package/dist/scripts/utils/code-analyzer.js.map +1 -0
- package/dist/scripts/utils/file-checker.d.ts +93 -0
- package/dist/scripts/utils/file-checker.d.ts.map +1 -0
- package/dist/scripts/utils/file-checker.js +248 -0
- package/dist/scripts/utils/file-checker.js.map +1 -0
- package/dist/scripts/utils/logger.d.ts +26 -0
- package/dist/scripts/utils/logger.d.ts.map +1 -0
- package/dist/scripts/utils/logger.js +86 -0
- package/dist/scripts/utils/logger.js.map +1 -0
- package/dist/scripts/utils/project-detector.d.ts +34 -0
- package/dist/scripts/utils/project-detector.d.ts.map +1 -0
- package/dist/scripts/utils/project-detector.js +124 -0
- package/dist/scripts/utils/project-detector.js.map +1 -0
- package/dist/scripts/utils/rule-engine.d.ts +57 -0
- package/dist/scripts/utils/rule-engine.d.ts.map +1 -0
- package/dist/scripts/utils/rule-engine.js +158 -0
- package/dist/scripts/utils/rule-engine.js.map +1 -0
- package/dist/scripts/view-bypass-log.d.ts +13 -0
- package/dist/scripts/view-bypass-log.d.ts.map +1 -0
- package/dist/scripts/view-bypass-log.js +117 -0
- package/dist/scripts/view-bypass-log.js.map +1 -0
- package/package.json +74 -0
- package/scripts/auto-fix.ts +115 -0
- package/scripts/cli.ts +246 -0
- package/scripts/delete-bypass-logs.ts +253 -0
- package/scripts/generate-doc.ts +317 -0
- package/scripts/generate-pr-checklist.ts +285 -0
- package/scripts/precommit-check.ts +349 -0
- package/scripts/set-admin-password.ts +90 -0
- package/scripts/set-bypass-password.ts +80 -0
- package/scripts/utils/auto-fixer.ts +181 -0
- package/scripts/utils/bypass-manager.ts +566 -0
- package/scripts/utils/code-analyzer.ts +341 -0
- package/scripts/utils/file-checker.ts +253 -0
- package/scripts/utils/logger.ts +88 -0
- package/scripts/utils/project-detector.ts +115 -0
- package/scripts/utils/rule-engine.ts +186 -0
- package/scripts/view-bypass-log.ts +92 -0
- package/templates/feature-doc-api.md +101 -0
- package/templates/feature-doc-service.md +113 -0
- package/templates/feature-doc-ui.md +91 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
/**
|
|
3
|
+
* ============================================================================
|
|
4
|
+
* set-admin-password.ts — CLI tool to set admin password
|
|
5
|
+
* ============================================================================
|
|
6
|
+
*
|
|
7
|
+
* Admin password is required to delete bypass log entries.
|
|
8
|
+
* This provides a higher level of security for log management.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* npm run set-admin-password
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { setAdminPassword } from './utils/bypass-manager';
|
|
15
|
+
import * as readline from 'readline';
|
|
16
|
+
|
|
17
|
+
function promptPassword(question: string): Promise<string> {
|
|
18
|
+
return new Promise((resolve) => {
|
|
19
|
+
const rl = readline.createInterface({
|
|
20
|
+
input: process.stdin,
|
|
21
|
+
output: process.stdout,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const stdin = process.stdin as any;
|
|
25
|
+
stdin.setRawMode(true);
|
|
26
|
+
|
|
27
|
+
let password = '';
|
|
28
|
+
process.stdout.write(question);
|
|
29
|
+
|
|
30
|
+
stdin.on('data', (char: Buffer) => {
|
|
31
|
+
const str = char.toString('utf-8');
|
|
32
|
+
|
|
33
|
+
if (str === '\n' || str === '\r' || str === '\u0004') {
|
|
34
|
+
stdin.setRawMode(false);
|
|
35
|
+
process.stdout.write('\n');
|
|
36
|
+
rl.close();
|
|
37
|
+
resolve(password);
|
|
38
|
+
} else if (str === '\u0003') {
|
|
39
|
+
// Ctrl+C
|
|
40
|
+
process.exit(1);
|
|
41
|
+
} else if (str === '\u007f' || str === '\b') {
|
|
42
|
+
// Backspace
|
|
43
|
+
if (password.length > 0) {
|
|
44
|
+
password = password.slice(0, -1);
|
|
45
|
+
process.stdout.write('\b \b');
|
|
46
|
+
}
|
|
47
|
+
} else {
|
|
48
|
+
password += str;
|
|
49
|
+
process.stdout.write('*');
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function main() {
|
|
56
|
+
console.log('🔐 Code Guardian — Set Admin Password\n');
|
|
57
|
+
console.log('⚠️ ADMIN PRIVILEGES:');
|
|
58
|
+
console.log(' • View all bypass logs');
|
|
59
|
+
console.log(' • Delete bypass log entries');
|
|
60
|
+
console.log(' • Access archived logs\n');
|
|
61
|
+
console.log('🔒 This password should be highly restricted and secure.\n');
|
|
62
|
+
|
|
63
|
+
const password = await promptPassword('Enter new admin password: ');
|
|
64
|
+
|
|
65
|
+
if (!password || password.length < 8) {
|
|
66
|
+
console.error('\n❌ Admin password must be at least 8 characters long.');
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const confirm = await promptPassword('Confirm password: ');
|
|
71
|
+
|
|
72
|
+
if (password !== confirm) {
|
|
73
|
+
console.error('\n❌ Passwords do not match.');
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
setAdminPassword(password);
|
|
78
|
+
console.log('\n✅ Admin password set successfully!');
|
|
79
|
+
console.log('📁 Stored in: .code-guardian/admin-credentials.hash');
|
|
80
|
+
console.log('\n⚠️ IMPORTANT SECURITY NOTES:');
|
|
81
|
+
console.log(' 1. Add .code-guardian/ to .gitignore (if not already done)');
|
|
82
|
+
console.log(' 2. Share this password only with authorized administrators');
|
|
83
|
+
console.log(' 3. Change default password immediately in production');
|
|
84
|
+
console.log(' 4. Store password securely (password manager recommended)');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
main().catch((err) => {
|
|
88
|
+
console.error(`Error: ${err.message}`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
/**
|
|
3
|
+
* ============================================================================
|
|
4
|
+
* set-bypass-password.ts — CLI tool to set bypass password
|
|
5
|
+
* ============================================================================
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* npm run set-bypass-password
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { setBypassPassword } from './utils/bypass-manager';
|
|
12
|
+
import * as readline from 'readline';
|
|
13
|
+
|
|
14
|
+
function promptPassword(question: string): Promise<string> {
|
|
15
|
+
return new Promise((resolve) => {
|
|
16
|
+
const rl = readline.createInterface({
|
|
17
|
+
input: process.stdin,
|
|
18
|
+
output: process.stdout,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const stdin = process.stdin as any;
|
|
22
|
+
stdin.setRawMode(true);
|
|
23
|
+
|
|
24
|
+
let password = '';
|
|
25
|
+
process.stdout.write(question);
|
|
26
|
+
|
|
27
|
+
stdin.on('data', (char: Buffer) => {
|
|
28
|
+
const str = char.toString('utf-8');
|
|
29
|
+
|
|
30
|
+
if (str === '\n' || str === '\r' || str === '\u0004') {
|
|
31
|
+
stdin.setRawMode(false);
|
|
32
|
+
process.stdout.write('\n');
|
|
33
|
+
rl.close();
|
|
34
|
+
resolve(password);
|
|
35
|
+
} else if (str === '\u0003') {
|
|
36
|
+
// Ctrl+C
|
|
37
|
+
process.exit(1);
|
|
38
|
+
} else if (str === '\u007f' || str === '\b') {
|
|
39
|
+
// Backspace
|
|
40
|
+
if (password.length > 0) {
|
|
41
|
+
password = password.slice(0, -1);
|
|
42
|
+
process.stdout.write('\b \b');
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
password += str;
|
|
46
|
+
process.stdout.write('*');
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function main() {
|
|
53
|
+
console.log('🔐 Code Guardian — Set Bypass Password\n');
|
|
54
|
+
console.log('This password will be required to bypass pre-commit checks.');
|
|
55
|
+
console.log('Share it only with authorized team members.\n');
|
|
56
|
+
|
|
57
|
+
const password = await promptPassword('Enter new bypass password: ');
|
|
58
|
+
|
|
59
|
+
if (!password || password.length < 6) {
|
|
60
|
+
console.error('\n❌ Password must be at least 6 characters long.');
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const confirm = await promptPassword('Confirm password: ');
|
|
65
|
+
|
|
66
|
+
if (password !== confirm) {
|
|
67
|
+
console.error('\n❌ Passwords do not match.');
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
setBypassPassword(password);
|
|
72
|
+
console.log('\n✅ Password set successfully!');
|
|
73
|
+
console.log('📁 Stored in: .code-guardian/bypass-password.hash');
|
|
74
|
+
console.log('\n⚠️ Remember to add .code-guardian/ to .gitignore if not already done.');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
main().catch((err) => {
|
|
78
|
+
console.error(`Error: ${err.message}`);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
});
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ============================================================================
|
|
3
|
+
* auto-fixer.ts — Automatic code fixes for common violations
|
|
4
|
+
* ============================================================================
|
|
5
|
+
*
|
|
6
|
+
* Provides auto-fix capabilities for rules that can be safely automated.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import { Violation } from './rule-engine';
|
|
11
|
+
|
|
12
|
+
export interface FixResult {
|
|
13
|
+
fixed: boolean;
|
|
14
|
+
message: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Attempt to auto-fix a violation
|
|
19
|
+
*/
|
|
20
|
+
export function autoFixViolation(violation: Violation, filePath: string): FixResult {
|
|
21
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
22
|
+
const lines = content.split('\n');
|
|
23
|
+
|
|
24
|
+
switch (violation.ruleId) {
|
|
25
|
+
case 'no-console-log':
|
|
26
|
+
return fixConsoleLog(lines, violation, filePath);
|
|
27
|
+
|
|
28
|
+
case 'no-any-type':
|
|
29
|
+
return fixAnyType(lines, violation, filePath);
|
|
30
|
+
|
|
31
|
+
case 'react-no-inline-styles':
|
|
32
|
+
return { fixed: false, message: 'Manual fix required - convert to Tailwind classes' };
|
|
33
|
+
|
|
34
|
+
case 'require-alt-text':
|
|
35
|
+
return fixMissingAlt(lines, violation, filePath);
|
|
36
|
+
|
|
37
|
+
case 'require-button-type':
|
|
38
|
+
return fixButtonType(lines, violation, filePath);
|
|
39
|
+
|
|
40
|
+
default:
|
|
41
|
+
return { fixed: false, message: 'No auto-fix available for this rule' };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Remove console.log statements
|
|
47
|
+
*/
|
|
48
|
+
function fixConsoleLog(lines: string[], violation: Violation, filePath: string): FixResult {
|
|
49
|
+
if (!violation.line) {
|
|
50
|
+
return { fixed: false, message: 'Cannot determine line number' };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const lineIndex = violation.line - 1;
|
|
54
|
+
const line = lines[lineIndex];
|
|
55
|
+
|
|
56
|
+
// Remove entire line if it only contains console.log
|
|
57
|
+
if (line.trim().match(/^console\.log\(.+\);?\s*$/)) {
|
|
58
|
+
lines.splice(lineIndex, 1);
|
|
59
|
+
fs.writeFileSync(filePath, lines.join('\n'), 'utf-8');
|
|
60
|
+
return { fixed: true, message: 'Removed console.log statement' };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return { fixed: false, message: 'Console.log is part of larger expression - manual fix required' };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Convert 'any' to 'unknown' (safer)
|
|
68
|
+
*/
|
|
69
|
+
function fixAnyType(lines: string[], violation: Violation, filePath: string): FixResult {
|
|
70
|
+
if (!violation.line) {
|
|
71
|
+
return { fixed: false, message: 'Cannot determine line number' };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const lineIndex = violation.line - 1;
|
|
75
|
+
let line = lines[lineIndex];
|
|
76
|
+
|
|
77
|
+
// Replace : any with : unknown
|
|
78
|
+
if (line.includes(': any')) {
|
|
79
|
+
line = line.replace(/:\s*any\b/g, ': unknown');
|
|
80
|
+
lines[lineIndex] = line;
|
|
81
|
+
fs.writeFileSync(filePath, lines.join('\n'), 'utf-8');
|
|
82
|
+
return { fixed: true, message: 'Changed any → unknown' };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Replace any[] with unknown[]
|
|
86
|
+
if (line.includes('any[]')) {
|
|
87
|
+
line = line.replace(/\bany\[\]/g, 'unknown[]');
|
|
88
|
+
lines[lineIndex] = line;
|
|
89
|
+
fs.writeFileSync(filePath, lines.join('\n'), 'utf-8');
|
|
90
|
+
return { fixed: true, message: 'Changed any[] → unknown[]' };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return { fixed: false, message: 'Complex any usage - manual fix required' };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Add alt="" to images
|
|
98
|
+
*/
|
|
99
|
+
function fixMissingAlt(lines: string[], violation: Violation, filePath: string): FixResult {
|
|
100
|
+
if (!violation.line) {
|
|
101
|
+
return { fixed: false, message: 'Cannot determine line number' };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const lineIndex = violation.line - 1;
|
|
105
|
+
let line = lines[lineIndex];
|
|
106
|
+
|
|
107
|
+
// Add alt="" before the closing />
|
|
108
|
+
if (/<img\b/.test(line) && !/alt\s*=/.test(line)) {
|
|
109
|
+
// Add alt before />
|
|
110
|
+
line = line.replace(/\/>/, ' alt="" />');
|
|
111
|
+
// Or before >
|
|
112
|
+
line = line.replace(/([^/])>/, '$1 alt="">');
|
|
113
|
+
|
|
114
|
+
lines[lineIndex] = line;
|
|
115
|
+
fs.writeFileSync(filePath, lines.join('\n'), 'utf-8');
|
|
116
|
+
return { fixed: true, message: 'Added alt="" attribute' };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return { fixed: false, message: 'Could not add alt attribute' };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Add type="button" to buttons
|
|
124
|
+
*/
|
|
125
|
+
function fixButtonType(lines: string[], violation: Violation, filePath: string): FixResult {
|
|
126
|
+
if (!violation.line) {
|
|
127
|
+
return { fixed: false, message: 'Cannot determine line number' };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const lineIndex = violation.line - 1;
|
|
131
|
+
let line = lines[lineIndex];
|
|
132
|
+
|
|
133
|
+
// Add type="button" to <button>
|
|
134
|
+
if (/<button\b/.test(line) && !/type\s*=/.test(line)) {
|
|
135
|
+
line = line.replace(/<button/, '<button type="button"');
|
|
136
|
+
|
|
137
|
+
lines[lineIndex] = line;
|
|
138
|
+
fs.writeFileSync(filePath, lines.join('\n'), 'utf-8');
|
|
139
|
+
return { fixed: true, message: 'Added type="button" attribute' };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return { fixed: false, message: 'Could not add type attribute' };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Auto-fix all fixable violations in a list
|
|
147
|
+
*/
|
|
148
|
+
export function autoFixAll(violations: Violation[], rootDir: string): {
|
|
149
|
+
fixed: number;
|
|
150
|
+
failed: number;
|
|
151
|
+
results: Array<{ violation: Violation; result: FixResult }>;
|
|
152
|
+
} {
|
|
153
|
+
const results: Array<{ violation: Violation; result: FixResult }> = [];
|
|
154
|
+
let fixed = 0;
|
|
155
|
+
let failed = 0;
|
|
156
|
+
|
|
157
|
+
// Group by file to avoid multiple reads/writes
|
|
158
|
+
const byFile = new Map<string, Violation[]>();
|
|
159
|
+
for (const v of violations) {
|
|
160
|
+
const existing = byFile.get(v.file) || [];
|
|
161
|
+
existing.push(v);
|
|
162
|
+
byFile.set(v.file, existing);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
for (const [file, fileViolations] of byFile) {
|
|
166
|
+
const fullPath = `${rootDir}/${file}`;
|
|
167
|
+
|
|
168
|
+
for (const violation of fileViolations) {
|
|
169
|
+
const result = autoFixViolation(violation, fullPath);
|
|
170
|
+
results.push({ violation, result });
|
|
171
|
+
|
|
172
|
+
if (result.fixed) {
|
|
173
|
+
fixed++;
|
|
174
|
+
} else {
|
|
175
|
+
failed++;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return { fixed, failed, results };
|
|
181
|
+
}
|