@aegis-scan/core 0.2.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/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +111 -0
- package/dist/config.js.map +1 -0
- package/dist/detect.d.ts +3 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +250 -0
- package/dist/detect.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/orchestrator.d.ts +7 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +101 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/scoring.d.ts +15 -0
- package/dist/scoring.d.ts.map +1 -0
- package/dist/scoring.js +130 -0
- package/dist/scoring.js.map +1 -0
- package/dist/types.d.ts +81 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +37 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +123 -0
- package/dist/utils.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +20 -0
- package/dist/version.js.map +1 -0
- package/package.json +45 -0
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AegisConfig } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Shape of a user-provided config file (aegis.config.json).
|
|
4
|
+
* `projectPath` and `mode` are always set by CLI args, never from the file.
|
|
5
|
+
*/
|
|
6
|
+
export type ConfigFileShape = Partial<Omit<AegisConfig, 'projectPath' | 'mode'>>;
|
|
7
|
+
export declare function loadConfig(projectPath: string, mode?: AegisConfig['mode']): Promise<AegisConfig>;
|
|
8
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,YAAY,CAAC;AA8C7D;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC;AA8BjF,wBAAsB,UAAU,CAC9B,WAAW,EAAE,MAAM,EACnB,IAAI,GAAE,WAAW,CAAC,MAAM,CAAU,GACjC,OAAO,CAAC,WAAW,CAAC,CA0CtB"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { detectStack } from './detect.js';
|
|
5
|
+
const ConfigFileSchema = z.object({
|
|
6
|
+
stack: z.object({
|
|
7
|
+
framework: z.string().optional(),
|
|
8
|
+
database: z.string().optional(),
|
|
9
|
+
auth: z.string().optional(),
|
|
10
|
+
ai: z.string().optional(),
|
|
11
|
+
payment: z.string().optional(),
|
|
12
|
+
deploy: z.string().optional(),
|
|
13
|
+
language: z.string().optional(),
|
|
14
|
+
hasI18n: z.boolean().optional(),
|
|
15
|
+
hasTests: z.boolean().optional(),
|
|
16
|
+
}).optional(),
|
|
17
|
+
locale: z.string().optional(),
|
|
18
|
+
compliance: z.array(z.string()).optional(),
|
|
19
|
+
scanners: z.record(z.record(z.unknown())).optional(),
|
|
20
|
+
rules: z.record(z.string()).optional(),
|
|
21
|
+
ignore: z.array(z.string()).optional(),
|
|
22
|
+
target: z.string().optional(),
|
|
23
|
+
}).strict();
|
|
24
|
+
const DEFAULT_IGNORE = [
|
|
25
|
+
'node_modules',
|
|
26
|
+
'.git',
|
|
27
|
+
'.next',
|
|
28
|
+
'.nuxt',
|
|
29
|
+
'dist',
|
|
30
|
+
'build',
|
|
31
|
+
'coverage',
|
|
32
|
+
'.turbo',
|
|
33
|
+
'.vercel',
|
|
34
|
+
'.cache',
|
|
35
|
+
'out',
|
|
36
|
+
'.output',
|
|
37
|
+
'__pycache__',
|
|
38
|
+
'.pytest_cache',
|
|
39
|
+
'.venv',
|
|
40
|
+
'venv',
|
|
41
|
+
'vendor',
|
|
42
|
+
'target',
|
|
43
|
+
'.gradle',
|
|
44
|
+
'.idea',
|
|
45
|
+
'.vscode',
|
|
46
|
+
];
|
|
47
|
+
/**
|
|
48
|
+
* Attempt to load aegis.config.json from the project directory.
|
|
49
|
+
* Only JSON config is supported — JS config files are not loaded to avoid
|
|
50
|
+
* arbitrary code execution.
|
|
51
|
+
*/
|
|
52
|
+
async function loadConfigFile(projectPath) {
|
|
53
|
+
const jsonPath = path.join(projectPath, 'aegis.config.json');
|
|
54
|
+
if (fs.existsSync(jsonPath)) {
|
|
55
|
+
try {
|
|
56
|
+
const raw = fs.readFileSync(jsonPath, 'utf-8');
|
|
57
|
+
const parsed = JSON.parse(raw);
|
|
58
|
+
const result = ConfigFileSchema.safeParse(parsed);
|
|
59
|
+
if (result.success) {
|
|
60
|
+
return result.data;
|
|
61
|
+
}
|
|
62
|
+
// Validation failed — log warning but don't crash, fall back to auto-detection
|
|
63
|
+
console.warn(`[aegis] Config validation warning in ${jsonPath}: ${result.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join(', ')}. Falling back to auto-detection.`);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Malformed JSON — fall through
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
export async function loadConfig(projectPath, mode = 'scan') {
|
|
73
|
+
if (!fs.existsSync(projectPath)) {
|
|
74
|
+
throw new Error(`Project path does not exist: ${projectPath}`);
|
|
75
|
+
}
|
|
76
|
+
const stack = detectStack(projectPath);
|
|
77
|
+
const config = {
|
|
78
|
+
projectPath,
|
|
79
|
+
stack,
|
|
80
|
+
mode,
|
|
81
|
+
ignore: [...DEFAULT_IGNORE],
|
|
82
|
+
};
|
|
83
|
+
// Load and merge user config file (values override auto-detected)
|
|
84
|
+
const fileConfig = await loadConfigFile(projectPath);
|
|
85
|
+
if (fileConfig) {
|
|
86
|
+
if (fileConfig.stack) {
|
|
87
|
+
config.stack = { ...stack, ...fileConfig.stack };
|
|
88
|
+
}
|
|
89
|
+
if (fileConfig.locale !== undefined) {
|
|
90
|
+
config.locale = fileConfig.locale;
|
|
91
|
+
}
|
|
92
|
+
if (fileConfig.compliance !== undefined) {
|
|
93
|
+
config.compliance = fileConfig.compliance;
|
|
94
|
+
}
|
|
95
|
+
if (fileConfig.scanners !== undefined) {
|
|
96
|
+
config.scanners = fileConfig.scanners;
|
|
97
|
+
}
|
|
98
|
+
if (fileConfig.rules !== undefined) {
|
|
99
|
+
config.rules = fileConfig.rules;
|
|
100
|
+
}
|
|
101
|
+
if (fileConfig.ignore !== undefined) {
|
|
102
|
+
// Merge with defaults — never lose node_modules/.git protection
|
|
103
|
+
config.ignore = [...new Set([...DEFAULT_IGNORE, ...fileConfig.ignore])];
|
|
104
|
+
}
|
|
105
|
+
if (fileConfig.target !== undefined) {
|
|
106
|
+
config.target = fileConfig.target;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return config;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAChC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC/B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC3B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACzB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC9B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC7B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC/B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAC/B,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;KACjC,CAAC,CAAC,QAAQ,EAAE;IACb,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC1C,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;IACpD,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACtC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACtC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC,CAAC,MAAM,EAAE,CAAC;AAEZ,MAAM,cAAc,GAAG;IACrB,cAAc;IACd,MAAM;IACN,OAAO;IACP,OAAO;IACP,MAAM;IACN,OAAO;IACP,UAAU;IACV,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,KAAK;IACL,SAAS;IACT,aAAa;IACb,eAAe;IACf,OAAO;IACP,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,OAAO;IACP,SAAS;CACV,CAAC;AAQF;;;;GAIG;AACH,KAAK,UAAU,cAAc,CAAC,WAAmB;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAC7D,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/B,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YAClD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,OAAO,MAAM,CAAC,IAAuB,CAAC;YACxC,CAAC;YACD,+EAA+E;YAC/E,OAAO,CAAC,IAAI,CACV,wCAAwC,QAAQ,KAAK,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,mCAAmC,CACvK,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,gCAAgC;QAClC,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,WAAmB,EACnB,OAA4B,MAAM;IAElC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,gCAAgC,WAAW,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IAEvC,MAAM,MAAM,GAAgB;QAC1B,WAAW;QACX,KAAK;QACL,IAAI;QACJ,MAAM,EAAE,CAAC,GAAG,cAAc,CAAC;KAC5B,CAAC;IAEF,kEAAkE;IAClE,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,CAAC;IACrD,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;YACrB,MAAM,CAAC,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,GAAG,UAAU,CAAC,KAAK,EAAmB,CAAC;QACpE,CAAC;QACD,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACpC,MAAM,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;QACpC,CAAC;QACD,IAAI,UAAU,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACxC,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC;QAC5C,CAAC;QACD,IAAI,UAAU,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACtC,MAAM,CAAC,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC;QACxC,CAAC;QACD,IAAI,UAAU,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC;QAClC,CAAC;QACD,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACpC,gEAAgE;YAChE,MAAM,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,cAAc,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACpC,MAAM,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;QACpC,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/detect.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAuBhD,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,CAoM9D"}
|
package/dist/detect.js
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
function readJsonSafe(filePath) {
|
|
4
|
+
try {
|
|
5
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
6
|
+
return JSON.parse(content);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return {};
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function readFileSafe(filePath) {
|
|
13
|
+
try {
|
|
14
|
+
return fs.readFileSync(filePath, 'utf-8');
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function hasDep(deps, ...names) {
|
|
21
|
+
return names.some((n) => n in deps);
|
|
22
|
+
}
|
|
23
|
+
export function detectStack(projectPath) {
|
|
24
|
+
const pkgPath = path.join(projectPath, 'package.json');
|
|
25
|
+
const pkg = readJsonSafe(pkgPath);
|
|
26
|
+
const deps = {
|
|
27
|
+
...(pkg['dependencies'] ?? {}),
|
|
28
|
+
...(pkg['devDependencies'] ?? {}),
|
|
29
|
+
};
|
|
30
|
+
// ---- Language ----
|
|
31
|
+
let language = 'unknown';
|
|
32
|
+
if (fs.existsSync(path.join(projectPath, 'tsconfig.json')) || hasDep(deps, 'typescript')) {
|
|
33
|
+
language = 'typescript';
|
|
34
|
+
}
|
|
35
|
+
else if (fs.existsSync(path.join(projectPath, 'package.json'))) {
|
|
36
|
+
language = 'javascript';
|
|
37
|
+
}
|
|
38
|
+
else if (fs.existsSync(path.join(projectPath, 'requirements.txt')) || fs.existsSync(path.join(projectPath, 'pyproject.toml'))) {
|
|
39
|
+
language = 'python';
|
|
40
|
+
}
|
|
41
|
+
else if (fs.existsSync(path.join(projectPath, 'Gemfile'))) {
|
|
42
|
+
language = 'ruby';
|
|
43
|
+
}
|
|
44
|
+
else if (fs.existsSync(path.join(projectPath, 'go.mod'))) {
|
|
45
|
+
language = 'go';
|
|
46
|
+
}
|
|
47
|
+
else if (fs.existsSync(path.join(projectPath, 'Cargo.toml'))) {
|
|
48
|
+
language = 'rust';
|
|
49
|
+
}
|
|
50
|
+
else if (fs.existsSync(path.join(projectPath, 'composer.json'))) {
|
|
51
|
+
language = 'php';
|
|
52
|
+
}
|
|
53
|
+
else if (fs.existsSync(path.join(projectPath, 'pom.xml')) || fs.existsSync(path.join(projectPath, 'build.gradle'))) {
|
|
54
|
+
language = 'java';
|
|
55
|
+
}
|
|
56
|
+
// ---- Framework ----
|
|
57
|
+
let framework = 'unknown';
|
|
58
|
+
// Check Node/JS frameworks first
|
|
59
|
+
if (hasDep(deps, 'next')) {
|
|
60
|
+
framework = 'nextjs';
|
|
61
|
+
}
|
|
62
|
+
else if (hasDep(deps, 'nuxt', '@nuxt/core')) {
|
|
63
|
+
framework = 'nuxt';
|
|
64
|
+
}
|
|
65
|
+
else if (hasDep(deps, '@remix-run/react', '@remix-run/node', '@remix-run/serve')) {
|
|
66
|
+
framework = 'remix';
|
|
67
|
+
}
|
|
68
|
+
else if (hasDep(deps, 'astro')) {
|
|
69
|
+
framework = 'astro';
|
|
70
|
+
}
|
|
71
|
+
else if (hasDep(deps, 'svelte', '@sveltejs/kit')) {
|
|
72
|
+
framework = 'svelte';
|
|
73
|
+
}
|
|
74
|
+
else if (hasDep(deps, 'vue', '@vue/core')) {
|
|
75
|
+
framework = 'vue';
|
|
76
|
+
}
|
|
77
|
+
else if (hasDep(deps, 'react', 'react-dom')) {
|
|
78
|
+
framework = 'react';
|
|
79
|
+
}
|
|
80
|
+
else if (hasDep(deps, 'fastify')) {
|
|
81
|
+
framework = 'fastify';
|
|
82
|
+
}
|
|
83
|
+
else if (hasDep(deps, 'express')) {
|
|
84
|
+
framework = 'express';
|
|
85
|
+
}
|
|
86
|
+
else if (fs.existsSync(path.join(projectPath, 'go.mod'))) {
|
|
87
|
+
framework = 'go';
|
|
88
|
+
}
|
|
89
|
+
else if (fs.existsSync(path.join(projectPath, 'Cargo.toml'))) {
|
|
90
|
+
framework = 'rust';
|
|
91
|
+
}
|
|
92
|
+
else if (fs.existsSync(path.join(projectPath, 'requirements.txt')) || fs.existsSync(path.join(projectPath, 'pyproject.toml'))) {
|
|
93
|
+
const reqContent = readFileSafe(path.join(projectPath, 'requirements.txt'));
|
|
94
|
+
const pyprojectContent = readFileSafe(path.join(projectPath, 'pyproject.toml'));
|
|
95
|
+
const combined = reqContent + pyprojectContent;
|
|
96
|
+
if (/\bdjango\b/i.test(combined)) {
|
|
97
|
+
framework = 'django';
|
|
98
|
+
}
|
|
99
|
+
else if (/\bflask\b/i.test(combined)) {
|
|
100
|
+
framework = 'flask';
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else if (fs.existsSync(path.join(projectPath, 'Gemfile'))) {
|
|
104
|
+
const gemfileContent = readFileSafe(path.join(projectPath, 'Gemfile'));
|
|
105
|
+
if (/\brails\b/i.test(gemfileContent)) {
|
|
106
|
+
framework = 'rails';
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else if (fs.existsSync(path.join(projectPath, 'composer.json'))) {
|
|
110
|
+
const composer = readJsonSafe(path.join(projectPath, 'composer.json'));
|
|
111
|
+
const composerDeps = {
|
|
112
|
+
...(composer['require'] ?? {}),
|
|
113
|
+
...(composer['require-dev'] ?? {}),
|
|
114
|
+
};
|
|
115
|
+
if (hasDep(composerDeps, 'laravel/framework')) {
|
|
116
|
+
framework = 'laravel';
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// ---- Database ----
|
|
120
|
+
let database = 'unknown';
|
|
121
|
+
if (hasDep(deps, '@supabase/supabase-js', '@supabase/ssr', '@supabase/auth-helpers-nextjs')) {
|
|
122
|
+
database = 'supabase';
|
|
123
|
+
}
|
|
124
|
+
else if (hasDep(deps, 'firebase', 'firebase-admin', '@firebase/firestore')) {
|
|
125
|
+
database = 'firebase';
|
|
126
|
+
}
|
|
127
|
+
else if (hasDep(deps, '@prisma/client', 'prisma')) {
|
|
128
|
+
database = 'prisma';
|
|
129
|
+
}
|
|
130
|
+
else if (hasDep(deps, 'drizzle-orm', 'drizzle-kit')) {
|
|
131
|
+
database = 'drizzle';
|
|
132
|
+
}
|
|
133
|
+
else if (hasDep(deps, 'mongoose')) {
|
|
134
|
+
database = 'mongoose';
|
|
135
|
+
}
|
|
136
|
+
else if (hasDep(deps, 'pg', 'postgres', 'node-postgres')) {
|
|
137
|
+
database = 'raw-pg';
|
|
138
|
+
}
|
|
139
|
+
else if (!fs.existsSync(path.join(projectPath, 'package.json')) &&
|
|
140
|
+
(fs.existsSync(path.join(projectPath, 'requirements.txt')) || fs.existsSync(path.join(projectPath, 'Gemfile')))) {
|
|
141
|
+
database = 'none';
|
|
142
|
+
}
|
|
143
|
+
// ---- Auth ----
|
|
144
|
+
let auth = 'unknown';
|
|
145
|
+
if (hasDep(deps, '@supabase/supabase-js', '@supabase/ssr', '@supabase/auth-helpers-nextjs')) {
|
|
146
|
+
auth = 'supabase-auth';
|
|
147
|
+
}
|
|
148
|
+
else if (hasDep(deps, 'next-auth', '@auth/core', '@auth/nextjs')) {
|
|
149
|
+
auth = 'next-auth';
|
|
150
|
+
}
|
|
151
|
+
else if (hasDep(deps, '@clerk/nextjs', '@clerk/clerk-react', '@clerk/clerk-sdk-node')) {
|
|
152
|
+
auth = 'clerk';
|
|
153
|
+
}
|
|
154
|
+
else if (hasDep(deps, 'lucia')) {
|
|
155
|
+
auth = 'lucia';
|
|
156
|
+
}
|
|
157
|
+
else if (hasDep(deps, 'passport', 'passport-local', 'passport-jwt')) {
|
|
158
|
+
auth = 'passport';
|
|
159
|
+
}
|
|
160
|
+
// ---- AI ----
|
|
161
|
+
let ai = 'unknown';
|
|
162
|
+
if (hasDep(deps, 'openai', '@openai/openai')) {
|
|
163
|
+
ai = 'openai';
|
|
164
|
+
}
|
|
165
|
+
else if (hasDep(deps, '@anthropic-ai/sdk', 'anthropic')) {
|
|
166
|
+
ai = 'anthropic';
|
|
167
|
+
}
|
|
168
|
+
else if (hasDep(deps, '@mistralai/mistralai', 'mistral', 'mistralai')) {
|
|
169
|
+
ai = 'mistral';
|
|
170
|
+
}
|
|
171
|
+
else if (hasDep(deps, 'ollama', '@ollama/ollama')) {
|
|
172
|
+
ai = 'ollama';
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
// Check Python requirements for AI libs
|
|
176
|
+
const reqContent = readFileSafe(path.join(projectPath, 'requirements.txt'));
|
|
177
|
+
if (/\bopenai\b/i.test(reqContent)) {
|
|
178
|
+
ai = 'openai';
|
|
179
|
+
}
|
|
180
|
+
else if (/\banthropic\b/i.test(reqContent)) {
|
|
181
|
+
ai = 'anthropic';
|
|
182
|
+
}
|
|
183
|
+
else if (/\bmistral/i.test(reqContent)) {
|
|
184
|
+
ai = 'mistral';
|
|
185
|
+
}
|
|
186
|
+
else if (/\bollama\b/i.test(reqContent)) {
|
|
187
|
+
ai = 'ollama';
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
ai = 'none';
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// ---- Payment ----
|
|
194
|
+
let payment = 'unknown';
|
|
195
|
+
if (hasDep(deps, 'stripe', '@stripe/stripe-js', '@stripe/react-stripe-js')) {
|
|
196
|
+
payment = 'stripe';
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
const reqContent = readFileSafe(path.join(projectPath, 'requirements.txt'));
|
|
200
|
+
if (/\bstripe\b/i.test(reqContent)) {
|
|
201
|
+
payment = 'stripe';
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
payment = 'none';
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// ---- Deploy ----
|
|
208
|
+
let deploy = 'unknown';
|
|
209
|
+
if (fs.existsSync(path.join(projectPath, 'vercel.json')) || fs.existsSync(path.join(projectPath, '.vercel'))) {
|
|
210
|
+
deploy = 'vercel';
|
|
211
|
+
}
|
|
212
|
+
else if (fs.existsSync(path.join(projectPath, 'Dockerfile')) || fs.existsSync(path.join(projectPath, 'docker-compose.yml')) || fs.existsSync(path.join(projectPath, 'docker-compose.yaml'))) {
|
|
213
|
+
deploy = 'docker';
|
|
214
|
+
}
|
|
215
|
+
else if (fs.existsSync(path.join(projectPath, 'railway.toml')) || fs.existsSync(path.join(projectPath, 'railway.json'))) {
|
|
216
|
+
deploy = 'railway';
|
|
217
|
+
}
|
|
218
|
+
else if (fs.existsSync(path.join(projectPath, 'fly.toml'))) {
|
|
219
|
+
deploy = 'fly';
|
|
220
|
+
}
|
|
221
|
+
else if (fs.existsSync(path.join(projectPath, 'netlify.toml'))) {
|
|
222
|
+
deploy = 'netlify';
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
deploy = 'none';
|
|
226
|
+
}
|
|
227
|
+
// ---- i18n ----
|
|
228
|
+
const hasI18n = hasDep(deps, 'next-intl', 'react-i18next', 'i18next', 'vue-i18n', '@nuxtjs/i18n', 'react-intl', 'lingui') ||
|
|
229
|
+
fs.existsSync(path.join(projectPath, 'messages')) ||
|
|
230
|
+
fs.existsSync(path.join(projectPath, 'locales')) ||
|
|
231
|
+
fs.existsSync(path.join(projectPath, 'i18n'));
|
|
232
|
+
// ---- Tests ----
|
|
233
|
+
const hasTests = hasDep(deps, 'vitest', 'jest', '@jest/core', 'mocha', 'jasmine', 'playwright', '@playwright/test', 'cypress') ||
|
|
234
|
+
fs.existsSync(path.join(projectPath, '__tests__')) ||
|
|
235
|
+
fs.existsSync(path.join(projectPath, 'tests')) ||
|
|
236
|
+
fs.existsSync(path.join(projectPath, 'spec')) ||
|
|
237
|
+
fs.existsSync(path.join(projectPath, 'e2e'));
|
|
238
|
+
return {
|
|
239
|
+
framework,
|
|
240
|
+
database,
|
|
241
|
+
auth,
|
|
242
|
+
ai,
|
|
243
|
+
payment,
|
|
244
|
+
deploy,
|
|
245
|
+
language,
|
|
246
|
+
hasI18n,
|
|
247
|
+
hasTests,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=detect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../src/detect.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export { detectStack } from './detect.js';
|
|
3
|
+
export { calculateScore, getGrade, getBadge, CATEGORY_WEIGHTS } from './scoring.js';
|
|
4
|
+
export { loadConfig, type ConfigFileShape } from './config.js';
|
|
5
|
+
export { Orchestrator } from './orchestrator.js';
|
|
6
|
+
export { exec, commandExists, walkFiles, readFileSafe, clearWalkFilesCache, type ExecResult, type ExecOptions } from './utils.js';
|
|
7
|
+
export { getVersion } from './version.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACpF,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,mBAAmB,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAClI,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export { detectStack } from './detect.js';
|
|
3
|
+
export { calculateScore, getGrade, getBadge, CATEGORY_WEIGHTS } from './scoring.js';
|
|
4
|
+
export { loadConfig } from './config.js';
|
|
5
|
+
export { Orchestrator } from './orchestrator.js';
|
|
6
|
+
export { exec, commandExists, walkFiles, readFileSafe, clearWalkFilesCache } from './utils.js';
|
|
7
|
+
export { getVersion } from './version.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACpF,OAAO,EAAE,UAAU,EAAwB,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,mBAAmB,EAAqC,MAAM,YAAY,CAAC;AAClI,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAmC,MAAM,YAAY,CAAC;AAcrG,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAiB;IAEjC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI1B,GAAG,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;CAiGrD"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { calculateScore } from './scoring.js';
|
|
2
|
+
const SCANNER_TIMEOUT_MS = 120_000; // 2 minutes per scanner
|
|
3
|
+
function withTimeout(promise, ms, label) {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
const timer = setTimeout(() => reject(new Error(`Scanner '${label}' timed out after ${ms / 1000}s`)), ms);
|
|
6
|
+
promise.then((val) => { clearTimeout(timer); resolve(val); }, (err) => { clearTimeout(timer); reject(err); });
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
export class Orchestrator {
|
|
10
|
+
scanners = [];
|
|
11
|
+
register(scanner) {
|
|
12
|
+
this.scanners.push(scanner);
|
|
13
|
+
}
|
|
14
|
+
async run(config) {
|
|
15
|
+
const startTime = Date.now();
|
|
16
|
+
// Check availability and run all scanners in parallel
|
|
17
|
+
const scanPromises = this.scanners.map(async (scanner) => {
|
|
18
|
+
let available;
|
|
19
|
+
try {
|
|
20
|
+
available = await scanner.isAvailable(config.projectPath);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
available = false;
|
|
24
|
+
}
|
|
25
|
+
if (!available) {
|
|
26
|
+
return {
|
|
27
|
+
scanner: scanner.name,
|
|
28
|
+
category: scanner.category,
|
|
29
|
+
findings: [],
|
|
30
|
+
duration: 0,
|
|
31
|
+
available: false,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const scanStart = Date.now();
|
|
35
|
+
try {
|
|
36
|
+
const result = await withTimeout(scanner.scan(config.projectPath, config), SCANNER_TIMEOUT_MS, scanner.name);
|
|
37
|
+
return {
|
|
38
|
+
...result,
|
|
39
|
+
available: true,
|
|
40
|
+
duration: result.duration ?? Date.now() - scanStart,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
return {
|
|
45
|
+
scanner: scanner.name,
|
|
46
|
+
category: scanner.category,
|
|
47
|
+
findings: [],
|
|
48
|
+
duration: Date.now() - scanStart,
|
|
49
|
+
available: true,
|
|
50
|
+
error: err instanceof Error ? err.message : String(err),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
const scanResults = await Promise.all(scanPromises);
|
|
55
|
+
// Aggregate and deduplicate findings (same file + line + title = duplicate)
|
|
56
|
+
const rawFindings = scanResults.flatMap((r) => r.findings);
|
|
57
|
+
const seen = new Set();
|
|
58
|
+
const allFindings = [];
|
|
59
|
+
for (const f of rawFindings) {
|
|
60
|
+
const key = `${f.file ?? ''}:${f.line ?? 0}:${f.title}`;
|
|
61
|
+
if (!seen.has(key)) {
|
|
62
|
+
seen.add(key);
|
|
63
|
+
allFindings.push(f);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Calculate confidence based on SECURITY-focused external tools.
|
|
67
|
+
// npm-audit, react-doctor, license-checker are always available (built-in node tools)
|
|
68
|
+
// and don't indicate real external security tool installation.
|
|
69
|
+
const SECURITY_EXTERNAL_NAMES = ['semgrep', 'gitleaks', 'nuclei', 'trivy', 'testssl', 'zap', 'trufflehog'];
|
|
70
|
+
const securityExternals = scanResults.filter((r) => SECURITY_EXTERNAL_NAMES.includes(r.scanner));
|
|
71
|
+
const securityAvailable = securityExternals.filter((r) => r.available).length;
|
|
72
|
+
let confidence;
|
|
73
|
+
if (securityAvailable >= 2) {
|
|
74
|
+
confidence = 'high';
|
|
75
|
+
}
|
|
76
|
+
else if (securityAvailable >= 1) {
|
|
77
|
+
confidence = 'medium';
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
confidence = 'low';
|
|
81
|
+
}
|
|
82
|
+
// Calculate score (confidence is passed so scoring can cap grade when low)
|
|
83
|
+
const scoreResult = calculateScore(allFindings, confidence);
|
|
84
|
+
const duration = Date.now() - startTime;
|
|
85
|
+
return {
|
|
86
|
+
score: scoreResult.score,
|
|
87
|
+
grade: scoreResult.grade,
|
|
88
|
+
badge: scoreResult.badge,
|
|
89
|
+
blocked: scoreResult.blocked,
|
|
90
|
+
blockerReason: scoreResult.blockerReason,
|
|
91
|
+
breakdown: scoreResult.breakdown,
|
|
92
|
+
findings: allFindings,
|
|
93
|
+
scanResults,
|
|
94
|
+
stack: config.stack,
|
|
95
|
+
duration,
|
|
96
|
+
timestamp: new Date().toISOString(),
|
|
97
|
+
confidence,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=orchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Finding, ScanCategory, Grade, Badge, AuditResult, Confidence } from './types.js';
|
|
2
|
+
export declare const CATEGORY_WEIGHTS: Record<ScanCategory, number>;
|
|
3
|
+
export declare function getGrade(score: number): Grade;
|
|
4
|
+
export declare function getBadge(grade: Grade): Badge;
|
|
5
|
+
export interface ScoreResult {
|
|
6
|
+
score: number;
|
|
7
|
+
grade: Grade;
|
|
8
|
+
badge: Badge;
|
|
9
|
+
blocked: boolean;
|
|
10
|
+
blockerReason?: string;
|
|
11
|
+
breakdown: AuditResult['breakdown'];
|
|
12
|
+
confidence: Confidence;
|
|
13
|
+
}
|
|
14
|
+
export declare function calculateScore(findings: Finding[], confidence?: Confidence): ScoreResult;
|
|
15
|
+
//# sourceMappingURL=scoring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoring.d.ts","sourceRoot":"","sources":["../src/scoring.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAK/F,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAazD,CAAC;AAYF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAO7C;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAU5C;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IACpC,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,UAAU,GAAE,UAAmB,GAAG,WAAW,CAuDhG"}
|
package/dist/scoring.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// Spec-specified relative weights. These do NOT need to sum to 1.0 here;
|
|
2
|
+
// calculateScore normalizes by dividing each weight by the sum so the
|
|
3
|
+
// final score is always on a 0–1000 scale regardless.
|
|
4
|
+
export const CATEGORY_WEIGHTS = {
|
|
5
|
+
security: 0.20,
|
|
6
|
+
dast: 0.10,
|
|
7
|
+
dependencies: 0.10,
|
|
8
|
+
compliance: 0.10,
|
|
9
|
+
quality: 0.075,
|
|
10
|
+
infrastructure: 0.075,
|
|
11
|
+
accessibility: 0.05,
|
|
12
|
+
performance: 0.05,
|
|
13
|
+
'ai-llm': 0.05,
|
|
14
|
+
i18n: 0.025,
|
|
15
|
+
runtime: 0.025,
|
|
16
|
+
attack: 0.05,
|
|
17
|
+
};
|
|
18
|
+
/** Base deduction per finding severity. Actual deduction uses diminishing returns. */
|
|
19
|
+
const SEVERITY_BASE_DEDUCTIONS = {
|
|
20
|
+
blocker: Infinity,
|
|
21
|
+
critical: 40,
|
|
22
|
+
high: 15,
|
|
23
|
+
medium: 5,
|
|
24
|
+
low: 1,
|
|
25
|
+
info: 0,
|
|
26
|
+
};
|
|
27
|
+
export function getGrade(score) {
|
|
28
|
+
if (score >= 950)
|
|
29
|
+
return 'S';
|
|
30
|
+
if (score >= 850)
|
|
31
|
+
return 'A';
|
|
32
|
+
if (score >= 700)
|
|
33
|
+
return 'B';
|
|
34
|
+
if (score >= 500)
|
|
35
|
+
return 'C';
|
|
36
|
+
if (score >= 300)
|
|
37
|
+
return 'D';
|
|
38
|
+
return 'F';
|
|
39
|
+
}
|
|
40
|
+
export function getBadge(grade) {
|
|
41
|
+
const map = {
|
|
42
|
+
S: 'FORTRESS',
|
|
43
|
+
A: 'HARDENED',
|
|
44
|
+
B: 'SOLID',
|
|
45
|
+
C: 'NEEDS_WORK',
|
|
46
|
+
D: 'AT_RISK',
|
|
47
|
+
F: 'CRITICAL',
|
|
48
|
+
};
|
|
49
|
+
return map[grade];
|
|
50
|
+
}
|
|
51
|
+
export function calculateScore(findings, confidence = 'high') {
|
|
52
|
+
// Check for blockers first — scanners are responsible for emitting severity: 'blocker'
|
|
53
|
+
const blockerFinding = findings.find((f) => f.severity === 'blocker');
|
|
54
|
+
if (blockerFinding) {
|
|
55
|
+
const breakdown = buildBreakdown(findings);
|
|
56
|
+
// Force all scores to 0
|
|
57
|
+
for (const cat of Object.keys(breakdown)) {
|
|
58
|
+
breakdown[cat].score = 0;
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
score: 0,
|
|
62
|
+
grade: 'F',
|
|
63
|
+
badge: 'CRITICAL',
|
|
64
|
+
blocked: true,
|
|
65
|
+
blockerReason: `Blocker finding: ${blockerFinding.title} (${blockerFinding.id})`,
|
|
66
|
+
breakdown,
|
|
67
|
+
confidence,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const breakdown = buildBreakdown(findings);
|
|
71
|
+
// Normalize weights so they sum to 1.0, preserving relative ratios
|
|
72
|
+
const weightSum = Object.values(CATEGORY_WEIGHTS).reduce((a, b) => a + b, 0);
|
|
73
|
+
// Calculate weighted total score (0–1000)
|
|
74
|
+
let totalScore = 0;
|
|
75
|
+
for (const [cat, weight] of Object.entries(CATEGORY_WEIGHTS)) {
|
|
76
|
+
const catData = breakdown[cat];
|
|
77
|
+
const catScore = catData.score; // already 0–1000 for this category
|
|
78
|
+
totalScore += catScore * (weight / weightSum);
|
|
79
|
+
}
|
|
80
|
+
// Round to nearest integer
|
|
81
|
+
const score = Math.round(totalScore);
|
|
82
|
+
let grade = getGrade(score);
|
|
83
|
+
let badge = getBadge(grade);
|
|
84
|
+
// Cap grade when confidence is low — S requires comprehensive scanning
|
|
85
|
+
// A is still achievable with low confidence, but S (FORTRESS) requires proof
|
|
86
|
+
if (confidence === 'low' && grade === 'S') {
|
|
87
|
+
grade = 'A';
|
|
88
|
+
badge = getBadge(grade);
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
score,
|
|
92
|
+
grade,
|
|
93
|
+
badge,
|
|
94
|
+
blocked: false,
|
|
95
|
+
breakdown,
|
|
96
|
+
confidence,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function buildBreakdown(findings) {
|
|
100
|
+
// Initialize breakdown with full scores per category
|
|
101
|
+
const breakdown = {};
|
|
102
|
+
for (const cat of Object.keys(CATEGORY_WEIGHTS)) {
|
|
103
|
+
breakdown[cat] = { score: 1000, maxScore: 1000, findings: 0 };
|
|
104
|
+
}
|
|
105
|
+
// Apply deductions per category with diminishing returns.
|
|
106
|
+
// Each subsequent finding of the same category deducts less (1/sqrt(n) scaling).
|
|
107
|
+
// This prevents 40 HIGH findings from completely zeroing a category while
|
|
108
|
+
// still penalizing projects with more findings.
|
|
109
|
+
const categoryFindingCount = {};
|
|
110
|
+
for (const finding of findings) {
|
|
111
|
+
const cat = finding.category;
|
|
112
|
+
if (!(cat in breakdown))
|
|
113
|
+
continue;
|
|
114
|
+
breakdown[cat].findings += 1;
|
|
115
|
+
const baseDeduction = SEVERITY_BASE_DEDUCTIONS[finding.severity] ?? 0;
|
|
116
|
+
if (baseDeduction === Infinity) {
|
|
117
|
+
breakdown[cat].score = 0;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (baseDeduction === 0)
|
|
121
|
+
continue;
|
|
122
|
+
// Diminishing returns: nth finding deducts base / sqrt(n)
|
|
123
|
+
categoryFindingCount[cat] = (categoryFindingCount[cat] ?? 0) + 1;
|
|
124
|
+
const n = categoryFindingCount[cat];
|
|
125
|
+
const actualDeduction = baseDeduction / Math.sqrt(n);
|
|
126
|
+
breakdown[cat].score = Math.max(0, breakdown[cat].score - actualDeduction);
|
|
127
|
+
}
|
|
128
|
+
return breakdown;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=scoring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scoring.js","sourceRoot":"","sources":["../src/scoring.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export type Severity = 'blocker' | 'critical' | 'high' | 'medium' | 'low' | 'info';
|
|
2
|
+
export type ScanCategory = 'security' | 'dast' | 'dependencies' | 'compliance' | 'quality' | 'accessibility' | 'performance' | 'infrastructure' | 'i18n' | 'ai-llm' | 'runtime' | 'attack';
|
|
3
|
+
export interface Finding {
|
|
4
|
+
id: string;
|
|
5
|
+
scanner: string;
|
|
6
|
+
category: ScanCategory;
|
|
7
|
+
severity: Severity;
|
|
8
|
+
title: string;
|
|
9
|
+
description: string;
|
|
10
|
+
file?: string;
|
|
11
|
+
line?: number;
|
|
12
|
+
column?: number;
|
|
13
|
+
fix?: string;
|
|
14
|
+
owasp?: string;
|
|
15
|
+
cwe?: number;
|
|
16
|
+
reference?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ScanResult {
|
|
19
|
+
scanner: string;
|
|
20
|
+
category: ScanCategory;
|
|
21
|
+
findings: Finding[];
|
|
22
|
+
score?: number;
|
|
23
|
+
duration: number;
|
|
24
|
+
available: boolean;
|
|
25
|
+
error?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface Scanner {
|
|
28
|
+
name: string;
|
|
29
|
+
description: string;
|
|
30
|
+
category: ScanCategory;
|
|
31
|
+
isAvailable(projectPath: string): Promise<boolean>;
|
|
32
|
+
scan(projectPath: string, config: AegisConfig): Promise<ScanResult>;
|
|
33
|
+
}
|
|
34
|
+
export interface DetectedStack {
|
|
35
|
+
framework: 'nextjs' | 'react' | 'vue' | 'svelte' | 'nuxt' | 'astro' | 'remix' | 'express' | 'fastify' | 'django' | 'flask' | 'rails' | 'laravel' | 'spring' | 'go' | 'rust' | 'unknown';
|
|
36
|
+
database: 'supabase' | 'firebase' | 'prisma' | 'drizzle' | 'mongoose' | 'raw-pg' | 'none' | 'unknown';
|
|
37
|
+
auth: 'supabase-auth' | 'next-auth' | 'clerk' | 'lucia' | 'passport' | 'none' | 'unknown';
|
|
38
|
+
ai: 'openai' | 'anthropic' | 'mistral' | 'ollama' | 'none' | 'unknown';
|
|
39
|
+
payment: 'stripe' | 'none' | 'unknown';
|
|
40
|
+
deploy: 'vercel' | 'docker' | 'railway' | 'fly' | 'netlify' | 'none' | 'unknown';
|
|
41
|
+
language: 'typescript' | 'javascript' | 'python' | 'ruby' | 'go' | 'rust' | 'php' | 'java' | 'unknown';
|
|
42
|
+
hasI18n: boolean;
|
|
43
|
+
hasTests: boolean;
|
|
44
|
+
}
|
|
45
|
+
export interface AegisConfig {
|
|
46
|
+
projectPath: string;
|
|
47
|
+
stack: DetectedStack;
|
|
48
|
+
locale?: string;
|
|
49
|
+
compliance?: string[];
|
|
50
|
+
scanners?: Record<string, Record<string, unknown>>;
|
|
51
|
+
rules?: Record<string, Severity>;
|
|
52
|
+
ignore?: string[];
|
|
53
|
+
target?: string;
|
|
54
|
+
mode: 'scan' | 'audit' | 'pentest' | 'siege' | 'fortress';
|
|
55
|
+
}
|
|
56
|
+
export type Grade = 'S' | 'A' | 'B' | 'C' | 'D' | 'F';
|
|
57
|
+
export type Badge = 'FORTRESS' | 'HARDENED' | 'SOLID' | 'NEEDS_WORK' | 'AT_RISK' | 'CRITICAL';
|
|
58
|
+
export type Confidence = 'low' | 'medium' | 'high';
|
|
59
|
+
export interface AuditResult {
|
|
60
|
+
score: number;
|
|
61
|
+
grade: Grade;
|
|
62
|
+
badge: Badge;
|
|
63
|
+
blocked: boolean;
|
|
64
|
+
blockerReason?: string;
|
|
65
|
+
breakdown: Record<ScanCategory, {
|
|
66
|
+
score: number;
|
|
67
|
+
maxScore: number;
|
|
68
|
+
findings: number;
|
|
69
|
+
}>;
|
|
70
|
+
findings: Finding[];
|
|
71
|
+
scanResults: ScanResult[];
|
|
72
|
+
stack: DetectedStack;
|
|
73
|
+
duration: number;
|
|
74
|
+
timestamp: string;
|
|
75
|
+
confidence: Confidence;
|
|
76
|
+
}
|
|
77
|
+
export interface Reporter {
|
|
78
|
+
name: string;
|
|
79
|
+
format(result: AuditResult): string;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface ExecOptions {
|
|
2
|
+
cwd?: string;
|
|
3
|
+
timeout?: number;
|
|
4
|
+
env?: NodeJS.ProcessEnv;
|
|
5
|
+
}
|
|
6
|
+
export interface ExecResult {
|
|
7
|
+
stdout: string;
|
|
8
|
+
stderr: string;
|
|
9
|
+
exitCode: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Safe child_process.execFile wrapper.
|
|
13
|
+
* ALWAYS resolves — even on non-zero exit codes — so callers can read stdout/stderr
|
|
14
|
+
* from tools that exit 1 when findings exist (gitleaks, semgrep, npm audit, etc.).
|
|
15
|
+
* Only rejects on timeout or signal kill.
|
|
16
|
+
*/
|
|
17
|
+
export declare function exec(command: string, args?: string[], options?: ExecOptions): Promise<ExecResult>;
|
|
18
|
+
/**
|
|
19
|
+
* Checks if a command exists on PATH.
|
|
20
|
+
*/
|
|
21
|
+
export declare function commandExists(command: string): Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* Clears the walkFiles result cache. Useful in tests or between audit runs.
|
|
24
|
+
*/
|
|
25
|
+
export declare function clearWalkFilesCache(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Recursive file walker returning ABSOLUTE paths.
|
|
28
|
+
* Filters by ignored directory names and optional file extensions (without dot).
|
|
29
|
+
* Results are memoized by (dir, ignore, extensions) key for the lifetime of the process
|
|
30
|
+
* or until clearWalkFilesCache() is called.
|
|
31
|
+
*/
|
|
32
|
+
export declare function walkFiles(dir: string, ignore?: string[], extensions?: string[]): string[];
|
|
33
|
+
/**
|
|
34
|
+
* Reads a file, returning null on any failure (file not found, permission denied, etc.).
|
|
35
|
+
*/
|
|
36
|
+
export declare function readFileSafe(filePath: string): string | null;
|
|
37
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAClB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,MAAM,EAAO,EACnB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CA2BrB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQrE;AAMD;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,EACX,MAAM,GAAE,MAAM,EAAO,EACrB,UAAU,GAAE,MAAM,EAAO,GACxB,MAAM,EAAE,CAmDV;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM5D"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as childProcess from 'node:child_process';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
/**
|
|
5
|
+
* Safe child_process.execFile wrapper.
|
|
6
|
+
* ALWAYS resolves — even on non-zero exit codes — so callers can read stdout/stderr
|
|
7
|
+
* from tools that exit 1 when findings exist (gitleaks, semgrep, npm audit, etc.).
|
|
8
|
+
* Only rejects on timeout or signal kill.
|
|
9
|
+
*/
|
|
10
|
+
export function exec(command, args = [], options = {}) {
|
|
11
|
+
const { cwd, timeout = 120_000, env } = options;
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
childProcess.execFile(command, args, {
|
|
14
|
+
cwd,
|
|
15
|
+
timeout,
|
|
16
|
+
maxBuffer: 50 * 1024 * 1024, // 50 MB
|
|
17
|
+
env: env ?? process.env,
|
|
18
|
+
}, (error, stdout, stderr) => {
|
|
19
|
+
if (error && error.killed) {
|
|
20
|
+
reject(new Error(`Command timed out: ${command} ${args.join(' ')}`));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
// Always resolve — non-zero exit is normal for many security tools
|
|
24
|
+
resolve({
|
|
25
|
+
stdout: stdout ?? '',
|
|
26
|
+
stderr: stderr ?? '',
|
|
27
|
+
exitCode: error ? error.code ?? 1 : 0,
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Checks if a command exists on PATH.
|
|
34
|
+
*/
|
|
35
|
+
export async function commandExists(command) {
|
|
36
|
+
try {
|
|
37
|
+
const whichCmd = process.platform === 'win32' ? 'where.exe' : 'which';
|
|
38
|
+
const result = await exec(whichCmd, [command], { timeout: 5000 });
|
|
39
|
+
return result.exitCode === 0;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Module-level cache for walkFiles results — avoids redundant directory traversals
|
|
46
|
+
* when multiple scanners walk the same directories in a single audit run. */
|
|
47
|
+
const _walkFilesCache = new Map();
|
|
48
|
+
/**
|
|
49
|
+
* Clears the walkFiles result cache. Useful in tests or between audit runs.
|
|
50
|
+
*/
|
|
51
|
+
export function clearWalkFilesCache() {
|
|
52
|
+
_walkFilesCache.clear();
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Recursive file walker returning ABSOLUTE paths.
|
|
56
|
+
* Filters by ignored directory names and optional file extensions (without dot).
|
|
57
|
+
* Results are memoized by (dir, ignore, extensions) key for the lifetime of the process
|
|
58
|
+
* or until clearWalkFilesCache() is called.
|
|
59
|
+
*/
|
|
60
|
+
export function walkFiles(dir, ignore = [], extensions = []) {
|
|
61
|
+
const resolvedDir = path.resolve(dir);
|
|
62
|
+
const cacheKey = `${resolvedDir}:${ignore.join(',')}:${extensions.join(',')}`;
|
|
63
|
+
const cached = _walkFilesCache.get(cacheKey);
|
|
64
|
+
if (cached)
|
|
65
|
+
return cached;
|
|
66
|
+
const results = [];
|
|
67
|
+
const visited = new Set();
|
|
68
|
+
function walk(current) {
|
|
69
|
+
// Resolve symlinks to detect cycles
|
|
70
|
+
let realPath;
|
|
71
|
+
try {
|
|
72
|
+
realPath = fs.realpathSync(current);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (visited.has(realPath))
|
|
78
|
+
return;
|
|
79
|
+
visited.add(realPath);
|
|
80
|
+
let entries;
|
|
81
|
+
try {
|
|
82
|
+
entries = fs.readdirSync(current, { withFileTypes: true });
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
for (const entry of entries) {
|
|
88
|
+
const fullPath = path.join(current, entry.name);
|
|
89
|
+
if (entry.isDirectory()) {
|
|
90
|
+
if (ignore.includes(entry.name))
|
|
91
|
+
continue;
|
|
92
|
+
walk(fullPath);
|
|
93
|
+
}
|
|
94
|
+
else if (entry.isFile()) {
|
|
95
|
+
if (extensions.length === 0) {
|
|
96
|
+
results.push(fullPath);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
// Fix: path.extname returns '.ts' — slice(1) removes the dot to match ['ts', 'js']
|
|
100
|
+
const ext = path.extname(entry.name).slice(1);
|
|
101
|
+
if (extensions.includes(ext)) {
|
|
102
|
+
results.push(fullPath);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
walk(resolvedDir);
|
|
109
|
+
_walkFilesCache.set(cacheKey, results);
|
|
110
|
+
return results;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Reads a file, returning null on any failure (file not found, permission denied, etc.).
|
|
114
|
+
*/
|
|
115
|
+
export function readFileSafe(filePath) {
|
|
116
|
+
try {
|
|
117
|
+
return fs.readFileSync(filePath, 'utf-8');
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAMA,wBAAgB,UAAU,IAAI,MAAM,CAYnC"}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { join, dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
let cachedVersion;
|
|
5
|
+
export function getVersion() {
|
|
6
|
+
if (cachedVersion !== undefined)
|
|
7
|
+
return cachedVersion;
|
|
8
|
+
try {
|
|
9
|
+
// Read from cli package.json (the main published package)
|
|
10
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const pkgPath = join(__dirname, '../../cli/package.json');
|
|
12
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
13
|
+
cachedVersion = pkg.version ?? '0.0.0';
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
cachedVersion = '0.0.0';
|
|
17
|
+
}
|
|
18
|
+
return cachedVersion;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,IAAI,aAAiC,CAAC;AAEtC,MAAM,UAAU,UAAU;IACxB,IAAI,aAAa,KAAK,SAAS;QAAE,OAAO,aAAa,CAAC;IACtD,IAAI,CAAC;QACH,0DAA0D;QAC1D,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,wBAAwB,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACvD,aAAa,GAAI,GAAG,CAAC,OAAkB,IAAI,OAAO,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,aAAa,GAAG,OAAO,CAAC;IAC1B,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aegis-scan/core",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/RideMatch1/a.e.g.i.s.git",
|
|
8
|
+
"directory": "core"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"keywords": [
|
|
17
|
+
"security",
|
|
18
|
+
"audit",
|
|
19
|
+
"scoring",
|
|
20
|
+
"scanner"
|
|
21
|
+
],
|
|
22
|
+
"description": "AEGIS core engine \u2014 orchestrator, scoring, config",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "dist/index.js",
|
|
25
|
+
"types": "dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"import": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsc",
|
|
34
|
+
"test": "vitest run",
|
|
35
|
+
"clean": "rm -rf dist"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"zod": "^3.23.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^22.0.0",
|
|
42
|
+
"typescript": "^5.8.0",
|
|
43
|
+
"vitest": "^3.1.0"
|
|
44
|
+
}
|
|
45
|
+
}
|