uneven-ai 1.1.8 → 1.1.9
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/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/dist/application/analysis/active/helpers.d.ts.map +1 -1
- package/dist/application/analysis/active/helpers.js +9 -2
- package/dist/cli/commands/pentest.js +1 -1
- package/dist/cli/commands/shell.d.ts.map +1 -1
- package/dist/cli/commands/shell.js +29 -34
- package/dist/cli/shell/intent-classifier.js +2 -2
- package/dist/infrastructure/io/logger/index.d.ts +4 -0
- package/dist/infrastructure/io/logger/index.d.ts.map +1 -1
- package/dist/infrastructure/io/logger/index.js +8 -0
- package/dist/infrastructure/io/process-watcher.d.ts.map +1 -1
- package/dist/infrastructure/io/process-watcher.js +17 -0
- package/dist/infrastructure/license/gate.d.ts +3 -0
- package/dist/infrastructure/license/gate.d.ts.map +1 -1
- package/dist/infrastructure/license/gate.js +17 -0
- package/dist/infrastructure/license/index.d.ts +1 -1
- package/dist/infrastructure/license/index.d.ts.map +1 -1
- package/dist/infrastructure/license/index.js +1 -1
- package/dist/infrastructure/utils/network.d.ts +6 -0
- package/dist/infrastructure/utils/network.d.ts.map +1 -0
- package/dist/infrastructure/utils/network.js +44 -0
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/uneven_core.node +0 -0
- package/prebuilds/linux-arm64/uneven_core.node +0 -0
- package/prebuilds/linux-x64/uneven_core.node +0 -0
- package/prebuilds/win32-x64/uneven_core.node +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ All notable changes to Uneven AI will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.1.9] - 2026-04-27
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Attacker Identification (Uneven Trace)**: Active pentester now injects a silent origin-tracking header (`X-Uneven-Origin-Trace`) containing the attacker's machine IP.
|
|
12
|
+
- **Threat Detection Engine**: Terminal watcher now detects incoming Uneven pentest probes and logs a critical security alert with the source IP.
|
|
13
|
+
- **Portuguese Intent Support**: Shell now recognizes "crie", "faça", "escreva" for AI tasks even in keyword-fallback mode.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- **License Gating**: Active Pentester mode is now restricted to the **Team** plan.
|
|
17
|
+
- **Shell Stability**: Improved intent classification to prevent substring collision (e.g., "mundo" no longer triggers "undo").
|
|
18
|
+
- **Success Hints**: Shell now only prints success hints if the underlying command actually returns a success exit code.
|
|
19
|
+
|
|
8
20
|
## [1.1.8] - 2026-04-27
|
|
9
21
|
|
|
10
22
|
### Added
|
package/README.md
CHANGED
|
@@ -158,7 +158,7 @@ uneven-ai ci
|
|
|
158
158
|
Run `uneven-ai` with no arguments to open the interactive shell:
|
|
159
159
|
|
|
160
160
|
```
|
|
161
|
-
◈ Uneven AI v1.1.
|
|
161
|
+
◈ Uneven AI v1.1.9
|
|
162
162
|
────────────────────────────────────────────────────────────
|
|
163
163
|
Olá! O que posso fazer por você hoje?
|
|
164
164
|
(Escreva sua mensagem ou "sair" para encerrar)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../src/application/analysis/active/helpers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../src/application/analysis/active/helpers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAI5B,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO1F;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC;IAC1F,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;IACtD,IAAI,EAAE,MAAM,CAAA;CACb,CAAC,CA0BD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAChE,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,OAAO,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;CACf,GAAG,IAAI,CAAC,CA8BR;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAY9F"}
|
|
@@ -3,6 +3,7 @@ import * as tls from 'tls';
|
|
|
3
3
|
import * as https from 'https';
|
|
4
4
|
import * as http from 'http';
|
|
5
5
|
import { CONNECT_TIMEOUT_MS, HTTP_TIMEOUT_MS } from './context.js';
|
|
6
|
+
import { getPublicIp } from '../../../infrastructure/utils/network.js';
|
|
6
7
|
export function tcpConnect(host, port, timeoutMs) {
|
|
7
8
|
return new Promise(resolve => {
|
|
8
9
|
const sock = net.createConnection({ host, port });
|
|
@@ -11,10 +12,16 @@ export function tcpConnect(host, port, timeoutMs) {
|
|
|
11
12
|
sock.on('error', () => { clearTimeout(timer); resolve(false); });
|
|
12
13
|
});
|
|
13
14
|
}
|
|
14
|
-
export function httpRequest(options, useHttps) {
|
|
15
|
+
export async function httpRequest(options, useHttps) {
|
|
16
|
+
const ip = await getPublicIp();
|
|
17
|
+
const customHeaders = {
|
|
18
|
+
...options.headers,
|
|
19
|
+
'User-Agent': 'Uneven-Pentester/1.1.9',
|
|
20
|
+
...(ip ? { 'X-Uneven-Origin-Trace': ip } : {})
|
|
21
|
+
};
|
|
15
22
|
return new Promise((resolve, reject) => {
|
|
16
23
|
const mod = useHttps ? https : http;
|
|
17
|
-
const req = mod.request({ ...options, rejectUnauthorized: false }, res => {
|
|
24
|
+
const req = mod.request({ ...options, headers: customHeaders, rejectUnauthorized: false }, res => {
|
|
18
25
|
let body = '';
|
|
19
26
|
res.on('data', (chunk) => { body += chunk.toString('utf-8'); });
|
|
20
27
|
res.on('end', () => resolve({
|
|
@@ -14,7 +14,7 @@ export async function pentestCommand(mode, options = {}) {
|
|
|
14
14
|
const resolvedMode = mode || 'static';
|
|
15
15
|
if (resolvedMode === 'active') {
|
|
16
16
|
const { license } = await import('../../infrastructure/index.js');
|
|
17
|
-
await license.
|
|
17
|
+
await license.requireTeam();
|
|
18
18
|
}
|
|
19
19
|
const ctx = new PentestSecurityContext();
|
|
20
20
|
// ── Handle --declare-scope flag ─────────────────────────────────────────────
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/shell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/shell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAgRH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAgElD"}
|
|
@@ -49,8 +49,8 @@ async function spawnSubcommand(args) {
|
|
|
49
49
|
stdio: 'inherit',
|
|
50
50
|
env: process.env,
|
|
51
51
|
});
|
|
52
|
-
child.on('close', resolve);
|
|
53
|
-
child.on('error', resolve);
|
|
52
|
+
child.on('close', (code) => resolve(code ?? 0));
|
|
53
|
+
child.on('error', () => resolve(1));
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
@@ -66,8 +66,8 @@ async function spawnWatch() {
|
|
|
66
66
|
});
|
|
67
67
|
const onSigint = () => child.kill('SIGTERM');
|
|
68
68
|
process.on('SIGINT', onSigint);
|
|
69
|
-
child.on('close', () => { process.off('SIGINT', onSigint); resolve(); });
|
|
70
|
-
child.on('error', () => { process.off('SIGINT', onSigint); resolve(); });
|
|
69
|
+
child.on('close', (code) => { process.off('SIGINT', onSigint); resolve(code ?? 0); });
|
|
70
|
+
child.on('error', () => { process.off('SIGINT', onSigint); resolve(1); });
|
|
71
71
|
});
|
|
72
72
|
}
|
|
73
73
|
// ─── Background task guard ────────────────────────────────────────────────────
|
|
@@ -121,24 +121,20 @@ async function execute(intent) {
|
|
|
121
121
|
switch (intent.action) {
|
|
122
122
|
case 'index':
|
|
123
123
|
console.log(D('\n ↳ Indexing your project…\n'));
|
|
124
|
-
await spawnSubcommand(['index']);
|
|
125
|
-
break;
|
|
124
|
+
return await spawnSubcommand(['index']);
|
|
126
125
|
case 'scan':
|
|
127
126
|
console.log(D('\n ↳ Scanning for vulnerabilities and malicious patterns…\n'));
|
|
128
|
-
await spawnSubcommand(['scan']);
|
|
129
|
-
break;
|
|
127
|
+
return await spawnSubcommand(['scan']);
|
|
130
128
|
case 'watch':
|
|
131
|
-
await spawnWatch();
|
|
132
|
-
break;
|
|
129
|
+
return await spawnWatch();
|
|
133
130
|
case 'explain': {
|
|
134
131
|
const file = intent.args.file;
|
|
135
132
|
if (!file) {
|
|
136
133
|
console.log(Y('\n Which file should I explain? e.g. "explain src/app.ts"\n'));
|
|
137
|
-
return;
|
|
134
|
+
return 1;
|
|
138
135
|
}
|
|
139
136
|
console.log(D(`\n ↳ Explaining ${file}…\n`));
|
|
140
|
-
await spawnSubcommand(['explain', file]);
|
|
141
|
-
break;
|
|
137
|
+
return await spawnSubcommand(['explain', file]);
|
|
142
138
|
}
|
|
143
139
|
case 'review': {
|
|
144
140
|
const args = ['review'];
|
|
@@ -149,50 +145,47 @@ async function execute(intent) {
|
|
|
149
145
|
if (intent.args.staged)
|
|
150
146
|
args.push('--staged');
|
|
151
147
|
console.log(D('\n ↳ Running code review…\n'));
|
|
152
|
-
await spawnSubcommand(args);
|
|
153
|
-
break;
|
|
148
|
+
return await spawnSubcommand(args);
|
|
154
149
|
}
|
|
155
150
|
case 'docs': {
|
|
156
151
|
const file = intent.args.file;
|
|
157
152
|
if (!file) {
|
|
158
153
|
console.log(Y('\n Which file should I document? e.g. "docs src/parser.ts"\n'));
|
|
159
|
-
return;
|
|
154
|
+
return 1;
|
|
160
155
|
}
|
|
161
156
|
console.log(D(`\n ↳ Generating documentation for ${file}…\n`));
|
|
162
|
-
await spawnSubcommand(['docs', file]);
|
|
163
|
-
break;
|
|
157
|
+
return await spawnSubcommand(['docs', file]);
|
|
164
158
|
}
|
|
165
159
|
case 'askf': {
|
|
166
160
|
const task = intent.args.task;
|
|
167
161
|
console.log(D('\n ↳ Task started in background — keep using the shell.\n'));
|
|
168
162
|
spawnBackground(['askf', task], task);
|
|
169
|
-
|
|
163
|
+
return 0;
|
|
170
164
|
}
|
|
171
165
|
case 'ask': {
|
|
172
166
|
const question = intent.args.question;
|
|
173
167
|
console.log(D('\n ↳ Looking up context…\n'));
|
|
174
|
-
await spawnSubcommand(['ask', question]);
|
|
175
|
-
break;
|
|
168
|
+
return await spawnSubcommand(['ask', question]);
|
|
176
169
|
}
|
|
177
170
|
case 'log':
|
|
178
171
|
console.log(D('\n ↳ Loading activity log…\n'));
|
|
179
|
-
await spawnSubcommand(['log']);
|
|
180
|
-
break;
|
|
172
|
+
return await spawnSubcommand(['log']);
|
|
181
173
|
case 'undo':
|
|
182
174
|
console.log(D('\n ↳ Reverting last fix…\n'));
|
|
183
|
-
await spawnSubcommand(['undo']);
|
|
184
|
-
break;
|
|
175
|
+
return await spawnSubcommand(['undo']);
|
|
185
176
|
case 'help':
|
|
186
177
|
printShellHelp();
|
|
187
|
-
|
|
178
|
+
return 0;
|
|
188
179
|
case 'exit':
|
|
189
|
-
|
|
180
|
+
return 0;
|
|
190
181
|
case 'unknown':
|
|
191
182
|
console.log(Y('\n Not sure what you meant. ') +
|
|
192
183
|
D('I can help with:\n') +
|
|
193
184
|
D(' index · scan · watch · explain <file> · review · docs <file>\n') +
|
|
194
185
|
D(' questions about your project · log · undo · help · exit\n'));
|
|
195
|
-
|
|
186
|
+
return 1;
|
|
187
|
+
default:
|
|
188
|
+
return 1;
|
|
196
189
|
}
|
|
197
190
|
}
|
|
198
191
|
// ─── Shell help ───────────────────────────────────────────────────────────────
|
|
@@ -285,12 +278,14 @@ export async function shellCommand() {
|
|
|
285
278
|
console.log('');
|
|
286
279
|
console.log(A(' ◈ ') + chalk.hex('#e8edf5')(message));
|
|
287
280
|
}
|
|
288
|
-
await execute(intent);
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
281
|
+
const code = await execute(intent);
|
|
282
|
+
if (code === 0) {
|
|
283
|
+
const hint = HINTS[intent.action];
|
|
284
|
+
if (hint) {
|
|
285
|
+
console.log('');
|
|
286
|
+
console.log(G(' ◈ ') + D(hint));
|
|
287
|
+
console.log('');
|
|
288
|
+
}
|
|
294
289
|
}
|
|
295
290
|
}
|
|
296
291
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
12
12
|
function hasAny(low, words) {
|
|
13
|
-
return words.some(w =>
|
|
13
|
+
return words.some(w => new RegExp(`\\b${w}\\b`).test(low));
|
|
14
14
|
}
|
|
15
15
|
// ─── File-path extraction ─────────────────────────────────────────────────────
|
|
16
16
|
export function extractFilePath(input) {
|
|
@@ -53,7 +53,7 @@ export function classifyIntent(raw) {
|
|
|
53
53
|
confidence: 'high',
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
|
-
if (hasAny(low, ['askf']))
|
|
56
|
+
if (hasAny(low, ['askf', 'crie', 'cria', 'criação', 'escreva', 'faça', 'make', 'create']))
|
|
57
57
|
return { action: 'askf', args: { task: input }, confidence: 'high' };
|
|
58
58
|
const file = extractFilePath(input);
|
|
59
59
|
if (file || hasAny(low, ['explain', 'explica']))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/io/logger/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,qBAAa,MAAM;IACjB,OAAO,CAAC,OAAO,CAAQ;IACvB;;;;OAIG;IACH,OAAO,CAAC,UAAU,CAAmC;IACrD,qDAAqD;IACrD,OAAO,CAAC,KAAK,CAAe;gBAEhB,OAAO,GAAE,MAA2B;YAKlC,UAAU;IAexB;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM1C;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM7C;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS3C;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3C;;OAEG;IACG,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/F;;OAEG;IACG,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAahB;;OAEG;IACG,eAAe,CACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC;IAqBhB;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;;OAGG;IACH,OAAO,CAAC,KAAK;CAWd"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/io/logger/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,qBAAa,MAAM;IACjB,OAAO,CAAC,OAAO,CAAQ;IACvB;;;;OAIG;IACH,OAAO,CAAC,UAAU,CAAmC;IACrD,qDAAqD;IACrD,OAAO,CAAC,KAAK,CAAe;gBAEhB,OAAO,GAAE,MAA2B;YAKlC,UAAU;IAexB;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM1C;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM7C;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS3C;;OAEG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM3C;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9C;;OAEG;IACG,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/F;;OAEG;IACG,UAAU,CACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAahB;;OAEG;IACG,eAAe,CACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC;IAqBhB;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B;;;OAGG;IACH,OAAO,CAAC,KAAK;CAWd"}
|
|
@@ -70,6 +70,14 @@ export class Logger {
|
|
|
70
70
|
const entry = `## [${timestamp}] ❌ Error\n\n${message}\n\n---\n\n`;
|
|
71
71
|
await this.write(entry);
|
|
72
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Log critical security alert
|
|
75
|
+
*/
|
|
76
|
+
async critical(message) {
|
|
77
|
+
const timestamp = this.getTimestamp();
|
|
78
|
+
const entry = `## [${timestamp}] 🚨 CRITICAL ALERT\n\n${message}\n\n---\n\n`;
|
|
79
|
+
await this.write(entry);
|
|
80
|
+
}
|
|
73
81
|
/**
|
|
74
82
|
* Log error detection
|
|
75
83
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-watcher.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/io/process-watcher.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,MAAM,EAA4B,MAAM,aAAa,CAAA;AAE9D,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAA;IACnE,SAAS,EAAE,IAAI,CAAA;IACf,IAAI,EAAE,GAAG,CAAA;CACV;AAQD,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,YAAY,CAAY;IAChC,OAAO,CAAC,SAAS,CAA6D;IAC9E,8EAA8E;IAC9E,OAAO,CAAC,YAAY,CAA8B;IAClD,6EAA6E;IAC7E,OAAO,CAAC,WAAW,CAA8B;gBAErC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM;IAKnD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA8C3B;;OAEG;IACH,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI;IAQpE;;OAEG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI;IAIrE;;OAEG;IACH,OAAO,CAAC,SAAS;IAsBjB;;OAEG;IACH,OAAO,CAAC,YAAY;
|
|
1
|
+
{"version":3,"file":"process-watcher.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/io/process-watcher.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,MAAM,EAA4B,MAAM,aAAa,CAAA;AAE9D,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAA;IACnE,SAAS,EAAE,IAAI,CAAA;IACf,IAAI,EAAE,GAAG,CAAA;CACV;AAQD,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,YAAY,CAAY;IAChC,OAAO,CAAC,SAAS,CAA6D;IAC9E,8EAA8E;IAC9E,OAAO,CAAC,YAAY,CAA8B;IAClD,6EAA6E;IAC7E,OAAO,CAAC,WAAW,CAA8B;gBAErC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM;IAKnD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA8C3B;;OAEG;IACH,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI;IAQpE;;OAEG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI;IAIrE;;OAEG;IACH,OAAO,CAAC,SAAS;IAsBjB;;OAEG;IACH,OAAO,CAAC,YAAY;IAsIpB;;OAEG;IACH,OAAO,CAAC,cAAc;IAmCtB;;OAEG;IACH,YAAY,IAAI,OAAO;CAGxB"}
|
|
@@ -178,6 +178,23 @@ export class ProcessWatcher {
|
|
|
178
178
|
fullOutput: text
|
|
179
179
|
});
|
|
180
180
|
}
|
|
181
|
+
// --- Attacker Attribution: Detect Uneven Trace Header ---
|
|
182
|
+
const traceMatch = text.match(/X-Uneven-Origin-Trace[:" ]+([\d.]{7,15})/i);
|
|
183
|
+
if (traceMatch) {
|
|
184
|
+
const attackerIp = traceMatch[1];
|
|
185
|
+
this.logger.critical(`SECURITY ALERT: Attacker identified via Uneven Trace! Origin IP: ${attackerIp}`);
|
|
186
|
+
errors.push({
|
|
187
|
+
type: 'security',
|
|
188
|
+
severity: 'critical',
|
|
189
|
+
file: 'SYSTEM',
|
|
190
|
+
line: 0,
|
|
191
|
+
column: 0,
|
|
192
|
+
message: `URGENT: Incoming pentest probe detected from IP ${attackerIp} using Uneven AI.`,
|
|
193
|
+
code: 'ATTACKER_ID',
|
|
194
|
+
context: [text],
|
|
195
|
+
fullOutput: text
|
|
196
|
+
});
|
|
197
|
+
}
|
|
181
198
|
if (errors.length > 0) {
|
|
182
199
|
this.logger.warning(`Process: Detected ${errors.length} errors in output`);
|
|
183
200
|
this.emitEvent('error', { errors });
|
|
@@ -5,4 +5,7 @@
|
|
|
5
5
|
/** Returns true if the current machine has an active Pro (or Team) license. Never throws. */
|
|
6
6
|
export declare function checkPro(): Promise<boolean>;
|
|
7
7
|
export declare function requirePro(): Promise<void>;
|
|
8
|
+
/** Returns true if the current machine has an active Team license. Never throws. */
|
|
9
|
+
export declare function checkTeam(): Promise<boolean>;
|
|
10
|
+
export declare function requireTeam(): Promise<void>;
|
|
8
11
|
//# sourceMappingURL=gate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/license/gate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,6FAA6F;AAC7F,wBAAsB,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC,CAGjD;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAYhD"}
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/license/gate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,6FAA6F;AAC7F,wBAAsB,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC,CAGjD;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAYhD;AAED,oFAAoF;AACpF,wBAAsB,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAGlD;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAYjD"}
|
|
@@ -21,3 +21,20 @@ export async function requirePro() {
|
|
|
21
21
|
process.exit(1);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
+
/** Returns true if the current machine has an active Team license. Never throws. */
|
|
25
|
+
export async function checkTeam() {
|
|
26
|
+
const license = await check();
|
|
27
|
+
return license.active && license.tier === 'team';
|
|
28
|
+
}
|
|
29
|
+
export async function requireTeam() {
|
|
30
|
+
const license = await check();
|
|
31
|
+
if (license.tier !== 'team' || !license.active) {
|
|
32
|
+
console.log();
|
|
33
|
+
console.log(chalk.hex('#FFD700')(' This feature requires Uneven Team.'));
|
|
34
|
+
console.log();
|
|
35
|
+
console.log(chalk.dim(' Upgrade at: ') + chalk.cyan('https://uneven.dev/pricing'));
|
|
36
|
+
console.log(chalk.dim(' Activate: ') + chalk.cyan('uneven-ai license activate <your-key>'));
|
|
37
|
+
console.log();
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -3,5 +3,5 @@ export * as LicenseManager from './manager.js';
|
|
|
3
3
|
export { parseKey } from './verifier.js';
|
|
4
4
|
export { readLicense, clearLicense } from './storage.js';
|
|
5
5
|
export { getMachineId } from './fingerprint.js';
|
|
6
|
-
export { requirePro, checkPro } from './gate.js';
|
|
6
|
+
export { requirePro, checkPro, requireTeam, checkTeam } from './gate.js';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/license/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAClE,OAAO,KAAK,cAAc,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/license/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAClE,OAAO,KAAK,cAAc,MAAM,cAAc,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA"}
|
|
@@ -3,4 +3,4 @@ export * as LicenseManager from './manager.js';
|
|
|
3
3
|
export { parseKey } from './verifier.js';
|
|
4
4
|
export { readLicense, clearLicense } from './storage.js';
|
|
5
5
|
export { getMachineId } from './fingerprint.js';
|
|
6
|
-
export { requirePro, checkPro } from './gate.js';
|
|
6
|
+
export { requirePro, checkPro, requireTeam, checkTeam } from './gate.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/utils/network.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAqC1D"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as https from 'https';
|
|
2
|
+
let cachedIp = null;
|
|
3
|
+
let lastFetch = 0;
|
|
4
|
+
const CACHE_TTL = 3600000; // 1 hour
|
|
5
|
+
/**
|
|
6
|
+
* Silently fetches the public IP of the current machine.
|
|
7
|
+
* Returns null if it fails or takes more than 1s.
|
|
8
|
+
*/
|
|
9
|
+
export async function getPublicIp() {
|
|
10
|
+
const now = Date.now();
|
|
11
|
+
if (cachedIp && (now - lastFetch < CACHE_TTL)) {
|
|
12
|
+
return cachedIp;
|
|
13
|
+
}
|
|
14
|
+
return new Promise((resolve) => {
|
|
15
|
+
const options = {
|
|
16
|
+
hostname: 'api.ipify.org',
|
|
17
|
+
port: 443,
|
|
18
|
+
path: '/?format=json',
|
|
19
|
+
method: 'GET',
|
|
20
|
+
timeout: 1000 // 1s timeout for "silence"
|
|
21
|
+
};
|
|
22
|
+
const req = https.request(options, (res) => {
|
|
23
|
+
let data = '';
|
|
24
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
25
|
+
res.on('end', () => {
|
|
26
|
+
try {
|
|
27
|
+
const parsed = JSON.parse(data);
|
|
28
|
+
cachedIp = parsed.ip;
|
|
29
|
+
lastFetch = Date.now();
|
|
30
|
+
resolve(cachedIp);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
resolve(null);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
req.on('error', () => resolve(null));
|
|
38
|
+
req.on('timeout', () => {
|
|
39
|
+
req.destroy();
|
|
40
|
+
resolve(null);
|
|
41
|
+
});
|
|
42
|
+
req.end();
|
|
43
|
+
});
|
|
44
|
+
}
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|