@quantakrypto/core 0.5.0 → 0.7.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 (51) hide show
  1. package/dist/crypto-agility.d.ts +158 -0
  2. package/dist/crypto-agility.d.ts.map +1 -0
  3. package/dist/crypto-agility.js +285 -0
  4. package/dist/crypto-agility.js.map +1 -0
  5. package/dist/dependencies.d.ts.map +1 -1
  6. package/dist/dependencies.js +180 -18
  7. package/dist/dependencies.js.map +1 -1
  8. package/dist/detectors/source.d.ts.map +1 -1
  9. package/dist/detectors/source.js +52 -0
  10. package/dist/detectors/source.js.map +1 -1
  11. package/dist/hndl.d.ts +241 -0
  12. package/dist/hndl.d.ts.map +1 -0
  13. package/dist/hndl.js +752 -0
  14. package/dist/hndl.js.map +1 -0
  15. package/dist/index.d.ts +6 -0
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +6 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/mandates.d.ts +138 -0
  20. package/dist/mandates.d.ts.map +1 -0
  21. package/dist/mandates.js +228 -0
  22. package/dist/mandates.js.map +1 -0
  23. package/dist/parallel.d.ts.map +1 -1
  24. package/dist/parallel.js +22 -23
  25. package/dist/parallel.js.map +1 -1
  26. package/dist/report.d.ts +8 -0
  27. package/dist/report.d.ts.map +1 -1
  28. package/dist/report.js +75 -19
  29. package/dist/report.js.map +1 -1
  30. package/dist/types.d.ts +1 -1
  31. package/dist/types.d.ts.map +1 -1
  32. package/dist/types.js.map +1 -1
  33. package/dist/version.d.ts +1 -1
  34. package/dist/version.js +1 -1
  35. package/dist/version.js.map +1 -1
  36. package/dist/walk.d.ts +31 -1
  37. package/dist/walk.d.ts.map +1 -1
  38. package/dist/walk.js +30 -9
  39. package/dist/walk.js.map +1 -1
  40. package/package.json +1 -1
  41. package/src/crypto-agility.ts +407 -0
  42. package/src/dependencies.ts +182 -16
  43. package/src/detectors/source.ts +62 -0
  44. package/src/hndl.ts +1012 -0
  45. package/src/index.ts +71 -0
  46. package/src/mandates.ts +365 -0
  47. package/src/parallel.ts +21 -20
  48. package/src/report.ts +84 -19
  49. package/src/types.ts +9 -1
  50. package/src/version.ts +1 -1
  51. package/src/walk.ts +47 -10
package/src/version.ts CHANGED
@@ -3,4 +3,4 @@
3
3
  * the scan orchestrator can import it without creating a cycle through index.ts.
4
4
  * Keep in sync with packages/core/package.json.
5
5
  */
6
- export const VERSION = "0.5.0";
6
+ export const VERSION = "0.7.0";
package/src/walk.ts CHANGED
@@ -291,12 +291,34 @@ export function looksMinified(content: string): boolean {
291
291
  return avgLine > 1_000;
292
292
  }
293
293
 
294
+ /** A scannable file plus the byte size the walker already stat'd for it. */
295
+ export interface WalkedFile {
296
+ /** Relative POSIX path from the walk root. */
297
+ rel: string;
298
+ /** File size in bytes (from the walker's own stat; never re-stat downstream). */
299
+ size: number;
300
+ }
301
+
294
302
  /**
295
303
  * Recursively yield scannable file paths (relative to `root`, POSIX) under a
296
304
  * directory. If `root` points at a single file, yields just that file's
297
- * basename (subject to the size / binary filters).
305
+ * basename (subject to the size / binary filters). Thin wrapper over
306
+ * {@link walkFilesSized} that drops the size (the historical string-yielding API).
298
307
  */
