correctover-scan 1.2.1 ā 1.4.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/core/license.js +37 -23
- package/package.json +2 -2
package/core/license.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* License validator for correctover-scan NPM.
|
|
3
|
-
* Mirrors the Python LicenseValidator:
|
|
3
|
+
* Mirrors the Python LicenseValidator: 30 free checks/month (no daily reset), CORRECTOVER_LICENSE_KEY unlocks.
|
|
4
4
|
* Supports CV-TRL/CV-PRO (FC) and COV- (Cloud) key formats.
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -9,7 +9,7 @@ const path = require('path');
|
|
|
9
9
|
const crypto = require('crypto');
|
|
10
10
|
const os = require('os');
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const FREE_LIMIT_PER_MONTH = 30;
|
|
13
13
|
const STATE_FILE = path.join(os.homedir(), '.correctover', 'license.json');
|
|
14
14
|
|
|
15
15
|
function loadState() {
|
|
@@ -28,14 +28,18 @@ function saveState(state) {
|
|
|
28
28
|
} catch (e) {}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
function currentMonth() {
|
|
32
|
+
return new Date().toISOString().slice(0, 7); // YYYY-MM
|
|
33
|
+
}
|
|
34
|
+
|
|
31
35
|
function getProductState(state, product) {
|
|
32
|
-
const
|
|
36
|
+
const month = currentMonth();
|
|
33
37
|
if (!state.products[product]) {
|
|
34
|
-
state.products[product] = {
|
|
38
|
+
state.products[product] = { checks_used: 0, month: month, total_checks: 0 };
|
|
35
39
|
}
|
|
36
|
-
if (state.products[product].
|
|
37
|
-
state.products[product].
|
|
38
|
-
state.products[product].
|
|
40
|
+
if (state.products[product].month !== month) {
|
|
41
|
+
state.products[product].checks_used = 0;
|
|
42
|
+
state.products[product].month = month;
|
|
39
43
|
}
|
|
40
44
|
return state.products[product];
|
|
41
45
|
}
|
|
@@ -80,49 +84,59 @@ function checkLicense(product) {
|
|
|
80
84
|
return {
|
|
81
85
|
authorized: true,
|
|
82
86
|
tier: 'pro',
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
checks_remaining: Infinity,
|
|
88
|
+
checks_used: ps.checks_used,
|
|
85
89
|
limit: Infinity,
|
|
86
90
|
};
|
|
87
91
|
}
|
|
88
92
|
|
|
89
|
-
const remaining = Math.max(0,
|
|
93
|
+
const remaining = Math.max(0, FREE_LIMIT_PER_MONTH - ps.checks_used);
|
|
90
94
|
return {
|
|
91
95
|
authorized: remaining > 0,
|
|
92
96
|
tier: 'free',
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
limit:
|
|
97
|
+
checks_remaining: remaining,
|
|
98
|
+
checks_used: ps.checks_used,
|
|
99
|
+
limit: FREE_LIMIT_PER_MONTH,
|
|
96
100
|
};
|
|
97
101
|
}
|
|
98
102
|
|
|
99
|
-
function recordCall(product) {
|
|
103
|
+
function recordCall(product, count = 1) {
|
|
100
104
|
const state = loadState();
|
|
101
105
|
const status = checkLicense(product);
|
|
102
106
|
if (!status.authorized) return status;
|
|
103
107
|
|
|
104
108
|
const ps = getProductState(state, product);
|
|
105
|
-
ps.
|
|
106
|
-
ps.
|
|
109
|
+
ps.checks_used += count;
|
|
110
|
+
ps.total_checks = (ps.total_checks || 0) + count;
|
|
107
111
|
saveState(state);
|
|
108
112
|
|
|
109
|
-
status.
|
|
110
|
-
status.
|
|
113
|
+
status.checks_remaining = Math.max(0, FREE_LIMIT_PER_MONTH - ps.checks_used);
|
|
114
|
+
status.checks_used = ps.checks_used;
|
|
111
115
|
return status;
|
|
112
116
|
}
|
|
113
117
|
|
|
114
|
-
function
|
|
118
|
+
function canRun(product, count) {
|
|
119
|
+
const status = checkLicense(product);
|
|
120
|
+
if (status.tier === 'pro') return true;
|
|
121
|
+
return status.checks_remaining >= count;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function getUpgradeMessage(status, context) {
|
|
115
125
|
if (status.tier !== 'free') return '';
|
|
116
|
-
if (status.
|
|
117
|
-
return `\nš« Free tier limit reached (${
|
|
126
|
+
if (status.checks_remaining <= 0) {
|
|
127
|
+
return `\nš« Free tier limit reached (${FREE_LIMIT_PER_MONTH} checks/month).\n Upgrade to Pro: https://correctover.com/checkout\n Or: export CORRECTOVER_LICENSE_KEY=<your-key>\n`;
|
|
128
|
+
}
|
|
129
|
+
if (context === 'results') {
|
|
130
|
+
return `\n${'ā'.repeat(50)}\nš ${status.checks_remaining} checks remaining this month.\n Upgrade to Pro for:\n ⢠Full risk report (all findings)\n ⢠Fix recommendations + auto-heal\n ⢠HTML audit reports\n${'ā'.repeat(50)}\n ā https://correctover.com/checkout\n${'ā'.repeat(50)}\n`;
|
|
118
131
|
}
|
|
119
|
-
return `\nš Free tier: ${status.
|
|
132
|
+
return `\nš Free tier: ${status.checks_remaining} checks remaining this month.\n Upgrade: https://correctover.com/checkout\n`;
|
|
120
133
|
}
|
|
121
134
|
|
|
122
135
|
module.exports = {
|
|
123
|
-
|
|
136
|
+
FREE_LIMIT_PER_MONTH,
|
|
124
137
|
checkLicense,
|
|
125
138
|
recordCall,
|
|
139
|
+
canRun,
|
|
126
140
|
getUpgradeMessage,
|
|
127
141
|
verifyLicenseKey,
|
|
128
142
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "correctover-scan",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "MCP security scanner ā 1 command, 14 OWASP AISVS 1.0 checks. Detect RCE, SSRF, credential exposure
|
|
3
|
+
"version": "1.4.0",
|
|
4
|
+
"description": "MCP security scanner ā 1 command, 14 OWASP AISVS 1.0 checks. Detect RCE, SSRF, credential exposure. Free: 30 checks/month.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"correctover-scan": "./index.js"
|