cryptoserve 0.1.2 → 0.1.3

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.
@@ -487,7 +487,15 @@ function calculateQuantumScore(libraries, classifications) {
487
487
 
488
488
  if (total === 0) return 100.0;
489
489
 
490
- let score = (safe / total) * 100;
490
+ // Two scoring approaches:
491
+ // - Ratio: safe / total (good for large samples)
492
+ // - Penalty: 100 - 30 per vulnerable (good for small samples)
493
+ // Small samples (≤3 algorithms) produce extreme ratios (1/1 = 0% or 100%),
494
+ // so use whichever approach gives the more representative score.
495
+ const ratioScore = (safe / total) * 100;
496
+ const penaltyScore = Math.max(0, 100 - vulnerable * 30);
497
+ let score = total <= 3 ? Math.max(ratioScore, penaltyScore) : ratioScore;
498
+
491
499
  if (classifications.some(c => c.category === 'pqc')) {
492
500
  score = Math.min(100, score + 20);
493
501
  }
package/lib/scanner.mjs CHANGED
@@ -179,9 +179,26 @@ export function scanProject(projectDir) {
179
179
  filesScanned: 0,
180
180
  };
181
181
 
182
- // 1. Scan package.json for crypto dependencies
183
- const pkgPath = join(projectDir, 'package.json');
184
- if (existsSync(pkgPath)) {
182
+ // 1. Scan package.json for crypto dependencies (root + monorepo workspaces)
183
+ const pkgPaths = [join(projectDir, 'package.json')];
184
+ // Check common monorepo locations for nested package.json files
185
+ const monorepoGlobs = ['apps', 'packages', 'libs', 'modules', 'services'];
186
+ for (const sub of monorepoGlobs) {
187
+ const subDir = join(projectDir, sub);
188
+ try {
189
+ const entries = readdirSync(subDir, { withFileTypes: true });
190
+ for (const entry of entries) {
191
+ if (entry.isDirectory()) {
192
+ const nested = join(subDir, entry.name, 'package.json');
193
+ if (existsSync(nested)) pkgPaths.push(nested);
194
+ }
195
+ }
196
+ } catch { /* dir doesn't exist */ }
197
+ }
198
+
199
+ const seenPkgs = new Set();
200
+ for (const pkgPath of pkgPaths) {
201
+ if (!existsSync(pkgPath)) continue;
185
202
  try {
186
203
  const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
187
204
  const allDeps = {
@@ -190,7 +207,8 @@ export function scanProject(projectDir) {
190
207
  };
191
208
 
192
209
  for (const [name, version] of Object.entries(allDeps)) {
193
- if (name in CRYPTO_PACKAGES) {
210
+ if (name in CRYPTO_PACKAGES && !seenPkgs.has(name)) {
211
+ seenPkgs.add(name);
194
212
  const info = CRYPTO_PACKAGES[name];
195
213
  results.libraries.push({
196
214
  name,
@@ -198,7 +216,7 @@ export function scanProject(projectDir) {
198
216
  algorithms: info.algorithms,
199
217
  quantumRisk: info.quantumRisk,
200
218
  category: info.category,
201
- source: 'package.json',
219
+ source: pkgPath.replace(projectDir + '/', ''),
202
220
  });
203
221
  }
204
222
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cryptoserve",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "CryptoServe CLI - Cryptographic scanning, PQC analysis, encryption, and local key management",
5
5
  "type": "module",
6
6
  "bin": {