299
308
  export async function* walkFiles(root: string, options: WalkOptions = {}): AsyncGenerator<string> {
309
+ for await (const f of walkFilesSized(root, options)) yield f.rel;
310
+ }
311
+
312
+ /**
313
+ * Like {@link walkFiles} but yields each file WITH the byte size the walker
314
+ * already obtained while applying the size limit. Callers that need sizes (the
315
+ * parallel scanner's byte-balanced chunking) consume this directly so they do
316
+ * not stat every file a second time (P2 double-stat elimination).
317
+ */
318
+ export async function* walkFilesSized(
319
+ root: string,
320
+ options: WalkOptions = {},
321
+ ): AsyncGenerator<WalkedFile> {
300
322
  const include = options.include ?? [];
301
323
  const exclude = options.exclude ?? [];
302
324
  const maxFileSize = options.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
@@ -312,7 +334,7 @@ export async function* walkFiles(root: string, options: WalkOptions = {}): Async
312
334
  isIncluded(name, include) &&
313
335
  passesSizeLimit(name, rootStat.size, maxFileSize)
314
336
  ) {
315
- yield name;
337
+ yield { rel: name, size: rootStat.size };
316
338
  }
317
339
  return;
318
340
  }
@@ -327,20 +349,33 @@ interface WalkContext {
327
349
  ignores: readonly string[];
328
350
  }
329
351
 
352
+ /**
353
+ * Manifests bypass the normal file-size cap (they carry the whole dependency
354
+ * tree and must not be dropped), but still get a generous hard ceiling so a
355
+ * pathological or hostile lockfile can't be read unbounded and OOM the scan.
356
+ * 16 MiB comfortably covers real monorepo lockfiles (npm's own is well under 5).
357
+ */
358
+ export const MANIFEST_MAX_BYTES = 16 * 1024 * 1024;
359
+
330
360
  /**
331
361
  * True if a file passes the size limit. Dependency manifests (package.json /
332
- * package-lock.json) are exempt from the cap so large lockfiles still get
333
- * scanned for vulnerable dependencies instead of being silently dropped.
362
+ * package-lock.json / yarn.lock / …) get the larger {@link MANIFEST_MAX_BYTES}
363
+ * ceiling instead of the ordinary cap, so large lockfiles still get scanned for
364
+ * vulnerable dependencies without letting an enormous one exhaust memory.
365
+ * Exported for unit testing.
334
366
  */
335
- function passesSizeLimit(rel: string, size: number, maxFileSize: number): boolean {
336
- // Dependency manifests are always read (they can exceed the size cap but carry
337
- // the whole dependency tree). Uses the single {@link isManifestFile} definition.
338
- if (isManifestFile(rel)) return true;
367
+ export function passesSizeLimit(rel: string, size: number, maxFileSize: number): boolean {
368
+ // Uses the single {@link isManifestFile} definition.
369
+ if (isManifestFile(rel)) return size <= MANIFEST_MAX_BYTES;
339
370
  return size <= maxFileSize;
340
371
  }
341
372
 
342
373
  /** Internal recursive directory walker. `relDir` is POSIX-relative to the root. */
343
- async function* walkDir(absDir: string, relDir: string, ctx: WalkContext): AsyncGenerator<string> {
374
+ async function* walkDir(
375
+ absDir: string,
376
+ relDir: string,
377
+ ctx: WalkContext,
378
+ ): AsyncGenerator<WalkedFile> {
344
379
  let entries: Dirent[];
345
380
  try {
346
381
  entries = await readdir(absDir, { withFileTypes: true });
@@ -377,13 +412,15 @@ async function* walkDir(absDir: string, relDir: string, ctx: WalkContext): Async
377
412
  if (!manifest && isBinaryPath(rel)) continue;
378
413
  if (!manifest && isGeneratedPath(rel)) continue;
379
414
 
415
+ let size: number;
380
416
  try {
381
417
  const s = await stat(abs);
382
418
  if (!passesSizeLimit(rel, s.size, ctx.maxFileSize)) continue;
419
+ size = s.size;
383
420
  } catch {
384
421
  continue;
385
422
  }
386
423
 
387
- yield rel;
424
+ yield { rel, size };
388
425
  }
389
426
  }