pumuki-ast-hooks 5.3.20 → 5.3.21
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/docs/RELEASE_NOTES.md +35 -0
- package/docs/VIOLATIONS_RESOLUTION_PLAN.md +58 -58
- package/package.json +3 -3
- package/scripts/hooks-system/.AI_TOKEN_STATUS.txt +1 -1
- package/scripts/hooks-system/.audit-reports/notifications.log +935 -0
- package/scripts/hooks-system/.audit-reports/token-monitor.log +2809 -0
- package/scripts/hooks-system/application/CompositionRoot.js +38 -22
- package/scripts/hooks-system/application/services/AutonomousOrchestrator.js +0 -18
- package/scripts/hooks-system/application/services/ContextDetectionEngine.js +0 -58
- package/scripts/hooks-system/application/services/DynamicRulesLoader.js +2 -12
- package/scripts/hooks-system/application/services/GitFlowService.js +0 -80
- package/scripts/hooks-system/application/services/GitTreeState.js +2 -5
- package/scripts/hooks-system/application/services/HookSystemScheduler.js +0 -4
- package/scripts/hooks-system/application/services/IntelligentCommitAnalyzer.js +0 -25
- package/scripts/hooks-system/application/services/IntelligentGitTreeMonitor.js +0 -11
- package/scripts/hooks-system/application/services/PlatformAnalysisService.js +0 -19
- package/scripts/hooks-system/application/services/PlatformDetectionService.js +0 -19
- package/scripts/hooks-system/application/services/PlaybookRunner.js +1 -22
- package/scripts/hooks-system/application/services/PredictiveHookAdvisor.js +0 -19
- package/scripts/hooks-system/application/services/RealtimeGuardPlugin.js +0 -25
- package/scripts/hooks-system/application/services/RealtimeGuardService.js +71 -41
- package/scripts/hooks-system/application/services/SmartDirtyTreeAnalyzer.js +0 -11
- package/scripts/hooks-system/application/services/commit/CommitMessageGenerator.js +0 -11
- package/scripts/hooks-system/application/services/commit/FeatureDetector.js +0 -11
- package/scripts/hooks-system/application/services/evidence/EvidenceContextManager.js +0 -25
- package/scripts/hooks-system/application/services/guard/GuardAutoManagerService.js +31 -21
- package/scripts/hooks-system/application/services/guard/GuardConfig.js +15 -18
- package/scripts/hooks-system/application/services/guard/GuardEventLogger.js +0 -11
- package/scripts/hooks-system/application/services/guard/GuardHealthReminder.js +0 -26
- package/scripts/hooks-system/application/services/guard/GuardHeartbeatMonitor.js +6 -20
- package/scripts/hooks-system/application/services/guard/GuardLockManager.js +0 -11
- package/scripts/hooks-system/application/services/guard/GuardMonitorLoop.js +0 -25
- package/scripts/hooks-system/application/services/guard/GuardNotificationHandler.js +0 -11
- package/scripts/hooks-system/application/services/guard/GuardProcessManager.js +23 -11
- package/scripts/hooks-system/application/services/guard/GuardRecoveryService.js +0 -11
- package/scripts/hooks-system/application/services/installation/ConfigurationGeneratorService.js +0 -18
- package/scripts/hooks-system/application/services/installation/FileSystemInstallerService.js +0 -18
- package/scripts/hooks-system/application/services/installation/GitEnvironmentService.js +1 -19
- package/scripts/hooks-system/application/services/installation/HookInstaller.js +62 -24
- package/scripts/hooks-system/application/services/installation/IdeIntegrationService.js +0 -11
- package/scripts/hooks-system/application/services/installation/InstallService.js +1 -25
- package/scripts/hooks-system/application/services/installation/McpConfigurator.js +2 -19
- package/scripts/hooks-system/application/services/installation/PlatformDetectorService.js +0 -11
- package/scripts/hooks-system/application/services/installation/VSCodeTaskConfigurator.js +0 -11
- package/scripts/hooks-system/application/services/logging/AuditLogger.js +0 -8
- package/scripts/hooks-system/application/services/logging/UnifiedLogger.js +13 -15
- package/scripts/hooks-system/application/services/monitoring/ActivityMonitor.js +0 -33
- package/scripts/hooks-system/application/services/monitoring/AstMonitor.js +0 -27
- package/scripts/hooks-system/application/services/monitoring/DevDocsMonitor.js +0 -26
- package/scripts/hooks-system/application/services/monitoring/EvidenceMonitor.js +0 -18
- package/scripts/hooks-system/application/services/monitoring/EvidenceMonitorService.js +4 -28
- package/scripts/hooks-system/application/services/monitoring/GitTreeMonitor.js +0 -28
- package/scripts/hooks-system/application/services/monitoring/GitTreeMonitorService.js +0 -26
- package/scripts/hooks-system/application/services/monitoring/HealthCheckProviders.js +0 -4
- package/scripts/hooks-system/application/services/monitoring/HealthCheckService.js +0 -25
- package/scripts/hooks-system/application/services/monitoring/HeartbeatMonitorService.js +0 -26
- package/scripts/hooks-system/application/services/monitoring/TokenMonitor.js +0 -26
- package/scripts/hooks-system/application/services/notification/MacNotificationSender.js +0 -11
- package/scripts/hooks-system/application/services/notification/NotificationCenterService.js +0 -18
- package/scripts/hooks-system/application/services/notification/NotificationDispatcher.js +0 -11
- package/scripts/hooks-system/application/services/notification/components/NotificationCooldownManager.js +0 -18
- package/scripts/hooks-system/application/services/notification/components/NotificationDeduplicator.js +0 -18
- package/scripts/hooks-system/application/services/notification/components/NotificationQueue.js +0 -11
- package/scripts/hooks-system/application/services/notification/components/NotificationRetryExecutor.js +0 -20
- package/scripts/hooks-system/application/services/platform/PlatformHeuristics.js +0 -19
- package/scripts/hooks-system/application/services/recovery/AutoRecoveryManager.js +0 -19
- package/scripts/hooks-system/application/services/smart-commit/CommitMessageSuggester.js +0 -11
- package/scripts/hooks-system/application/services/smart-commit/FileContextGrouper.js +0 -19
- package/scripts/hooks-system/application/services/smart-commit/SmartCommitSummaryBuilder.js +0 -4
- package/scripts/hooks-system/application/services/token/CursorTokenService.js +0 -20
- package/scripts/hooks-system/application/services/token/TokenMetricsService.js +2 -12
- package/scripts/hooks-system/application/services/token/TokenMonitorService.js +0 -19
- package/scripts/hooks-system/application/services/token/TokenStatusReporter.js +0 -12
- package/scripts/hooks-system/bin/cli.js +15 -1
- package/scripts/hooks-system/bin/guard-env.sh +18 -38
- package/scripts/hooks-system/bin/guard-supervisor.js +5 -515
- package/scripts/hooks-system/bin/session-loader.sh +3 -262
- package/scripts/hooks-system/bin/start-guards.sh +21 -184
- package/scripts/hooks-system/bin/update-evidence.sh +10 -1161
- package/scripts/hooks-system/config/project.config.json +1 -1
- package/scripts/hooks-system/domain/events/index.js +31 -24
- package/scripts/hooks-system/infrastructure/ast/android/analyzers/AndroidAnalysisOrchestrator.js +3 -2
- package/scripts/hooks-system/infrastructure/ast/ast-core.js +12 -20
- package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +8 -18
- package/scripts/hooks-system/infrastructure/ast/backend/analyzers/BackendPatternDetector.js +2 -1
- package/scripts/hooks-system/infrastructure/ast/backend/ast-backend.js +18 -14
- package/scripts/hooks-system/infrastructure/ast/frontend/ast-frontend.js +196 -196
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSASTIntelligentAnalyzer.js +3 -2
- package/scripts/hooks-system/infrastructure/hooks/skill-activation-prompt.js +3 -2
- package/scripts/hooks-system/infrastructure/logging/UnifiedLoggerFactory.js +5 -4
- package/scripts/hooks-system/infrastructure/mcp/ast-intelligence-automation.js +88 -0
- package/scripts/hooks-system/infrastructure/orchestration/intelligent-audit.js +17 -16
- package/scripts/hooks-system/infrastructure/shell/orchestrators/audit-orchestrator.sh +92 -54
- package/scripts/hooks-system/infrastructure/telemetry/metrics-server.js +3 -2
- package/scripts/hooks-system/infrastructure/validators/enforce-english-literals.js +6 -8
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
const {
|
|
2
|
-
ValidationException,
|
|
3
|
-
BadRequestException,
|
|
4
|
-
InternalServerException
|
|
5
|
-
} = require('../exceptions');
|
|
1
|
+
const { ValidationError } = require('../errors');
|
|
6
2
|
|
|
7
3
|
class DomainEvent {
|
|
8
4
|
constructor(type, payload) {
|
|
9
|
-
if (!type) throw new ValidationException('Event type is required', { field: 'type' });
|
|
10
|
-
if (!payload) throw new ValidationException('Event payload is required', { field: 'payload' });
|
|
11
5
|
this.type = type;
|
|
12
6
|
this.payload = payload;
|
|
13
7
|
this.timestamp = new Date().toISOString();
|
|
@@ -15,8 +9,8 @@ class DomainEvent {
|
|
|
15
9
|
}
|
|
16
10
|
|
|
17
11
|
validate() {
|
|
18
|
-
if (!this.type) throw new
|
|
19
|
-
if (!this.payload) throw new
|
|
12
|
+
if (!this.type) throw new ValidationError('Event type is required', 'type', this.type);
|
|
13
|
+
if (!this.payload) throw new ValidationError('Event payload is required', 'payload', this.payload);
|
|
20
14
|
return true;
|
|
21
15
|
}
|
|
22
16
|
|
|
@@ -37,7 +31,9 @@ class EvidenceStaleEvent extends DomainEvent {
|
|
|
37
31
|
|
|
38
32
|
validate() {
|
|
39
33
|
super.validate();
|
|
40
|
-
if (!this.payload.evidencePath)
|
|
34
|
+
if (!this.payload.evidencePath) {
|
|
35
|
+
throw new ValidationError('Evidence path is required', 'payload.evidencePath', this.payload.evidencePath);
|
|
36
|
+
}
|
|
41
37
|
}
|
|
42
38
|
}
|
|
43
39
|
|
|
@@ -49,8 +45,12 @@ class GitFlowViolationEvent extends DomainEvent {
|
|
|
49
45
|
|
|
50
46
|
validate() {
|
|
51
47
|
super.validate();
|
|
52
|
-
if (!this.payload.branch)
|
|
53
|
-
|
|
48
|
+
if (!this.payload.branch) {
|
|
49
|
+
throw new ValidationError('Branch name is required', 'payload.branch', this.payload.branch);
|
|
50
|
+
}
|
|
51
|
+
if (!this.payload.violation) {
|
|
52
|
+
throw new ValidationError('Violation details are required', 'payload.violation', this.payload.violation);
|
|
53
|
+
}
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -62,7 +62,9 @@ class AstCriticalFoundEvent extends DomainEvent {
|
|
|
62
62
|
|
|
63
63
|
validate() {
|
|
64
64
|
super.validate();
|
|
65
|
-
if (!Array.isArray(this.payload.findings))
|
|
65
|
+
if (!Array.isArray(this.payload.findings)) {
|
|
66
|
+
throw new ValidationError('Findings must be an array', 'payload.findings', this.payload.findings);
|
|
67
|
+
}
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
|
|
@@ -71,12 +73,6 @@ class PreCommitBlockedEvent extends DomainEvent {
|
|
|
71
73
|
super('PRE_COMMIT_BLOCKED', { reason, violations });
|
|
72
74
|
this.validate();
|
|
73
75
|
}
|
|
74
|
-
|
|
75
|
-
validate() {
|
|
76
|
-
super.validate();
|
|
77
|
-
if (!this.payload.reason) throw new ValidationException('Reason is required', { field: 'reason' });
|
|
78
|
-
if (!this.payload.violations) throw new ValidationException('Violations are required', { field: 'violations' });
|
|
79
|
-
}
|
|
80
76
|
}
|
|
81
77
|
|
|
82
78
|
class AnalysisCompletedEvent extends DomainEvent {
|
|
@@ -84,16 +80,13 @@ class AnalysisCompletedEvent extends DomainEvent {
|
|
|
84
80
|
super('ANALYSIS_COMPLETED', summary);
|
|
85
81
|
this.validate();
|
|
86
82
|
}
|
|
87
|
-
|
|
88
|
-
validate() {
|
|
89
|
-
super.validate();
|
|
90
|
-
if (!this.payload) throw new ValidationException('Summary is required', { field: 'summary' });
|
|
91
|
-
}
|
|
92
83
|
}
|
|
93
84
|
|
|
94
85
|
class EventBus {
|
|
95
86
|
constructor() {
|
|
96
87
|
this.subscribers = new Map();
|
|
88
|
+
this.processedIds = new Set();
|
|
89
|
+
this.maxProcessed = 500;
|
|
97
90
|
}
|
|
98
91
|
|
|
99
92
|
subscribe(eventType, handler) {
|
|
@@ -113,11 +106,25 @@ class EventBus {
|
|
|
113
106
|
}
|
|
114
107
|
|
|
115
108
|
async publish(event) {
|
|
109
|
+
if (event?.id && this.processedIds.has(event.id)) {
|
|
110
|
+
return event;
|
|
111
|
+
}
|
|
116
112
|
const handlers = this.subscribers.get(event.type) || [];
|
|
117
113
|
const wildcardHandlers = this.subscribers.get('*') || [];
|
|
118
114
|
const allHandlers = [...handlers, ...wildcardHandlers];
|
|
119
115
|
|
|
120
116
|
await Promise.all(allHandlers.map(handler => handler(event)));
|
|
117
|
+
|
|
118
|
+
if (event?.id) {
|
|
119
|
+
this.processedIds.add(event.id);
|
|
120
|
+
if (this.processedIds.size > this.maxProcessed) {
|
|
121
|
+
const iter = this.processedIds.values();
|
|
122
|
+
for (let i = 0; i < 50 && this.processedIds.size > this.maxProcessed; i++) {
|
|
123
|
+
const next = iter.next();
|
|
124
|
+
if (!next.done) this.processedIds.delete(next.value);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
121
128
|
return event;
|
|
122
129
|
}
|
|
123
130
|
|
package/scripts/hooks-system/infrastructure/ast/android/analyzers/AndroidAnalysisOrchestrator.js
CHANGED
|
@@ -40,8 +40,9 @@ class AndroidAnalysisOrchestrator {
|
|
|
40
40
|
return 0.6745 * (x - med) / madValue;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
-
const
|
|
44
|
-
const
|
|
43
|
+
const env = require('../../../../config/env');
|
|
44
|
+
const pOutlier = env.getNumber('AST_GODCLASS_P_OUTLIER', 90);
|
|
45
|
+
const pExtreme = env.getNumber('AST_GODCLASS_P_EXTREME', 97);
|
|
45
46
|
|
|
46
47
|
const methods = this.godClassCandidates.map(c => c.methodsCount);
|
|
47
48
|
const props = this.godClassCandidates.map(c => c.propertiesCount);
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
const { Project, Node, SyntaxKind, ScriptTarget, ModuleKind } = require("ts-morph");
|
|
3
3
|
const path = require("path");
|
|
4
4
|
const fs = require("fs");
|
|
5
|
+
const env = require("../../config/env");
|
|
5
6
|
|
|
6
7
|
let SeverityEvaluator = null;
|
|
7
8
|
let severityEvaluatorInstance = null;
|
|
@@ -19,7 +20,7 @@ function getSeverityEvaluator() {
|
|
|
19
20
|
return severityEvaluatorInstance;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
let INTELLIGENT_SEVERITY_ENABLED =
|
|
23
|
+
let INTELLIGENT_SEVERITY_ENABLED = env.getBool('INTELLIGENT_SEVERITY', false);
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
26
|
* Get repository root directory (portable - dynamic detection)
|
|
@@ -179,18 +180,18 @@ function pushFinding(ruleId, severity, sf, node, message, findings, metrics = {}
|
|
|
179
180
|
let mappedSeverity = mapToLevel(severity);
|
|
180
181
|
const isCleanLayerMarkerRule = ruleId === 'backend.clean.domain' || ruleId === 'backend.clean.application' || ruleId === 'backend.clean.infrastructure' || ruleId === 'backend.clean.presentation';
|
|
181
182
|
let isStrictCriticalRule = false;
|
|
182
|
-
if (
|
|
183
|
+
if (env.get('AUDIT_STRICT', '0') === '1' && !isCleanLayerMarkerRule) {
|
|
183
184
|
const defaultStrictCriticalRegex = '(solid\\.|architecture\\.|clean\\.|cqrs\\.|tdd\\.|bdd\\.|security\\.|error\\.|testing\\.|performance\\.|metrics\\.|observability\\.|validation\\.|i18n\\.|accessibility\\.|naming\\.)';
|
|
184
185
|
const defaultStrictCriticalRegexLibrary = '(solid\\.|architecture\\.|clean\\.|cqrs\\.|tdd\\.|bdd\\.|security\\.|error\\.|testing\\.|validation\\.|naming\\.)';
|
|
185
|
-
const strictRegexSource =
|
|
186
|
-
|
|
187
|
-
?
|
|
186
|
+
const strictRegexSource = env.get('AST_STRICT_CRITICAL_RULES_REGEX',
|
|
187
|
+
env.getBool('AUDIT_LIBRARY', false)
|
|
188
|
+
? env.get('AST_STRICT_CRITICAL_RULES_REGEX_LIBRARY', defaultStrictCriticalRegexLibrary)
|
|
188
189
|
: defaultStrictCriticalRegex);
|
|
189
190
|
let strictRegex;
|
|
190
191
|
try {
|
|
191
192
|
strictRegex = new RegExp(strictRegexSource, 'i');
|
|
192
193
|
} catch {
|
|
193
|
-
strictRegex = new RegExp(
|
|
194
|
+
strictRegex = new RegExp(env.getBool('AUDIT_LIBRARY', false) ? defaultStrictCriticalRegexLibrary : defaultStrictCriticalRegex, 'i');
|
|
194
195
|
}
|
|
195
196
|
isStrictCriticalRule = strictRegex.test(ruleId);
|
|
196
197
|
if (isStrictCriticalRule) {
|
|
@@ -241,18 +242,18 @@ function pushFileFinding(ruleId, severity, filePath, line, column, message, find
|
|
|
241
242
|
let mappedSeverity = mapToLevel(severity);
|
|
242
243
|
const isCleanLayerMarkerRule = ruleId === 'backend.clean.domain' || ruleId === 'backend.clean.application' || ruleId === 'backend.clean.infrastructure' || ruleId === 'backend.clean.presentation';
|
|
243
244
|
let isStrictCriticalRule = false;
|
|
244
|
-
if (
|
|
245
|
+
if (env.get('AUDIT_STRICT', '0') === '1' && !isCleanLayerMarkerRule) {
|
|
245
246
|
const defaultStrictCriticalRegex = '(solid\\.|architecture\\.|clean\\.|cqrs\\.|tdd\\.|bdd\\.|security\\.|error\\.|testing\\.|performance\\.|metrics\\.|observability\\.|validation\\.|i18n\\.|accessibility\\.|naming\\.)';
|
|
246
247
|
const defaultStrictCriticalRegexLibrary = '(solid\\.|architecture\\.|clean\\.|cqrs\\.|tdd\\.|bdd\\.|security\\.|error\\.|testing\\.|validation\\.|naming\\.)';
|
|
247
|
-
const strictRegexSource =
|
|
248
|
-
|
|
249
|
-
?
|
|
248
|
+
const strictRegexSource = env.get('AST_STRICT_CRITICAL_RULES_REGEX',
|
|
249
|
+
env.getBool('AUDIT_LIBRARY', false)
|
|
250
|
+
? env.get('AST_STRICT_CRITICAL_RULES_REGEX_LIBRARY', defaultStrictCriticalRegexLibrary)
|
|
250
251
|
: defaultStrictCriticalRegex);
|
|
251
252
|
let strictRegex;
|
|
252
253
|
try {
|
|
253
254
|
strictRegex = new RegExp(strictRegexSource, 'i');
|
|
254
255
|
} catch {
|
|
255
|
-
strictRegex = new RegExp(
|
|
256
|
+
strictRegex = new RegExp(env.getBool('AUDIT_LIBRARY', false) ? defaultStrictCriticalRegexLibrary : defaultStrictCriticalRegex, 'i');
|
|
256
257
|
}
|
|
257
258
|
isStrictCriticalRule = strictRegex.test(ruleId);
|
|
258
259
|
if (isStrictCriticalRule) {
|
|
@@ -332,15 +333,6 @@ function mapToLevel(severity) {
|
|
|
332
333
|
function platformOf(filePath) {
|
|
333
334
|
const p = filePath.replace(/\\/g, "/");
|
|
334
335
|
|
|
335
|
-
if (p.includes("/infrastructure/ast/") && process.env.AUDIT_LIBRARY !== 'true') return null;
|
|
336
|
-
|
|
337
|
-
if (process.env.AUDIT_LIBRARY === 'true') {
|
|
338
|
-
if (p.includes("/infrastructure/ast/backend/") || p.includes("/scripts/hooks-system/infrastructure/ast/backend/")) return "backend";
|
|
339
|
-
if (p.includes("/infrastructure/ast/frontend/") || p.includes("/scripts/hooks-system/infrastructure/ast/frontend/")) return "frontend";
|
|
340
|
-
if (p.includes("/infrastructure/ast/android/") || p.includes("/scripts/hooks-system/infrastructure/ast/android/")) return "android";
|
|
341
|
-
if (p.includes("/infrastructure/ast/ios/") || p.includes("/scripts/hooks-system/infrastructure/ast/ios/")) return "ios";
|
|
342
|
-
}
|
|
343
|
-
|
|
344
336
|
if (p.includes("/apps/backend/") || p.includes("apps/backend/")) return "backend";
|
|
345
337
|
if (p.includes("/apps/admin/") || p.includes("/admin-dashboard/")) return "frontend";
|
|
346
338
|
if (p.includes("/apps/mobile-ios/") || p.includes("/apps/ios/")) return "ios";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
const path = require("path");
|
|
3
3
|
const fs = require("fs");
|
|
4
|
+
const env = require("../../config/env");
|
|
4
5
|
|
|
5
6
|
const astModulesPath = __dirname;
|
|
6
7
|
const { createProject, platformOf, mapToLevel } = require(path.join(astModulesPath, "ast-core"));
|
|
@@ -27,13 +28,7 @@ async function runASTIntelligence() {
|
|
|
27
28
|
const { getRepoRoot } = require('./ast-core');
|
|
28
29
|
const root = getRepoRoot();
|
|
29
30
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
const allFiles = listSourceFiles(root).filter(f => {
|
|
33
|
-
const p = String(f || '').replace(/\\/g, '/');
|
|
34
|
-
if (!isLibraryAudit && p.includes('/infrastructure/ast/')) return false;
|
|
35
|
-
return true;
|
|
36
|
-
});
|
|
31
|
+
const allFiles = listSourceFiles(root);
|
|
37
32
|
|
|
38
33
|
const project = createProject(allFiles);
|
|
39
34
|
const findings = [];
|
|
@@ -75,9 +70,9 @@ async function runASTIntelligence() {
|
|
|
75
70
|
}
|
|
76
71
|
|
|
77
72
|
function runProjectHardcodedThresholdAudit(root, allFiles, findings) {
|
|
78
|
-
if (
|
|
73
|
+
if (env.get('AST_INSIGHTS', '0') !== '1') return;
|
|
79
74
|
|
|
80
|
-
const maxFindings =
|
|
75
|
+
const maxFindings = env.getNumber('AST_INSIGHTS_PROJECT_MAX', 200);
|
|
81
76
|
if (!Number.isFinite(maxFindings) || maxFindings <= 0) return;
|
|
82
77
|
|
|
83
78
|
const isExcludedPath = (filePath) => {
|
|
@@ -160,7 +155,7 @@ function runProjectHardcodedThresholdAudit(root, allFiles, findings) {
|
|
|
160
155
|
}
|
|
161
156
|
|
|
162
157
|
function runHardcodedThresholdAudit(root, findings) {
|
|
163
|
-
if (
|
|
158
|
+
if (env.get('AST_INSIGHTS', '0') !== '1') return;
|
|
164
159
|
|
|
165
160
|
const ruleDirs = [
|
|
166
161
|
path.join(root, 'infrastructure', 'ast'),
|
|
@@ -317,7 +312,7 @@ async function runPlatformAnalysis(project, findings, context) {
|
|
|
317
312
|
}
|
|
318
313
|
} catch (error) {
|
|
319
314
|
console.error(`[ERROR] Error processing platform ${platform}:`, error.message);
|
|
320
|
-
if (
|
|
315
|
+
if (env.getBool('DEBUG_AST', false)) {
|
|
321
316
|
console.error(error.stack);
|
|
322
317
|
}
|
|
323
318
|
}
|
|
@@ -376,7 +371,7 @@ function generateOutput(findings, context, project, root) {
|
|
|
376
371
|
* Save detailed JSON report
|
|
377
372
|
*/
|
|
378
373
|
function saveDetailedReport(findings, levelTotals, platformTotals, project, root) {
|
|
379
|
-
const outDir =
|
|
374
|
+
const outDir = env.get('AUDIT_TMP', path.join(root, ".audit_tmp"));
|
|
380
375
|
try {
|
|
381
376
|
fs.mkdirSync(outDir, { recursive: true });
|
|
382
377
|
|
|
@@ -532,7 +527,7 @@ function checkForMigrations(root) {
|
|
|
532
527
|
* List source files recursively
|
|
533
528
|
*/
|
|
534
529
|
function listSourceFiles(root) {
|
|
535
|
-
if (
|
|
530
|
+
if (env.get('STAGING_ONLY_MODE', '0') === "1") {
|
|
536
531
|
const { execSync } = require("child_process");
|
|
537
532
|
try {
|
|
538
533
|
const allStaged = execSync("git diff --cached --name-only --diff-filter=ACM", {
|
|
@@ -600,11 +595,6 @@ function listSourceFiles(root) {
|
|
|
600
595
|
function shouldIgnore(file) {
|
|
601
596
|
const p = file.replace(/\\/g, "/");
|
|
602
597
|
if (p.includes("node_modules/")) return true;
|
|
603
|
-
|
|
604
|
-
const isLibraryAudit = process.env.AUDIT_LIBRARY === 'true';
|
|
605
|
-
|
|
606
|
-
if (!isLibraryAudit && p.includes("scripts/hooks-system/")) return true;
|
|
607
|
-
if (!isLibraryAudit && p.includes("/infrastructure/ast/")) return true;
|
|
608
598
|
if (p.includes("/.cursor/")) return true;
|
|
609
599
|
if (/\.bak/i.test(p)) return true;
|
|
610
600
|
if (p.includes("/.next/")) return true;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const env = require('../../../../config/env');
|
|
3
4
|
|
|
4
5
|
class BackendPatternDetector {
|
|
5
6
|
constructor(projectRoot) {
|
|
@@ -11,7 +12,7 @@ class BackendPatternDetector {
|
|
|
11
12
|
const fullPath = path.join(this.projectRoot, relativePath);
|
|
12
13
|
return fs.readFileSync(fullPath, 'utf-8');
|
|
13
14
|
} catch (error) {
|
|
14
|
-
if (
|
|
15
|
+
if (env.getBool('DEBUG', false)) {
|
|
15
16
|
console.debug(`[BackendPatternDetector] Failed to read file ${relativePath}: ${error.message}`);
|
|
16
17
|
}
|
|
17
18
|
return '';
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
+
const env = require('../../../config/env');
|
|
2
3
|
const {
|
|
4
|
+
platformOf,
|
|
3
5
|
pushFinding,
|
|
6
|
+
pushFileFinding,
|
|
4
7
|
mapToLevel,
|
|
5
|
-
|
|
8
|
+
positionOf,
|
|
6
9
|
isTestFile,
|
|
7
|
-
|
|
10
|
+
SyntaxKind,
|
|
8
11
|
hasImport,
|
|
9
12
|
hasDecorator,
|
|
10
13
|
findStringLiterals,
|
|
@@ -118,7 +121,7 @@ function runBackendIntelligence(project, findings, platform) {
|
|
|
118
121
|
const filePath = sf.getFilePath();
|
|
119
122
|
if (platformOf(filePath) !== 'backend') return;
|
|
120
123
|
if (/\/ast-[^/]+\.js$/.test(filePath)) return;
|
|
121
|
-
if (
|
|
124
|
+
if (!env.getBool('AUDIT_LIBRARY', false)) {
|
|
122
125
|
if (/scripts\/hooks-system\/infrastructure\/ast\//i.test(filePath) || /\/infrastructure\/ast\//i.test(filePath)) return;
|
|
123
126
|
}
|
|
124
127
|
if (isTestFile(filePath)) return;
|
|
@@ -143,8 +146,8 @@ function runBackendIntelligence(project, findings, platform) {
|
|
|
143
146
|
|
|
144
147
|
if (metrics.length === 0) return null;
|
|
145
148
|
|
|
146
|
-
const pOutlier =
|
|
147
|
-
const pExtreme =
|
|
149
|
+
const pOutlier = env.getNumber('AST_GODCLASS_P_OUTLIER', 90);
|
|
150
|
+
const pExtreme = env.getNumber('AST_GODCLASS_P_EXTREME', 97);
|
|
148
151
|
|
|
149
152
|
const methods = metrics.map(m => m.methodsCount);
|
|
150
153
|
const props = metrics.map(m => m.propertiesCount);
|
|
@@ -201,12 +204,12 @@ function runBackendIntelligence(project, findings, platform) {
|
|
|
201
204
|
if (platformOf(filePath) !== "backend") return;
|
|
202
205
|
|
|
203
206
|
if (/\/ast-[^/]+\.js$/.test(filePath)) return;
|
|
204
|
-
if (
|
|
207
|
+
if (!env.getBool('AUDIT_LIBRARY', false)) {
|
|
205
208
|
if (/scripts\/hooks-system\/infrastructure\/ast\//i.test(filePath) || /\/infrastructure\/ast\//i.test(filePath)) return;
|
|
206
209
|
}
|
|
207
210
|
|
|
208
211
|
const fullText = sf.getFullText();
|
|
209
|
-
const insightsEnabled =
|
|
212
|
+
const insightsEnabled = env.get('AST_INSIGHTS', '0') === '1';
|
|
210
213
|
const isSpecFile = /\.(spec|test)\.(ts|tsx|js|jsx)$/.test(filePath);
|
|
211
214
|
const secretPattern = /(password|secret|key|token)\s*[:=]\s*['"`]([^'"]{8,})['"`]/gi;
|
|
212
215
|
const matches = Array.from(fullText.matchAll(secretPattern));
|
|
@@ -366,12 +369,11 @@ function runBackendIntelligence(project, findings, platform) {
|
|
|
366
369
|
}
|
|
367
370
|
});
|
|
368
371
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
// }
|
|
372
|
+
const hasCors = sf.getFullText().includes("cors") || sf.getFullText().includes("CORS") || sf.getFullText().includes("@CrossOrigin");
|
|
373
|
+
const missingCorsSeverity = hasGlobalCors ? "low" : "high";
|
|
374
|
+
if (!hasCors && (sf.getFullText().includes("controller") || sf.getFullText().includes("Controller"))) {
|
|
375
|
+
pushFinding("backend.auth.missing_cors", missingCorsSeverity, sf, sf, "Missing CORS configuration in controller - consider @CrossOrigin or global CORS config", findings);
|
|
376
|
+
}
|
|
375
377
|
|
|
376
378
|
sf.getDescendantsOfKind(SyntaxKind.CallExpression).forEach((call) => {
|
|
377
379
|
const expr = call.getExpression();
|
|
@@ -423,7 +425,9 @@ function runBackendIntelligence(project, findings, platform) {
|
|
|
423
425
|
|
|
424
426
|
if (isTestFile(filePath)) {
|
|
425
427
|
sf.getDescendantsOfKind(SyntaxKind.CallExpression).forEach((call) => {
|
|
426
|
-
const
|
|
428
|
+
const expr = call.getExpression();
|
|
429
|
+
if (!expr) return;
|
|
430
|
+
const exprText = expr.getText();
|
|
427
431
|
if (/Thread\.sleep|await|delay/.test(exprText)) {
|
|
428
432
|
pushFinding("backend.testing.slow_tests", "medium", sf, call, "Test with sleep/delay detected - slow tests impact CI/CD performance", findings);
|
|
429
433
|
}
|