relsec 0.1.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.
Files changed (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +376 -0
  3. package/SECURITY.md +36 -0
  4. package/dist/advisories.d.ts +5 -0
  5. package/dist/advisories.js +111 -0
  6. package/dist/advisories.js.map +1 -0
  7. package/dist/cli.d.ts +2 -0
  8. package/dist/cli.js +181 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/config.d.ts +15 -0
  11. package/dist/config.js +50 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/engine.d.ts +8 -0
  14. package/dist/engine.js +76 -0
  15. package/dist/engine.js.map +1 -0
  16. package/dist/interactive.d.ts +58 -0
  17. package/dist/interactive.js +698 -0
  18. package/dist/interactive.js.map +1 -0
  19. package/dist/inventory.d.ts +3 -0
  20. package/dist/inventory.js +27 -0
  21. package/dist/inventory.js.map +1 -0
  22. package/dist/ioc.d.ts +16 -0
  23. package/dist/ioc.js +46 -0
  24. package/dist/ioc.js.map +1 -0
  25. package/dist/manifests.d.ts +10 -0
  26. package/dist/manifests.js +157 -0
  27. package/dist/manifests.js.map +1 -0
  28. package/dist/osv.d.ts +13 -0
  29. package/dist/osv.js +82 -0
  30. package/dist/osv.js.map +1 -0
  31. package/dist/reachability.d.ts +6 -0
  32. package/dist/reachability.js +19 -0
  33. package/dist/reachability.js.map +1 -0
  34. package/dist/report.d.ts +4 -0
  35. package/dist/report.js +74 -0
  36. package/dist/report.js.map +1 -0
  37. package/dist/security-modules.d.ts +14 -0
  38. package/dist/security-modules.js +126 -0
  39. package/dist/security-modules.js.map +1 -0
  40. package/dist/theme.d.ts +43 -0
  41. package/dist/theme.js +191 -0
  42. package/dist/theme.js.map +1 -0
  43. package/dist/types.d.ts +37 -0
  44. package/dist/types.js +2 -0
  45. package/dist/types.js.map +1 -0
  46. package/dist/version-info.d.ts +1 -0
  47. package/dist/version-info.js +2 -0
  48. package/dist/version-info.js.map +1 -0
  49. package/dist/version.d.ts +4 -0
  50. package/dist/version.js +74 -0
  51. package/dist/version.js.map +1 -0
  52. package/docs/RELEASE.md +41 -0
  53. package/package.json +64 -0
@@ -0,0 +1,126 @@
1
+ import { readdir, readFile, stat } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { loadInventory, serviceRoot } from './inventory.js';
4
+ import { discoverDependencies } from './manifests.js';
5
+ const SKIP_DIRS = new Set(['.git', 'node_modules', 'dist', 'build', '.next', 'coverage']);
6
+ export async function scanExposure(input) {
7
+ const inventory = await loadInventory(input.inventory);
8
+ const exposed = inventory.services.filter((service) => service.exposure === 'internet' || service.exposure === 'partner');
9
+ return [
10
+ 'Exposure findings',
11
+ ...exposed.map((service) => `- ${service.name} ${service.exposure} ${service.ingress?.join(', ') ?? ''}`),
12
+ ...(exposed.length === 0 ? ['- no externally exposed services found'] : [])
13
+ ].join('\n');
14
+ }
15
+ export async function scanSbom(input) {
16
+ const inventory = await loadInventory(input.inventory);
17
+ const rows = [];
18
+ for (const service of inventory.services) {
19
+ const deps = await discoverDependencies(serviceRoot(input.workspace, service.path));
20
+ rows.push(...deps.map((dep) => `- ${service.name} ${dep.name}@${dep.version} ${dep.manifestPath}`));
21
+ }
22
+ return ['SBOM inventory', ...(rows.length > 0 ? rows : ['- no dependencies found'])].join('\n');
23
+ }
24
+ export async function scanSecrets(input) {
25
+ const root = path.resolve(input.target ?? input.workspace);
26
+ const files = await walkFiles(root);
27
+ const findings = [];
28
+ const patterns = [
29
+ /AWS_SECRET_ACCESS_KEY\s*=\s*([A-Z0-9/+=]{16,})/i,
30
+ /AKIA[0-9A-Z]{16}/,
31
+ /(api[_-]?key|token|secret)\s*[:=]\s*['"]?([A-Za-z0-9_./+=-]{16,})/i
32
+ ];
33
+ for (const file of files) {
34
+ const text = await safeRead(file);
35
+ if (!text)
36
+ continue;
37
+ text.split(/\r?\n/).forEach((line, index) => {
38
+ for (const pattern of patterns) {
39
+ if (pattern.test(line))
40
+ findings.push(`- ${file}:${index + 1} ${redact(line.trim())}`);
41
+ }
42
+ });
43
+ }
44
+ return ['Secret scan', ...(findings.length > 0 ? findings : ['- no obvious secrets found'])].join('\n');
45
+ }
46
+ export async function scanCloudTrail(input) {
47
+ return scanLogs(input.logs, 'CloudTrail findings', [/ConsoleLogin/i, /AccessDenied/i, /AssumeRole/i, /CreateAccessKey/i]);
48
+ }
49
+ export async function scanAuth(input) {
50
+ return scanLogs(input.logs, 'Auth findings', [/203\.0\.113\.77/, /failed/i, /impossible travel/i, /MFA/i]);
51
+ }
52
+ export async function scanYara(input) {
53
+ if (!input.rule)
54
+ return 'set rule <file> first';
55
+ const ruleText = await readFile(input.rule, 'utf8');
56
+ const ruleName = ruleText.match(/rule\s+([A-Za-z0-9_]+)/)?.[1] ?? path.basename(input.rule);
57
+ const literals = [...ruleText.matchAll(/=\s*"([^"]+)"/g)].map((match) => match[1]).filter(Boolean);
58
+ const matches = await matchLiterals(input.logs, literals);
59
+ return [`YARA ${ruleName}`, ...(matches.length > 0 ? matches : ['- no matches'])].join('\n');
60
+ }
61
+ export async function scanSigma(input) {
62
+ if (!input.rule)
63
+ return 'set rule <file> first';
64
+ const ruleText = await readFile(input.rule, 'utf8');
65
+ const title = ruleText.match(/^title:\s*(.+)$/m)?.[1]?.trim() ?? path.basename(input.rule);
66
+ const literals = [...ruleText.matchAll(/-\s*([A-Za-z0-9_.:-]+\.[A-Za-z0-9_.:-]+)/g)].map((match) => match[1]).filter(Boolean);
67
+ const matches = await matchLiterals(input.logs, literals);
68
+ return [`Sigma ${title}`, ...(matches.length > 0 ? matches : ['- no matches'])].join('\n');
69
+ }
70
+ async function scanLogs(logs, title, patterns) {
71
+ const findings = [];
72
+ for (const log of logs) {
73
+ const text = await safeRead(log);
74
+ if (!text)
75
+ continue;
76
+ text.split(/\r?\n/).forEach((line, index) => {
77
+ if (patterns.some((pattern) => pattern.test(line)))
78
+ findings.push(`- ${log}:${index + 1} ${line.trim()}`);
79
+ });
80
+ }
81
+ return [title, ...(findings.length > 0 ? findings : ['- no findings'])].join('\n');
82
+ }
83
+ async function matchLiterals(files, literals) {
84
+ const findings = [];
85
+ for (const file of files) {
86
+ const text = await safeRead(file);
87
+ if (!text)
88
+ continue;
89
+ text.split(/\r?\n/).forEach((line, index) => {
90
+ for (const literal of literals) {
91
+ if (literal && line.includes(literal))
92
+ findings.push(`- ${file}:${index + 1} ${literal}`);
93
+ }
94
+ });
95
+ }
96
+ return findings;
97
+ }
98
+ async function walkFiles(root) {
99
+ const current = await stat(root);
100
+ if (current.isFile())
101
+ return [root];
102
+ const entries = await readdir(root, { withFileTypes: true });
103
+ const files = [];
104
+ for (const entry of entries) {
105
+ if (entry.isDirectory() && SKIP_DIRS.has(entry.name))
106
+ continue;
107
+ const full = path.join(root, entry.name);
108
+ if (entry.isDirectory())
109
+ files.push(...await walkFiles(full));
110
+ else if (entry.isFile())
111
+ files.push(full);
112
+ }
113
+ return files;
114
+ }
115
+ async function safeRead(file) {
116
+ try {
117
+ return await readFile(file, 'utf8');
118
+ }
119
+ catch {
120
+ return undefined;
121
+ }
122
+ }
123
+ function redact(value) {
124
+ return value.replace(/(=|:\s*['"]?)([A-Za-z0-9/+=_-]{8})[A-Za-z0-9/+=_-]{8,}/g, '$1$2…');
125
+ }
126
+ //# sourceMappingURL=security-modules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-modules.js","sourceRoot":"","sources":["../src/security-modules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { IocScanResult } from './ioc.js';
2
+ import type { RelevanceResult } from './types.js';
3
+ export declare const colors: {
4
+ reset: string;
5
+ bold: string;
6
+ dim: string;
7
+ green: string;
8
+ yellow: string;
9
+ red: string;
10
+ blue: string;
11
+ mauve: string;
12
+ teal: string;
13
+ text: string;
14
+ muted: string;
15
+ };
16
+ export declare function renderBanner(input: {
17
+ workspace: string;
18
+ inventory?: string;
19
+ }): string;
20
+ export declare function renderResultCard(result: RelevanceResult): string;
21
+ export declare function renderIocSummary(result: IocScanResult): string;
22
+ export declare function renderStatus(input: {
23
+ workspace: string;
24
+ inventory?: string;
25
+ indicators?: string;
26
+ format: string;
27
+ lastResult?: RelevanceResult;
28
+ }): string;
29
+ export declare function renderHelp(): string;
30
+ export declare function renderOptions(input: {
31
+ workspace: string;
32
+ inventory?: string;
33
+ indicators?: string;
34
+ format: string;
35
+ module?: string;
36
+ cve?: string;
37
+ logs: string[];
38
+ }): string;
39
+ export declare function renderSet(key: string, value: string): string;
40
+ export declare function renderOk(message: string): string;
41
+ export declare function renderError(message: string): string;
42
+ export declare function prompt(module?: string): string;
43
+ export declare function stripAnsi(value: string): string;
package/dist/theme.js ADDED
@@ -0,0 +1,191 @@
1
+ export const colors = {
2
+ reset: '\x1b[0m',
3
+ bold: '\x1b[1m',
4
+ dim: '\x1b[2m',
5
+ green: '\x1b[38;2;166;227;161m',
6
+ yellow: '\x1b[38;2;249;226;175m',
7
+ red: '\x1b[38;2;243;139;168m',
8
+ blue: '\x1b[38;2;137;180;250m',
9
+ mauve: '\x1b[38;2;203;166;247m',
10
+ teal: '\x1b[38;2;148;226;213m',
11
+ text: '\x1b[38;2;205;214;244m',
12
+ muted: '\x1b[38;2;127;132;156m'
13
+ };
14
+ export function renderBanner(input) {
15
+ const width = 76;
16
+ return [
17
+ `${colors.red}${colors.bold} __ __${colors.reset}`,
18
+ `${colors.red}${colors.bold} _____ / /__ _ __ ___ _ ____ / /_${colors.reset}`,
19
+ `${colors.red}${colors.bold} / ___// //_/| | / // _ \`// __// __/${colors.reset}`,
20
+ `${colors.red}${colors.bold} / / / ,< | |/ // __// / / /_${colors.reset}`,
21
+ `${colors.red}${colors.bold}/_/ /_/|_| |___/ \\___//_/ \\__/${colors.reset}`,
22
+ `${colors.muted} relevant console · local-first security relevance${colors.reset}`,
23
+ `${colors.muted}${'─'.repeat(width)}${colors.reset}`,
24
+ `${colors.muted}workspace ${colors.reset}${colors.text}${input.workspace}${colors.reset}`,
25
+ `${colors.muted}inventory ${colors.reset}${colors.text}${input.inventory ?? 'not set'}${colors.reset}`,
26
+ `${colors.muted}${'─'.repeat(width)}${colors.reset}`,
27
+ `${colors.muted}type ${colors.yellow}help${colors.muted} for commands, ${colors.yellow}exit${colors.muted} to quit${colors.reset}`,
28
+ ''
29
+ ].join('\n');
30
+ }
31
+ export function renderResultCard(result) {
32
+ const badge = verdictBadge(result.verdict);
33
+ const risk = riskBadge(result.risk);
34
+ return [
35
+ `${colors.bold}${colors.text}${result.subject}${colors.reset} ${badge} ${risk}`,
36
+ `${colors.muted}${'─'.repeat(76)}${colors.reset}`,
37
+ wrap(result.summary, 76),
38
+ '',
39
+ `${colors.blue}${colors.bold}Affected${colors.reset}`,
40
+ ...(result.affectedComponents.length > 0
41
+ ? result.affectedComponents.map((component) => ` ${colors.muted}•${colors.reset} ${component}`)
42
+ : [` ${colors.muted}• none${colors.reset}`]),
43
+ '',
44
+ `${colors.blue}${colors.bold}Evidence${colors.reset}`,
45
+ ...result.evidence.map((item) => ` ${colors.muted}•${colors.reset} ${item}`),
46
+ '',
47
+ `${colors.blue}${colors.bold}Actions${colors.reset}`,
48
+ ...result.recommendedActions.map((item) => ` ${colors.muted}•${colors.reset} ${item}`)
49
+ ].join('\n');
50
+ }
51
+ export function renderIocSummary(result) {
52
+ return [
53
+ `${colors.bold}${colors.text}IOC matches${colors.reset} ${riskBadge(result.totalMatches > 0 ? 'high' : 'low')} ${result.totalMatches}`,
54
+ `${colors.muted}${'─'.repeat(76)}${colors.reset}`,
55
+ ...(result.matches.length > 0
56
+ ? result.matches.map((match) => ` ${colors.muted}•${colors.reset} ${colors.yellow}${match.indicator}${colors.reset} ${colors.muted}${match.type}${colors.reset} ${match.file}:${match.line}`)
57
+ : [` ${colors.muted}• no indicators matched${colors.reset}`])
58
+ ].join('\n');
59
+ }
60
+ export function renderStatus(input) {
61
+ return table([
62
+ ['workspace', input.workspace],
63
+ ['inventory', input.inventory ?? 'not set'],
64
+ ['indicators', input.indicators ?? 'not set'],
65
+ ['format', input.format],
66
+ ['last', input.lastResult?.subject ?? 'none']
67
+ ]);
68
+ }
69
+ export function renderHelp() {
70
+ return [
71
+ `${colors.bold}${colors.text}Interactive commands${colors.reset}`,
72
+ `${colors.muted}${'─'.repeat(76)}${colors.reset}`,
73
+ table([
74
+ ['set workspace <path>', 'set repo/environment root'],
75
+ ['set inventory <path>', 'set service exposure inventory'],
76
+ ['set indicators <path>', 'set IOC list'],
77
+ ['set format <text|json|markdown>', 'change output mode'],
78
+ ['set logdir <dir> / set logglob <glob>', 'discover log files for hunts'],
79
+ ['set target <path> / set rule <path>', 'set target/rule for scanner modules'],
80
+ ['use <module>', 'select cve/ioc/exposure/sbom/secrets/cloudtrail/auth/yara/sigma'],
81
+ ['show options/modules/advisories', 'inspect console state'],
82
+ ['run', 'execute selected module'],
83
+ ['back', 'clear selected module'],
84
+ ['cve <CVE-ID>', 'scan using current workspace/inventory'],
85
+ ['scan <CVE-ID>', 'alias for cve'],
86
+ ['ioc <log> [more logs]', 'scan logs using current indicators'],
87
+ ['explain / evidence / actions', 'inspect last CVE result'],
88
+ ['export markdown <file>', 'write last result as Markdown'],
89
+ ['export json <file>', 'write last result as JSON'],
90
+ ['config save | config show', 'persist or inspect defaults'],
91
+ ['profile save/use/list', 'save and restore console profiles'],
92
+ ['workspace add/use/list', 'manage named workspaces'],
93
+ ['sessions / session show <id>', 'revisit previous scan output'],
94
+ ['clear | cls', 'clear the terminal screen'],
95
+ ['!<command>', 'run shell command'],
96
+ ['exit', 'quit']
97
+ ])
98
+ ].join('\n');
99
+ }
100
+ export function renderOptions(input) {
101
+ const rows = [
102
+ ['WORKSPACE', input.workspace, 'repo/environment root'],
103
+ ['FORMAT', input.format, 'output format']
104
+ ];
105
+ if (input.module === 'cve') {
106
+ rows.push(['INVENTORY', input.inventory ?? 'not set', 'service exposure inventory']);
107
+ rows.push(['CVE', input.cve ?? 'not set', 'CVE identifier']);
108
+ }
109
+ else if (input.module === 'ioc') {
110
+ rows.push(['INDICATORS', input.indicators ?? 'not set', 'IOC file']);
111
+ rows.push(['LOGS', input.logs.length > 0 ? input.logs.join(', ') : 'not set', 'log files']);
112
+ }
113
+ else {
114
+ rows.push(['MODULE', 'not set', 'use cve | use ioc']);
115
+ }
116
+ return [
117
+ `${colors.bold}${colors.text}Module options${colors.reset} ${colors.muted}${input.module ? `(${input.module})` : ''}${colors.reset}`,
118
+ `${colors.muted}${'─'.repeat(76)}${colors.reset}`,
119
+ optionTable(rows)
120
+ ].join('\n');
121
+ }
122
+ export function renderSet(key, value) {
123
+ return `${colors.green}✓${colors.reset} ${colors.muted}${key}${colors.reset} = ${colors.text}${value}${colors.reset}`;
124
+ }
125
+ export function renderOk(message) {
126
+ return `${colors.green}✓${colors.reset} ${message}`;
127
+ }
128
+ export function renderError(message) {
129
+ return `${colors.red}error${colors.reset}: ${message}`;
130
+ }
131
+ export function prompt(module) {
132
+ const head = module ? `rel(${module})` : 'rel';
133
+ return `${colors.red}${head}${colors.reset} ${colors.muted}>${colors.reset} `;
134
+ }
135
+ export function stripAnsi(value) {
136
+ return value.replace(/\x1b\[[0-9;]*m/g, '');
137
+ }
138
+ function verdictBadge(verdict) {
139
+ if (verdict === 'relevant')
140
+ return `${colors.red}${colors.bold}RELEVANT${colors.reset}`;
141
+ if (verdict === 'not_relevant')
142
+ return `${colors.green}${colors.bold}NOT RELEVANT${colors.reset}`;
143
+ return `${colors.yellow}${colors.bold}UNKNOWN${colors.reset}`;
144
+ }
145
+ function riskBadge(risk) {
146
+ if (risk === 'critical' || risk === 'high')
147
+ return `${colors.red}${colors.bold}${risk.toUpperCase()}${colors.reset}`;
148
+ if (risk === 'medium')
149
+ return `${colors.yellow}${colors.bold}MEDIUM${colors.reset}`;
150
+ if (risk === 'low')
151
+ return `${colors.green}${colors.bold}LOW${colors.reset}`;
152
+ return `${colors.yellow}${colors.bold}UNKNOWN${colors.reset}`;
153
+ }
154
+ function table(rows) {
155
+ const keyWidth = Math.max(...rows.map(([key]) => key.length));
156
+ return rows
157
+ .map(([key, value]) => ` ${colors.muted}${key.padEnd(keyWidth)}${colors.reset} ${colors.text}${value}${colors.reset}`)
158
+ .join('\n');
159
+ }
160
+ function optionTable(rows) {
161
+ const nameWidth = Math.max('Name'.length, ...rows.map(([name]) => name.length));
162
+ const valueWidth = Math.min(36, Math.max('Current Setting'.length, ...rows.map(([, value]) => stripAnsi(value).length)));
163
+ const header = ` ${colors.muted}${'Name'.padEnd(nameWidth)} ${'Current Setting'.padEnd(valueWidth)} Description${colors.reset}`;
164
+ const divider = ` ${colors.muted}${'-'.repeat(nameWidth)} ${'-'.repeat(valueWidth)} ${'-'.repeat(28)}${colors.reset}`;
165
+ const body = rows.map(([name, value, description]) => ` ${colors.text}${name.padEnd(nameWidth)}${colors.reset} ${colors.yellow}${truncate(value, valueWidth).padEnd(valueWidth)}${colors.reset} ${colors.muted}${description}${colors.reset}`);
166
+ return [header, divider, ...body].join('\n');
167
+ }
168
+ function truncate(value, max) {
169
+ const plain = stripAnsi(value);
170
+ if (plain.length <= max)
171
+ return value;
172
+ return `${plain.slice(0, Math.max(1, max - 1))}…`;
173
+ }
174
+ function wrap(value, width) {
175
+ const words = value.split(/\s+/);
176
+ const lines = [];
177
+ let current = '';
178
+ for (const word of words) {
179
+ if ((current + ' ' + word).trim().length > width) {
180
+ lines.push(current);
181
+ current = word;
182
+ }
183
+ else {
184
+ current = `${current} ${word}`.trim();
185
+ }
186
+ }
187
+ if (current)
188
+ lines.push(current);
189
+ return lines.join('\n');
190
+ }
191
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ export type Verdict = 'relevant' | 'not_relevant' | 'unknown';
2
+ export type Risk = 'critical' | 'high' | 'medium' | 'low' | 'unknown';
3
+ export interface AdvisoryRecord {
4
+ id: string;
5
+ title: string;
6
+ ecosystem: 'npm' | 'pypi';
7
+ packageName: string;
8
+ vulnerableRange: string;
9
+ fixedVersion?: string;
10
+ vulnerableSymbols: string[];
11
+ summary: string;
12
+ recommendedActions: string[];
13
+ }
14
+ export interface ServiceInventory {
15
+ name: string;
16
+ path: string;
17
+ exposure: 'internet' | 'partner' | 'internal' | 'unknown';
18
+ ingress?: string[];
19
+ }
20
+ export interface Inventory {
21
+ services: ServiceInventory[];
22
+ }
23
+ export interface DependencyFinding {
24
+ service: ServiceInventory;
25
+ packageName: string;
26
+ version: string;
27
+ manifestPath: string;
28
+ }
29
+ export interface RelevanceResult {
30
+ subject: string;
31
+ verdict: Verdict;
32
+ risk: Risk;
33
+ summary: string;
34
+ affectedComponents: string[];
35
+ evidence: string[];
36
+ recommendedActions: string[];
37
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export declare const VERSION = "0.1.0";
@@ -0,0 +1,2 @@
1
+ export const VERSION = '0.1.0';
2
+ //# sourceMappingURL=version-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-info.js","sourceRoot":"","sources":["../src/version-info.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { AdvisoryRecord } from './types.js';
2
+ type Ecosystem = AdvisoryRecord['ecosystem'];
3
+ export declare function satisfiesVulnerableRange(version: string, range: string, ecosystem?: Ecosystem): boolean;
4
+ export {};
@@ -0,0 +1,74 @@
1
+ import semver from 'semver';
2
+ export function satisfiesVulnerableRange(version, range, ecosystem = 'npm') {
3
+ if (ecosystem === 'pypi')
4
+ return satisfiesPypiRange(version, range);
5
+ return semver.satisfies(version, range, { includePrerelease: true, loose: true });
6
+ }
7
+ function satisfiesPypiRange(version, range) {
8
+ const parsed = parsePypiVersion(version);
9
+ if (!parsed)
10
+ return false;
11
+ return range
12
+ .split(',')
13
+ .map((item) => item.trim())
14
+ .filter(Boolean)
15
+ .every((specifier) => satisfiesPypiSpecifier(parsed, specifier));
16
+ }
17
+ function satisfiesPypiSpecifier(version, specifier) {
18
+ const match = specifier.match(/^(<=|>=|==|!=|<|>)\s*([A-Za-z0-9._!*+-]+)$/);
19
+ if (!match)
20
+ return false;
21
+ const operator = match[1] ?? '';
22
+ const target = parsePypiVersion(match[2] ?? '');
23
+ if (!target)
24
+ return false;
25
+ const comparison = comparePypiVersions(version, target);
26
+ if (operator === '<')
27
+ return comparison < 0;
28
+ if (operator === '<=')
29
+ return comparison <= 0;
30
+ if (operator === '>')
31
+ return comparison > 0;
32
+ if (operator === '>=')
33
+ return comparison >= 0;
34
+ if (operator === '==')
35
+ return comparison === 0;
36
+ if (operator === '!=')
37
+ return comparison !== 0;
38
+ return false;
39
+ }
40
+ function parsePypiVersion(value) {
41
+ const normalized = value.trim().toLowerCase().replace(/_/g, '.').replace(/-/g, '.');
42
+ const match = normalized.match(/^v?(\d+(?:\.\d+)*)(?:(a|b|rc|post|dev)\.?(\d+)?)?$/);
43
+ if (!match)
44
+ return undefined;
45
+ const release = (match[1] ?? '').split('.').map((part) => Number.parseInt(part, 10));
46
+ const phase = pypiPhase(match[2]);
47
+ const phaseNumber = match[3] ? Number.parseInt(match[3], 10) : 0;
48
+ return { release, phase, phaseNumber };
49
+ }
50
+ function pypiPhase(value) {
51
+ if (value === 'dev')
52
+ return -4;
53
+ if (value === 'a')
54
+ return -3;
55
+ if (value === 'b')
56
+ return -2;
57
+ if (value === 'rc')
58
+ return -1;
59
+ if (value === 'post')
60
+ return 1;
61
+ return 0;
62
+ }
63
+ function comparePypiVersions(a, b) {
64
+ const releaseLength = Math.max(a.release.length, b.release.length);
65
+ for (let i = 0; i < releaseLength; i++) {
66
+ const diff = (a.release[i] ?? 0) - (b.release[i] ?? 0);
67
+ if (diff !== 0)
68
+ return diff;
69
+ }
70
+ if (a.phase !== b.phase)
71
+ return a.phase - b.phase;
72
+ return a.phaseNumber - b.phaseNumber;
73
+ }
74
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ # Release Process
2
+
3
+ `relsec` uses semantic versioning. The CLI binary is exposed as both `relevant` and `relsec`.
4
+
5
+ ## Versioning
6
+
7
+ - Patch: bug fixes, detector tuning, documentation, non-breaking CLI improvements.
8
+ - Minor: new commands, new modules, new supported input formats, additive output fields.
9
+ - Major: breaking command syntax, removed fields, changed default output formats, incompatible config migrations.
10
+
11
+ The package version in `package.json` must match `src/version-info.ts`.
12
+
13
+ ## Pre-Release Checklist
14
+
15
+ Run:
16
+
17
+ ```bash
18
+ npm run release:check
19
+ npm run pack:dry-run
20
+ ```
21
+
22
+ Verify:
23
+
24
+ - `npm test` passes.
25
+ - `npm run typecheck` passes.
26
+ - `npm run build` passes.
27
+ - `npm pack --dry-run` includes only expected files.
28
+ - `node dist/cli.js --version` prints the intended version.
29
+ - `node dist/cli.js help` renders usable help.
30
+ - `SECURITY.md` and `README.md` accurately describe current limitations.
31
+
32
+ ## npm Publishing
33
+
34
+ Publishing is intentionally not automated yet. When ready:
35
+
36
+ ```bash
37
+ npm login
38
+ npm publish --access public
39
+ ```
40
+
41
+ Use provenance and signed release artifacts once the project is moved into a public repository with CI release automation.
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "relsec",
3
+ "version": "0.1.0",
4
+ "description": "Local-first security relevance CLI for CVEs, advisories, IOCs, repos, and enterprise evidence.",
5
+ "license": "MIT",
6
+ "author": "MistanKh",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/MistanKh/relsec.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/MistanKh/relsec/issues"
13
+ },
14
+ "homepage": "https://github.com/MistanKh/relsec#readme",
15
+ "type": "module",
16
+ "bin": {
17
+ "relevant": "dist/cli.js",
18
+ "relsec": "dist/cli.js"
19
+ },
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/cli.d.ts",
23
+ "import": "./dist/cli.js"
24
+ }
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "README.md",
29
+ "SECURITY.md",
30
+ "LICENSE",
31
+ "docs"
32
+ ],
33
+ "scripts": {
34
+ "test": "vitest run",
35
+ "typecheck": "tsc -p tsconfig.json --noEmit",
36
+ "build": "tsc -p tsconfig.build.json",
37
+ "dev": "tsx src/cli.ts",
38
+ "release:check": "npm run typecheck && npm test && npm run build",
39
+ "pack:dry-run": "npm pack --dry-run",
40
+ "prepack": "npm run release:check"
41
+ },
42
+ "keywords": [
43
+ "security",
44
+ "cve",
45
+ "ioc",
46
+ "sbom",
47
+ "soc",
48
+ "appsec",
49
+ "cli"
50
+ ],
51
+ "engines": {
52
+ "node": ">=20"
53
+ },
54
+ "devDependencies": {
55
+ "@types/node": "^22.15.29",
56
+ "@types/semver": "^7.7.1",
57
+ "tsx": "^4.19.4",
58
+ "typescript": "^5.8.3",
59
+ "vitest": "^3.2.4"
60
+ },
61
+ "dependencies": {
62
+ "semver": "^7.8.1"
63
+ }
64
+ }