@quantakrypto/core 0.5.0 → 0.6.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/crypto-agility.d.ts +158 -0
- package/dist/crypto-agility.d.ts.map +1 -0
- package/dist/crypto-agility.js +285 -0
- package/dist/crypto-agility.js.map +1 -0
- package/dist/dependencies.d.ts.map +1 -1
- package/dist/dependencies.js +180 -18
- package/dist/dependencies.js.map +1 -1
- package/dist/detectors/source.d.ts.map +1 -1
- package/dist/detectors/source.js +52 -0
- package/dist/detectors/source.js.map +1 -1
- package/dist/hndl.d.ts +241 -0
- package/dist/hndl.d.ts.map +1 -0
- package/dist/hndl.js +752 -0
- package/dist/hndl.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/parallel.d.ts.map +1 -1
- package/dist/parallel.js +22 -23
- package/dist/parallel.js.map +1 -1
- package/dist/report.d.ts +8 -0
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +75 -19
- package/dist/report.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/walk.d.ts +31 -1
- package/dist/walk.d.ts.map +1 -1
- package/dist/walk.js +30 -9
- package/dist/walk.js.map +1 -1
- package/package.json +1 -1
- package/src/crypto-agility.ts +407 -0
- package/src/dependencies.ts +182 -16
- package/src/detectors/source.ts +62 -0
- package/src/hndl.ts +1012 -0
- package/src/index.ts +52 -0
- package/src/parallel.ts +21 -20
- package/src/report.ts +84 -19
- package/src/types.ts +9 -1
- package/src/version.ts +1 -1
- package/src/walk.ts +47 -10
package/dist/hndl.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hndl.js","sourceRoot":"","sources":["../src/hndl.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * HNDL (\"harvest now, decrypt later\") data-risk quantifier - roadmap initiative 2.\n *\n * A crypto finding on its own answers \"what is broken\"; it does not answer \"how\n * much does it matter\". This module joins the crypto finding to the DATA it\n * protects and makes Mosca's inequality concrete, so a migration backlog can be\n * ranked by real exposure instead of by finding counts.\n *\n * Exposure per finding = crypto-vulnerability (V) x data-sensitivity (S) x\n * Mosca-factor (M), each normalised to 0..1, reported as an integer 0..100:\n *\n * - V: how breakable + how confidently detected the crypto is, discounted hard\n * when the finding is not HNDL-exposed (a signature cannot be broken\n * retroactively to reveal harvested ciphertext).\n * - S: the declared sensitivity class of the data the finding sits next to.\n * - M: the fraction of the data's protection horizon (retention / secrecy\n * lifetime + migration time) that extends BEYOND the quantum-threat\n * horizon. Mosca: concern exists when X + Y > Z.\n *\n * The data map is a declared `hndl.yml` (assets, classification, retention +\n * secrecy lifetime, path/scope bindings). Parsing is hand-rolled and\n * zero-dependency, consistent with the rest of core (ADR-0001): no YAML library\n * is pulled in. The full model is documented in docs/HNDL.md so the score is\n * contestable rather than magic.\n */\nimport { readFile } from \"node:fs/promises\";\nimport * as path from \"node:path\";\n\nimport type { Confidence, Finding, Severity } from \"./types.js\";\nimport { fingerprintFinding } from \"./baseline.js\";\nimport { defaultRegistry, detectorScope } from \"./registry.js\";\n\n/* -------------------------------------------------------------------------- */\n/* Model constants (exported so the score is contestable, not magic) */\n/* -------------------------------------------------------------------------- */\n\n/** Version of the exposure model. Bump on any weight / formula change. */\nexport const HNDL_MODEL_VERSION = \"1\" as const;\n\n/** Canonical `hndl.yml` file name discovered at a scan root. */\nexport const HNDL_FILENAME = \"hndl.yml\";\n\n/** Data sensitivity classes, least → most sensitive. Vocabulary aligned with the\n * readiness DPE (data-protection) practice. */\nexport type DataClassification = \"public\" | \"internal\" | \"confidential\" | \"regulated\";\n\nconst CLASSIFICATIONS: readonly DataClassification[] = [\n \"public\",\n \"internal\",\n \"confidential\",\n \"regulated\",\n];\n\n/**\n * Logical scope a finding belongs to, used for optional scope-bound assets. The\n * two detector scopes (\"source\" / \"config\") plus \"dependency\" (manifest\n * findings, which are not produced by a Detector).\n */\nexport type HndlScope = \"source\" | \"config\" | \"dependency\";\n\nconst HNDL_SCOPES: readonly HndlScope[] = [\"source\", \"config\", \"dependency\"];\n\n/** Crypto-vulnerability weight (V) contributed by a finding's severity. */\nexport const SEVERITY_VULNERABILITY: Record<Severity, number> = {\n critical: 1.0,\n high: 0.8,\n medium: 0.5,\n low: 0.25,\n info: 0.1,\n};\n\n/** Crypto-vulnerability weight (V) scaled by detector confidence. */\nexport const CONFIDENCE_WEIGHT: Record<Confidence, number> = {\n high: 1.0,\n medium: 0.85,\n low: 0.6,\n};\n\n/** Data-sensitivity weight (S) per classification. */\nexport const CLASSIFICATION_SENSITIVITY: Record<DataClassification, number> = {\n public: 0.1,\n internal: 0.4,\n confidential: 0.7,\n regulated: 1.0,\n};\n\n/**\n * Discount applied to V when a finding is NOT harvest-now-decrypt-later exposed\n * (e.g. a pure signature). A forged signature is a future-integrity problem, not\n * a retroactive-confidentiality one, so it barely moves the HNDL needle.\n */\nexport const NON_HNDL_DISCOUNT = 0.15;\n\n/**\n * Default years until a cryptographically-relevant quantum computer is assumed\n * to exist (Z in Mosca's inequality). 15 years is a defensible mid-point of the\n * commonly-cited Mosca / NIST window; override per-org in `hndl.yml`.\n */\nexport const DEFAULT_QUANTUM_THREAT_YEARS = 15;\n\n/**\n * Default years to complete the org's PQC migration (Y in Mosca's inequality).\n * Override per-org in `hndl.yml`.\n */\nexport const DEFAULT_MIGRATION_HORIZON_YEARS = 5;\n\n/** Classification assumed for findings that bind to no declared asset. */\nexport const DEFAULT_UNBOUND_CLASSIFICATION: DataClassification = \"internal\";\n\n/* -------------------------------------------------------------------------- */\n/* Declared data map (hndl.yml) */\n/* -------------------------------------------------------------------------- */\n\n/** A single declared data asset from `hndl.yml`. */\nexport interface HndlDataAsset {\n /** Stable id (referenced by finding exposures + the website's `data_asset.key`). */\n key: string;\n /** Human name. */\n name: string;\n classification: DataClassification;\n /** How long the data is retained, in years. */\n retentionYears: number;\n /** How long the data must remain confidential once captured, in years. */\n secrecyLifetimeYears: number;\n /** Path globs (POSIX, relative to scan root) whose findings bind to this asset. */\n paths: string[];\n /** Optional detector-scope filter: only findings of these scopes bind here. */\n scopes?: HndlScope[];\n}\n\n/** The Mosca horizons that gate the exposure model. */\nexport interface HndlHorizon {\n /** Z: years until a cryptographically-relevant quantum computer is assumed. */\n quantumThreatYears: number;\n /** Y: years to complete the org's PQC migration. */\n migrationHorizonYears: number;\n}\n\n/** Defaults applied to findings that bind to no declared asset. */\nexport interface HndlDefaults {\n classification: DataClassification;\n}\n\n/** A fully-parsed, validated `hndl.yml`. */\nexport interface HndlMap {\n version: number;\n horizon: HndlHorizon;\n defaults: HndlDefaults;\n assets: HndlDataAsset[];\n}\n\n/** Thrown when `hndl.yml` is malformed (structure or a bad known value). */\nexport class HndlError extends Error {\n override readonly name = \"HndlError\";\n /** The `hndl.yml` path the error relates to, when known. */\n readonly path: string | undefined;\n constructor(message: string, hndlPath?: string) {\n super(message);\n this.path = hndlPath;\n }\n}\n\n/* -------------------------------------------------------------------------- */\n/* Exposure results */\n/* -------------------------------------------------------------------------- */\n\n/** Full, auditable breakdown of one finding's exposure score. */\nexport interface ExposureRationale {\n /** V - crypto-vulnerability factor (0..1). */\n vulnerability: number;\n /** S - data-sensitivity factor (0..1). */\n sensitivity: number;\n /** M - Mosca factor (0..1): fraction of the protection horizon past the threat. */\n mosca: number;\n classification: DataClassification;\n retentionYears: number;\n secrecyLifetimeYears: number;\n /** X = max(retention, secrecy lifetime): the data's protection requirement. */\n secrecyHorizonYears: number;\n /** Z - quantum-threat horizon (years). */\n quantumThreatYears: number;\n /** Y - migration horizon (years). */\n migrationHorizonYears: number;\n /** (X + Y) - Z; positive means Mosca's inequality is breached. */\n moscaMarginYears: number;\n /** True when (X + Y) > Z (data captured today is exposed while still secret). */\n moscaBreach: boolean;\n /** Whether the finding is HNDL-exposed (drives {@link NON_HNDL_DISCOUNT}). */\n hndl: boolean;\n severity: Severity;\n confidence: Confidence;\n scope: HndlScope;\n /** True when the finding matched a declared asset (false = defaults applied). */\n bound: boolean;\n}\n\n/** A finding's computed exposure, keyed by fingerprint for website ingest. */\nexport interface FindingExposure {\n /** Finding identity: `finding.fingerprint` when present, else the canonical\n * `fingerprintFinding()` hash. This is the join key the website stores. */\n fingerprint: string;\n ruleId: string;\n file: string;\n /** The bound data asset's stable key, or null when unbound. */\n dataAsset: string | null;\n /** 0..100 exposure score. */\n exposureScore: number;\n rationale: ExposureRationale;\n}\n\n/** Per-asset rollup for the repo summary. */\nexport interface AssetExposure {\n key: string;\n name: string;\n classification: DataClassification;\n retentionYears: number;\n secrecyLifetimeYears: number;\n /** Number of findings bound to this asset. */\n findings: number;\n /** Highest exposure among this asset's findings. */\n maxExposure: number;\n /** True when the data's secrecy horizon outlives the quantum threat (X > Z). */\n outlivesThreat: boolean;\n}\n\n/** Repo-level HNDL summary. */\nexport interface HndlSummary {\n findingsScored: number;\n assetsDeclared: number;\n /** Declared assets that bound at least one finding. */\n assetsWithFindings: number;\n /** Declared assets whose secrecy horizon outlives the quantum threat (X > Z). */\n assetsOutlivingHorizon: number;\n /** Findings whose Mosca inequality is breached ((X + Y) > Z). */\n moscaBreaches: number;\n maxExposure: number;\n /** Rounded mean exposure across scored findings. */\n meanExposure: number;\n /** The worst findings, most-exposed first (capped). */\n topExposures: FindingExposure[];\n}\n\n/** The complete HNDL analysis of a scan. */\nexport interface HndlReport {\n modelVersion: string;\n horizon: HndlHorizon;\n /** Per-finding exposures, in input order. */\n exposures: FindingExposure[];\n /** Fingerprint → exposure, for reporters to annotate each finding. */\n byFingerprint: Map<string, FindingExposure>;\n /** Per-asset rollups. */\n assets: AssetExposure[];\n summary: HndlSummary;\n}\n\n/** How many findings the summary's `topExposures` lists. */\nconst TOP_EXPOSURES = 5;\n\n/* -------------------------------------------------------------------------- */\n/* Fingerprint + scope resolution */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Identity key for a finding's exposure. Prefers a `finding.fingerprint` field\n * when a build supplies one (another workstream is adding it to core's Finding\n * type + reporters); falls back to the canonical `fingerprintFinding()` hash\n * (`sha256(ruleId|file|normalizedSnippet)`) otherwise. INTEGRATION POINT: once\n * `Finding.fingerprint` lands, this transparently switches to it - no caller\n * change needed.\n */\nexport function findingFingerprint(f: Finding): string {\n const declared = (f as { fingerprint?: unknown }).fingerprint;\n if (typeof declared === \"string\" && declared.length > 0) return declared;\n return fingerprintFinding(f);\n}\n\n/** ruleId → detector scope, built once from the default registry. */\nlet scopeIndex: Map<string, HndlScope> | undefined;\n\nfunction ruleScopeIndex(): Map<string, HndlScope> {\n if (scopeIndex) return scopeIndex;\n const index = new Map<string, HndlScope>();\n for (const det of defaultRegistry.all()) {\n const scope = detectorScope(det) as HndlScope;\n for (const rule of det.rules ?? []) index.set(rule.id, scope);\n }\n scopeIndex = index;\n return index;\n}\n\n/**\n * The scope a finding belongs to. Dependency findings (from the manifest\n * scanner, category \"dependency\") are \"dependency\"; everything else is looked up\n * by ruleId in the detector registry, defaulting to \"source\".\n */\nexport function findingScope(f: Finding): HndlScope {\n if (f.category === \"dependency\") return \"dependency\";\n return ruleScopeIndex().get(f.ruleId) ?? \"source\";\n}\n\n/* -------------------------------------------------------------------------- */\n/* Glob matching (hand-rolled, zero-dependency) */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Match a POSIX path against a glob supporting `**` (any path segments incl.\n * `/`), `*` (any run of non-`/` chars), and `?` (a single non-`/` char). A\n * trailing `/**` also matches the directory itself. Everything else is literal.\n */\nexport function globMatch(glob: string, filePath: string): boolean {\n return globToRegExp(glob).test(filePath);\n}\n\nconst globCache = new Map<string, RegExp>();\n\nfunction globToRegExp(glob: string): RegExp {\n const cached = globCache.get(glob);\n if (cached) return cached;\n let re = \"^\";\n for (let i = 0; i < glob.length; i++) {\n const ch = glob[i] as string;\n if (ch === \"*\") {\n if (glob[i + 1] === \"*\") {\n // `**` - any number of characters including path separators. Consume a\n // following `/` so `a/**/b` matches `a/b` (zero segments) too.\n i++;\n if (glob[i + 1] === \"/\") i++;\n re += \".*\";\n } else {\n re += \"[^/]*\";\n }\n } else if (ch === \"?\") {\n re += \"[^/]\";\n } else if (\"\\\\^$.|+()[]{}\".includes(ch)) {\n re += `\\\\${ch}`;\n } else {\n re += ch;\n }\n }\n re += \"$\";\n const compiled = new RegExp(re);\n globCache.set(glob, compiled);\n return compiled;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Exposure math */\n/* -------------------------------------------------------------------------- */\n\nfunction clamp01(x: number): number {\n return x < 0 ? 0 : x > 1 ? 1 : x;\n}\n\n/** V - crypto-vulnerability factor for a finding (0..1). */\nexport function vulnerabilityFactor(f: Finding): number {\n const base = SEVERITY_VULNERABILITY[f.severity] * CONFIDENCE_WEIGHT[f.confidence];\n return clamp01(base * (f.hndl ? 1 : NON_HNDL_DISCOUNT));\n}\n\n/**\n * M - the Mosca factor (0..1). `X` is the data's protection horizon\n * (max of retention + secrecy lifetime), `Y` the migration horizon, `Z` the\n * quantum-threat horizon. M is the fraction of `X + Y` that falls after `Z`:\n * 0 when the threat is beyond the whole horizon, 1 when the threat is already\n * here. Mosca's inequality (X + Y > Z) is exactly `M > 0`.\n */\nexport function moscaFactor(secrecyHorizonYears: number, horizon: HndlHorizon): number {\n const span = secrecyHorizonYears + horizon.migrationHorizonYears;\n if (span <= 0) return 0;\n const margin = span - horizon.quantumThreatYears;\n return clamp01(margin / span);\n}\n\ninterface ScoreInput {\n vulnerability: number;\n classification: DataClassification;\n retentionYears: number;\n secrecyLifetimeYears: number;\n bound: boolean;\n}\n\nfunction scoreFinding(f: Finding, input: ScoreInput, horizon: HndlHorizon): FindingExposure {\n const sensitivity = CLASSIFICATION_SENSITIVITY[input.classification];\n const secrecyHorizonYears = Math.max(input.retentionYears, input.secrecyLifetimeYears);\n const mosca = moscaFactor(secrecyHorizonYears, horizon);\n const exposureScore = Math.round(100 * clamp01(input.vulnerability * sensitivity * mosca));\n const moscaMarginYears =\n secrecyHorizonYears + horizon.migrationHorizonYears - horizon.quantumThreatYears;\n const rationale: ExposureRationale = {\n vulnerability: round3(input.vulnerability),\n sensitivity: round3(sensitivity),\n mosca: round3(mosca),\n classification: input.classification,\n retentionYears: input.retentionYears,\n secrecyLifetimeYears: input.secrecyLifetimeYears,\n secrecyHorizonYears,\n quantumThreatYears: horizon.quantumThreatYears,\n migrationHorizonYears: horizon.migrationHorizonYears,\n moscaMarginYears,\n moscaBreach: moscaMarginYears > 0,\n hndl: f.hndl,\n severity: f.severity,\n confidence: f.confidence,\n scope: findingScope(f),\n bound: input.bound,\n };\n return {\n fingerprint: findingFingerprint(f),\n ruleId: f.ruleId,\n file: f.location.file,\n dataAsset: null,\n exposureScore,\n rationale,\n };\n}\n\nfunction round3(x: number): number {\n return Math.round(x * 1000) / 1000;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Binding + top-level compute */\n/* -------------------------------------------------------------------------- */\n\n/** Assets whose path globs + optional scope filter match a finding. */\nfunction matchingAssets(f: Finding, map: HndlMap, scope: HndlScope): HndlDataAsset[] {\n const out: HndlDataAsset[] = [];\n for (const asset of map.assets) {\n if (asset.scopes && !asset.scopes.includes(scope)) continue;\n if (asset.paths.some((g) => globMatch(g, f.location.file))) out.push(asset);\n }\n return out;\n}\n\n/**\n * Compute HNDL exposure for a set of findings against a declared data map.\n *\n * A finding binds to every declared asset whose path glob (and optional scope\n * filter) matches its file; when several match, the WORST-CASE (highest)\n * exposure is chosen and its asset recorded, since risk ranking should not be\n * diluted by an incidental low-sensitivity overlap. A finding that binds to no\n * asset is still scored, using the map's `defaults.classification` and the\n * global horizons, and flagged `bound: false` so it is visibly a fallback. Its\n * secrecy lifetime is assumed to be the quantum-threat horizon Z (the\n * minimum-concern horizon; see {@link scoreFinding} call below and docs/HNDL.md\n * §4), so the fallback classification produces a real, rankable exposure rather\n * than a dead 0.\n *\n * Purely additive: it never mutates findings and never affects a scan's exit\n * code.\n */\nexport function computeHndl(findings: readonly Finding[], map: HndlMap): HndlReport {\n const exposures: FindingExposure[] = [];\n const byFingerprint = new Map<string, FindingExposure>();\n const assetFindings = new Map<string, number>();\n const assetMax = new Map<string, number>();\n\n for (const f of findings) {\n const vulnerability = vulnerabilityFactor(f);\n const scope = findingScope(f);\n const candidates = matchingAssets(f, map, scope);\n\n let best: FindingExposure;\n if (candidates.length === 0) {\n best = scoreFinding(\n f,\n {\n vulnerability,\n classification: map.defaults.classification,\n // Unbound: the data's lifetime is unknown, so we cannot read X off a\n // declared asset. Assuming X = 0 would drive M (hence the score) to a\n // dead 0 for EVERY unbound finding under any sane horizon, making the\n // documented `defaults.classification` fallback unrankable. Instead we\n // assume the MINIMUM-CONCERN horizon: data captured today must stay\n // confidential at least until the quantum threat arrives (X = Z). That\n // yields M = Y / (Y + Z) - a small but non-zero, rankable exposure that\n // never exceeds a declared long-lived asset's and self-adjusts to any\n // per-org horizon override. Retention stays 0 (genuinely unknown); the\n // secrecy lifetime carries the assumption. See docs/HNDL.md §4.\n retentionYears: 0,\n secrecyLifetimeYears: map.horizon.quantumThreatYears,\n bound: false,\n },\n map.horizon,\n );\n } else {\n let bestAsset: HndlDataAsset | undefined;\n best = undefined as unknown as FindingExposure;\n for (const asset of candidates) {\n const scored = scoreFinding(\n f,\n {\n vulnerability,\n classification: asset.classification,\n retentionYears: asset.retentionYears,\n secrecyLifetimeYears: asset.secrecyLifetimeYears,\n bound: true,\n },\n map.horizon,\n );\n if (!bestAsset || scored.exposureScore > best.exposureScore) {\n best = scored;\n bestAsset = asset;\n }\n }\n best.dataAsset = bestAsset!.key;\n assetFindings.set(bestAsset!.key, (assetFindings.get(bestAsset!.key) ?? 0) + 1);\n assetMax.set(bestAsset!.key, Math.max(assetMax.get(bestAsset!.key) ?? 0, best.exposureScore));\n }\n\n exposures.push(best);\n byFingerprint.set(best.fingerprint, best);\n }\n\n const assets: AssetExposure[] = map.assets.map((a) => ({\n key: a.key,\n name: a.name,\n classification: a.classification,\n retentionYears: a.retentionYears,\n secrecyLifetimeYears: a.secrecyLifetimeYears,\n findings: assetFindings.get(a.key) ?? 0,\n maxExposure: assetMax.get(a.key) ?? 0,\n outlivesThreat:\n Math.max(a.retentionYears, a.secrecyLifetimeYears) > map.horizon.quantumThreatYears,\n }));\n\n const scores = exposures.map((e) => e.exposureScore);\n const maxExposure = scores.reduce((m, s) => Math.max(m, s), 0);\n const meanExposure =\n scores.length > 0 ? Math.round(scores.reduce((a, b) => a + b, 0) / scores.length) : 0;\n const topExposures = [...exposures]\n .sort((a, b) => b.exposureScore - a.exposureScore || a.fingerprint.localeCompare(b.fingerprint))\n .slice(0, TOP_EXPOSURES);\n\n const summary: HndlSummary = {\n findingsScored: exposures.length,\n assetsDeclared: map.assets.length,\n assetsWithFindings: assets.filter((a) => a.findings > 0).length,\n assetsOutlivingHorizon: assets.filter((a) => a.outlivesThreat).length,\n moscaBreaches: exposures.filter((e) => e.rationale.moscaBreach).length,\n maxExposure,\n meanExposure,\n topExposures,\n };\n\n return {\n modelVersion: HNDL_MODEL_VERSION,\n horizon: map.horizon,\n exposures,\n byFingerprint,\n assets,\n summary,\n };\n}\n\n/* -------------------------------------------------------------------------- */\n/* hndl.yml parsing (hand-rolled YAML subset) */\n/* -------------------------------------------------------------------------- */\n\ninterface YamlLine {\n indent: number;\n content: string;\n /** 1-based source line number, for error messages. */\n n: number;\n}\n\n/** Strip an inline `# comment` that begins after whitespace, outside quotes. */\nfunction stripInlineComment(text: string): string {\n let quote: string | undefined;\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n if (quote) {\n if (ch === quote) quote = undefined;\n continue;\n }\n if (ch === '\"' || ch === \"'\") {\n quote = ch;\n continue;\n }\n if (ch === \"#\" && (i === 0 || /\\s/.test(text[i - 1] as string))) {\n return text.slice(0, i);\n }\n }\n return text;\n}\n\n/** Tokenise text into non-blank, non-comment lines with their indent depth. */\nfunction tokenizeYaml(text: string, file?: string): YamlLine[] {\n const lines: YamlLine[] = [];\n const raw = text.split(/\\r?\\n/);\n for (let i = 0; i < raw.length; i++) {\n const line = raw[i] as string;\n if (line.includes(\"\\t\")) {\n throw new HndlError(`tabs are not allowed for indentation (line ${i + 1})`, file);\n }\n const stripped = stripInlineComment(line).replace(/\\s+$/, \"\");\n if (stripped.trim() === \"\") continue;\n const indent = stripped.length - stripped.trimStart().length;\n lines.push({ indent, content: stripped.trimStart(), n: i + 1 });\n }\n return lines;\n}\n\n/** True when `content` opens a `key:` mapping entry (colon outside quotes). */\nfunction isKeyLine(content: string): boolean {\n return /^[A-Za-z0-9_.-]+\\s*:(\\s|$)/.test(content);\n}\n\nfunction splitKey(content: string, file: string, n: number): { key: string; value: string } {\n const idx = content.indexOf(\":\");\n if (idx < 0) throw new HndlError(`expected \"key: value\" (line ${n})`, file);\n return { key: content.slice(0, idx).trim(), value: content.slice(idx + 1).trim() };\n}\n\n/** Coerce a scalar token: quoted string, boolean, number, or bare string. */\nfunction parseScalar(token: string): string | number | boolean {\n if (token.length >= 2) {\n const q = token[0];\n if ((q === '\"' || q === \"'\") && token[token.length - 1] === q) {\n return token.slice(1, -1);\n }\n }\n if (token === \"true\") return true;\n if (token === \"false\") return false;\n if (/^-?\\d+(\\.\\d+)?$/.test(token)) return Number(token);\n return token;\n}\n\n/**\n * Parse a mapping/sequence VALUE token: either an inline-flow list\n * (`[a, \"b\", c]`, `[]`) or a plain scalar. Only flat flow lists of scalars are\n * supported - enough for `paths: [...]` / `scopes: [...]` without a full YAML\n * flow grammar.\n */\nfunction parseValueToken(token: string, file: string, n: number): YamlValue {\n if (token.startsWith(\"[\")) {\n if (!token.endsWith(\"]\")) {\n throw new HndlError(`unterminated inline list (line ${n})`, file);\n }\n return parseFlowList(token.slice(1, -1), file, n);\n }\n return parseScalar(token);\n}\n\n/** Split a flow-list body on top-level commas (quote-aware) → scalar elements. */\nfunction parseFlowList(body: string, file: string, n: number): YamlValue[] {\n const out: YamlValue[] = [];\n let cur = \"\";\n let quote: string | undefined;\n for (let i = 0; i < body.length; i++) {\n const ch = body[i] as string;\n if (quote) {\n cur += ch;\n if (ch === quote) quote = undefined;\n continue;\n }\n if (ch === '\"' || ch === \"'\") {\n quote = ch;\n cur += ch;\n continue;\n }\n if (ch === \",\") {\n out.push(cur.trim());\n cur = \"\";\n continue;\n }\n cur += ch;\n }\n if (quote) throw new HndlError(`unterminated string in inline list (line ${n})`, file);\n const last = cur.trim();\n // A trailing empty segment only when the list itself is empty (`[]`).\n if (last !== \"\" || out.length > 0) out.push(last);\n return out.filter((t) => t !== \"\").map((t) => parseScalar(t as string));\n}\n\ntype YamlValue = string | number | boolean | null | YamlValue[] | { [k: string]: YamlValue };\n\n/** Recursive-descent parse of the tokenised lines into a generic value. */\nfunction parseYaml(text: string, file: string): YamlValue {\n const lines = tokenizeYaml(text, file);\n if (lines.length === 0) return {};\n\n function parseNode(i: number, indent: number): [YamlValue, number] {\n const first = lines[i] as YamlLine;\n if (first.content === \"-\" || first.content.startsWith(\"- \")) {\n return parseSeq(i, indent);\n }\n return parseMap(i, indent);\n }\n\n function parseSeq(start: number, indent: number): [YamlValue[], number] {\n const arr: YamlValue[] = [];\n let i = start;\n while (\n i < lines.length &&\n (lines[i] as YamlLine).indent === indent &&\n ((lines[i] as YamlLine).content === \"-\" || (lines[i] as YamlLine).content.startsWith(\"- \"))\n ) {\n const line = lines[i] as YamlLine;\n const rest = line.content === \"-\" ? \"\" : line.content.slice(2).trim();\n const itemIndent = indent + 2;\n if (rest === \"\") {\n if (i + 1 < lines.length && (lines[i + 1] as YamlLine).indent > indent) {\n const [val, next] = parseNode(i + 1, (lines[i + 1] as YamlLine).indent);\n arr.push(val);\n i = next;\n } else {\n arr.push(null);\n i++;\n }\n } else if (isKeyLine(rest)) {\n // Map item introduced by the dash: rewrite this line as its first key at\n // the deeper indent, then let parseMap consume it + aligned siblings.\n lines[i] = { indent: itemIndent, content: rest, n: line.n };\n const [val, next] = parseMap(i, itemIndent);\n arr.push(val);\n i = next;\n } else {\n arr.push(parseValueToken(rest, file, line.n));\n i++;\n }\n }\n return [arr, i];\n }\n\n function parseMap(start: number, indent: number): [{ [k: string]: YamlValue }, number] {\n const obj: { [k: string]: YamlValue } = {};\n let i = start;\n while (\n i < lines.length &&\n (lines[i] as YamlLine).indent === indent &&\n !(lines[i] as YamlLine).content.startsWith(\"- \") &&\n (lines[i] as YamlLine).content !== \"-\"\n ) {\n const line = lines[i] as YamlLine;\n const { key, value } = splitKey(line.content, file, line.n);\n if (value !== \"\") {\n obj[key] = parseValueToken(value, file, line.n);\n i++;\n } else if (i + 1 < lines.length && (lines[i + 1] as YamlLine).indent > indent) {\n const [val, next] = parseNode(i + 1, (lines[i + 1] as YamlLine).indent);\n obj[key] = val;\n i = next;\n } else {\n obj[key] = null;\n i++;\n }\n }\n return [obj, i];\n }\n\n const [value] = parseNode(0, (lines[0] as YamlLine).indent);\n return value;\n}\n\n/* -------------------------------------------------------------------------- */\n/* hndl.yml validation → HndlMap */\n/* -------------------------------------------------------------------------- */\n\nfunction isObject(v: YamlValue): v is { [k: string]: YamlValue } {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nfunction asString(v: YamlValue, what: string, file: string): string {\n if (typeof v !== \"string\" || v.length === 0) {\n throw new HndlError(`${what} must be a non-empty string`, file);\n }\n return v;\n}\n\nfunction asNonNegNumber(v: YamlValue, what: string, file: string): number {\n if (typeof v !== \"number\" || !Number.isFinite(v) || v < 0) {\n throw new HndlError(`${what} must be a non-negative number`, file);\n }\n return v;\n}\n\nfunction asClassification(v: YamlValue, what: string, file: string): DataClassification {\n if (typeof v !== \"string\" || !(CLASSIFICATIONS as readonly string[]).includes(v)) {\n throw new HndlError(`${what} must be one of: ${CLASSIFICATIONS.join(\", \")}`, file);\n }\n return v as DataClassification;\n}\n\nfunction asStringList(v: YamlValue, what: string, file: string): string[] {\n if (!Array.isArray(v) || v.some((x) => typeof x !== \"string\" || x.length === 0)) {\n throw new HndlError(`${what} must be a list of non-empty strings`, file);\n }\n return v as string[];\n}\n\n/**\n * Validate a parsed `hndl.yml` object into a typed {@link HndlMap}. Applies\n * defaults for `version`, `horizon`, and `defaults`; requires each asset to have\n * a unique `key`, a `name`, a valid `classification`, non-negative retention +\n * secrecy lifetime, and at least one path glob.\n */\nexport function parseHndlMap(text: string, file = HNDL_FILENAME): HndlMap {\n const root = parseYaml(text, file);\n if (!isObject(root)) {\n throw new HndlError(`hndl.yml must be a mapping at the top level`, file);\n }\n\n let version = 1;\n if (\"version\" in root) {\n const v = root[\"version\"];\n if (typeof v !== \"number\" || !Number.isInteger(v)) {\n throw new HndlError(`\"version\" must be an integer`, file);\n }\n version = v;\n }\n\n const horizon: HndlHorizon = {\n quantumThreatYears: DEFAULT_QUANTUM_THREAT_YEARS,\n migrationHorizonYears: DEFAULT_MIGRATION_HORIZON_YEARS,\n };\n if (\"horizon\" in root && root[\"horizon\"] !== null) {\n const h = root[\"horizon\"];\n if (!isObject(h)) throw new HndlError(`\"horizon\" must be a mapping`, file);\n if (\"quantum_threat_years\" in h) {\n horizon.quantumThreatYears = asNonNegNumber(\n h[\"quantum_threat_years\"],\n `\"horizon.quantum_threat_years\"`,\n file,\n );\n }\n if (\"migration_horizon_years\" in h) {\n horizon.migrationHorizonYears = asNonNegNumber(\n h[\"migration_horizon_years\"],\n `\"horizon.migration_horizon_years\"`,\n file,\n );\n }\n }\n\n const defaults: HndlDefaults = { classification: DEFAULT_UNBOUND_CLASSIFICATION };\n if (\"defaults\" in root && root[\"defaults\"] !== null) {\n const d = root[\"defaults\"];\n if (!isObject(d)) throw new HndlError(`\"defaults\" must be a mapping`, file);\n if (\"classification\" in d) {\n defaults.classification = asClassification(\n d[\"classification\"],\n `\"defaults.classification\"`,\n file,\n );\n }\n }\n\n const rawAssets = \"assets\" in root ? root[\"assets\"] : [];\n if (!Array.isArray(rawAssets)) {\n throw new HndlError(`\"assets\" must be a list`, file);\n }\n const assets: HndlDataAsset[] = [];\n const seenKeys = new Set<string>();\n for (let idx = 0; idx < rawAssets.length; idx++) {\n const a = rawAssets[idx];\n if (!isObject(a)) throw new HndlError(`assets[${idx}] must be a mapping`, file);\n const key = asString(a[\"key\"], `assets[${idx}].key`, file);\n if (seenKeys.has(key)) throw new HndlError(`duplicate asset key \"${key}\"`, file);\n seenKeys.add(key);\n const asset: HndlDataAsset = {\n key,\n name: asString(a[\"name\"], `assets[${idx}].name`, file),\n classification: asClassification(a[\"classification\"], `assets[${idx}].classification`, file),\n retentionYears: asNonNegNumber(a[\"retention_years\"], `assets[${idx}].retention_years`, file),\n secrecyLifetimeYears: asNonNegNumber(\n a[\"secrecy_lifetime_years\"],\n `assets[${idx}].secrecy_lifetime_years`,\n file,\n ),\n paths: asStringList(a[\"paths\"], `assets[${idx}].paths`, file),\n };\n if (asset.paths.length === 0) {\n throw new HndlError(`assets[${idx}].paths must list at least one glob`, file);\n }\n if (\"scopes\" in a && a[\"scopes\"] !== null) {\n const scopes = asStringList(a[\"scopes\"], `assets[${idx}].scopes`, file);\n for (const s of scopes) {\n if (!(HNDL_SCOPES as readonly string[]).includes(s)) {\n throw new HndlError(\n `assets[${idx}].scopes: \"${s}\" must be one of: ${HNDL_SCOPES.join(\", \")}`,\n file,\n );\n }\n }\n asset.scopes = scopes as HndlScope[];\n }\n assets.push(asset);\n }\n\n return { version, horizon, defaults, assets };\n}\n\n/**\n * Load and validate the `hndl.yml` for a scan. By default reads\n * `<root>/hndl.yml`; pass an explicit `*.yml` path to read a named file. A\n * missing file is always an error here (the caller opted into `--hndl`).\n *\n * @throws {HndlError} On a missing file, unreadable file, or malformed content.\n */\nexport async function loadHndlMap(root: string): Promise<{ map: HndlMap; path: string }> {\n const base = path.basename(root);\n const file =\n base === HNDL_FILENAME || base.endsWith(\".yml\") || base.endsWith(\".yaml\")\n ? path.resolve(root)\n : path.resolve(root, HNDL_FILENAME);\n let text: string;\n try {\n text = await readFile(file, \"utf8\");\n } catch {\n throw new HndlError(\n `hndl.yml not found: ${file} (run \"qscan hndl init\" to scaffold one)`,\n file,\n );\n }\n return { map: parseHndlMap(text, file), path: file };\n}\n\n/* -------------------------------------------------------------------------- */\n/* hndl.yml scaffolding (`qscan hndl init`) */\n/* -------------------------------------------------------------------------- */\n\n/** First path segment of a POSIX file path, or \".\" for a root-level file. */\nfunction topDir(file: string): string {\n const slash = file.indexOf(\"/\");\n return slash < 0 ? \".\" : file.slice(0, slash);\n}\n\n/** A URL/key-safe slug for a directory name. */\nfunction slugify(dir: string): string {\n const slug = dir\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\");\n return slug.length > 0 ? slug : \"root\";\n}\n\n/**\n * Scaffold an `hndl.yml` document seeded from a scan's findings. Config-scope,\n * HNDL-exposed findings are the crypto-to-data join points (KMS, secrets-at-rest,\n * database TDE, brokers, JOSE/JWE), so each directory that contains one becomes a\n * proposed asset stub the user fills in. The returned string is valid `hndl.yml`\n * (it round-trips through {@link parseHndlMap}); the classification / retention /\n * secrecy values are conservative placeholders the user is expected to correct.\n */\nexport function scaffoldHndlYaml(findings: readonly Finding[]): string {\n // Group data-adjacent findings by their top-level directory.\n const byDir = new Map<string, Set<string>>();\n for (const f of findings) {\n if (findingScope(f) !== \"config\" || !f.hndl) continue;\n const dir = topDir(f.location.file);\n let rules = byDir.get(dir);\n if (!rules) {\n rules = new Set<string>();\n byDir.set(dir, rules);\n }\n rules.add(f.ruleId);\n }\n\n const lines: string[] = [\n \"# hndl.yml - HNDL (harvest-now-decrypt-later) data map for this repo.\",\n \"#\",\n \"# qScan joins each crypto finding to the data it protects and scores exposure as\",\n \"# crypto-vulnerability x data-sensitivity x Mosca-factor (retention + secrecy\",\n \"# lifetime vs the quantum-threat horizon). See docs/HNDL.md for the model.\",\n \"#\",\n \"# Fill in the assets below: correct the classification, the retention_years and\",\n \"# secrecy_lifetime_years, and the path globs. Delete stubs that do not apply.\",\n \"version: 1\",\n \"\",\n \"horizon:\",\n ` quantum_threat_years: ${DEFAULT_QUANTUM_THREAT_YEARS} # Z: years until a CRQC is assumed`,\n ` migration_horizon_years: ${DEFAULT_MIGRATION_HORIZON_YEARS} # Y: years to finish your PQC migration`,\n \"\",\n \"defaults:\",\n ` classification: ${DEFAULT_UNBOUND_CLASSIFICATION} # applied to findings that match no asset below`,\n \"\",\n \"assets:\",\n ];\n\n if (byDir.size === 0) {\n lines.push(\n \" # No data-adjacent (config-scope, HNDL) findings were detected to seed from.\",\n \" # Declare your data assets manually, for example:\",\n \" - key: customer-pii\",\n \" name: Customer PII\",\n \" classification: regulated\",\n \" retention_years: 7\",\n \" secrecy_lifetime_years: 25\",\n \" paths:\",\n ' - \"src/**\"',\n );\n } else {\n const dirs = [...byDir.keys()].sort();\n for (const dir of dirs) {\n const rules = [...(byDir.get(dir) as Set<string>)].sort();\n const glob = dir === \".\" ? \"*\" : `${dir}/**`;\n lines.push(\n ` # detected data-adjacent crypto here: ${rules.join(\", \")}`,\n ` - key: ${slugify(dir)}`,\n ` name: ${dir === \".\" ? \"Repository root\" : dir}`,\n \" classification: confidential # TODO: public | internal | confidential | regulated\",\n \" retention_years: 7 # TODO: how long the data is kept\",\n \" secrecy_lifetime_years: 10 # TODO: how long it must stay confidential\",\n \" paths:\",\n ` - \"${glob}\"`,\n );\n }\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -36,6 +36,8 @@ export type { Baseline } from "./baseline.js";
|
|
|
36
36
|
export { changedFiles } from "./changed.js";
|
|
37
37
|
export { loadConfig, ConfigError, CONFIG_FILENAME } from "./config.js";
|
|
38
38
|
export type { QuantakryptoFileConfig, LoadConfigResult } from "./config.js";
|
|
39
|
+
export { HNDL_MODEL_VERSION, HNDL_FILENAME, SEVERITY_VULNERABILITY, CONFIDENCE_WEIGHT, CLASSIFICATION_SENSITIVITY, NON_HNDL_DISCOUNT, DEFAULT_QUANTUM_THREAT_YEARS, DEFAULT_MIGRATION_HORIZON_YEARS, DEFAULT_UNBOUND_CLASSIFICATION, HndlError, computeHndl, vulnerabilityFactor, moscaFactor, globMatch, findingFingerprint, findingScope, parseHndlMap, loadHndlMap, scaffoldHndlYaml, } from "./hndl.js";
|
|
40
|
+
export type { DataClassification, HndlScope, HndlDataAsset, HndlHorizon, HndlDefaults, HndlMap, ExposureRationale, FindingExposure, AssetExposure, HndlSummary, HndlReport, } from "./hndl.js";
|
|
39
41
|
export { walkFiles, isBinaryPath, looksMinified } from "./walk.js";
|
|
40
42
|
export { isAnalyzableSource, ANALYZABLE_SOURCE_EXTENSIONS, ANALYZABLE_LANGUAGES_LABEL, } from "./detect-utils.js";
|
|
41
43
|
export { buildInventory } from "./inventory.js";
|
|
@@ -48,6 +50,8 @@ export type { CycloneDxBom, CbomComponent } from "./cbom.js";
|
|
|
48
50
|
export { mergeCboms } from "./cbom-merge.js";
|
|
49
51
|
export { toOpenVex } from "./vex.js";
|
|
50
52
|
export type { OpenVexDocument, OpenVexStatement, OpenVexOptions } from "./vex.js";
|
|
53
|
+
export { buildCryptoAgilityManifest, validateCryptoAgilityManifest, CRYPTO_AGILITY_MANIFEST_VERSION, CRYPTO_AGILITY_WELL_KNOWN_PATH, } from "./crypto-agility.js";
|
|
54
|
+
export type { CryptoAgilityManifest, CryptoAgilityManifestOptions, CryptoAgilityPosture, CryptoAgilityCbomSummary, CryptoAgilityFamily, CryptoAgilityPolicy, ManifestValidation, } from "./crypto-agility.js";
|
|
51
55
|
export { buildReadinessReport, signReadinessReport, verifyReadinessReport } from "./evidence.js";
|
|
52
56
|
export type { ReadinessReport, EvidenceFinding, ReadinessReportOptions, EvidenceSigner, SignEvidenceOptions, VerifyReadinessResult, } from "./evidence.js";
|
|
53
57
|
export { buildPolicyMapping, parseCryptoPolicy } from "./policy.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGzE,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC7D,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,YAAY,EACV,YAAY,EACZ,eAAe,EACf,aAAa,EACb,KAAK,EACL,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACvF,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACrE,YAAY,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,aAAa,GACd,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAI9D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGlE,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG5C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACvE,YAAY,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG5E,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,iBAAiB,EACjB,0BAA0B,EAC1B,iBAAiB,EACjB,4BAA4B,EAC5B,+BAA+B,EAC/B,8BAA8B,EAC9B,SAAS,EACT,WAAW,EACX,mBAAmB,EACnB,WAAW,EACX,SAAS,EACT,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,gBAAgB,GACjB,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,kBAAkB,EAClB,SAAS,EACT,aAAa,EACb,WAAW,EACX,YAAY,EACZ,OAAO,EACP,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,WAAW,EACX,UAAU,GACX,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAGnE,OAAO,EACL,kBAAkB,EAClB,4BAA4B,EAC5B,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAKhD,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGhG,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGzF,OAAO,EACL,OAAO,EACP,MAAM,EACN,aAAa,EACb,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE7D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAElF,OAAO,EACL,0BAA0B,EAC1B,6BAA6B,EAC7B,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,qBAAqB,EACrB,4BAA4B,EAC5B,oBAAoB,EACpB,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AACjG,YAAY,EACV,eAAe,EACf,eAAe,EACf,sBAAsB,EACtB,cAAc,EACd,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACpE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGpG,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGrD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAG7F,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAG9E,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,UAAU,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -36,6 +36,8 @@ export { fingerprintFinding, baselineFromFindings, applyBaseline, loadBaseline,
|
|
|
36
36
|
export { changedFiles } from "./changed.js";
|
|
37
37
|
// Optional `quantakrypto.config.json` loader (P2-9; see docs/CONFIG.md).
|
|
38
38
|
export { loadConfig, ConfigError, CONFIG_FILENAME } from "./config.js";
|
|
39
|
+
// HNDL (harvest-now-decrypt-later) data-risk quantifier (see docs/HNDL.md).
|
|
40
|
+
export { HNDL_MODEL_VERSION, HNDL_FILENAME, SEVERITY_VULNERABILITY, CONFIDENCE_WEIGHT, CLASSIFICATION_SENSITIVITY, NON_HNDL_DISCOUNT, DEFAULT_QUANTUM_THREAT_YEARS, DEFAULT_MIGRATION_HORIZON_YEARS, DEFAULT_UNBOUND_CLASSIFICATION, HndlError, computeHndl, vulnerabilityFactor, moscaFactor, globMatch, findingFingerprint, findingScope, parseHndlMap, loadHndlMap, scaffoldHndlYaml, } from "./hndl.js";
|
|
39
41
|
// Filesystem walker (relative POSIX paths, default ignores, size/binary filters).
|
|
40
42
|
export { walkFiles, isBinaryPath, looksMinified } from "./walk.js";
|
|
41
43
|
// Analyzable-language coverage (which source languages the scanner inspects).
|
|
@@ -56,6 +58,8 @@ export { toCbom } from "./cbom.js";
|
|
|
56
58
|
export { mergeCboms } from "./cbom-merge.js";
|
|
57
59
|
// OpenVEX 0.2.0 export — quantum-readiness posture as VEX statements.
|
|
58
60
|
export { toOpenVex } from "./vex.js";
|
|
61
|
+
// Crypto-agility manifest: agent-consumable crypto-posture document.
|
|
62
|
+
export { buildCryptoAgilityManifest, validateCryptoAgilityManifest, CRYPTO_AGILITY_MANIFEST_VERSION, CRYPTO_AGILITY_WELL_KNOWN_PATH, } from "./crypto-agility.js";
|
|
59
63
|
// ISO/IEC 27001 A.8.24 evidence-chain readiness report.
|
|
60
64
|
export { buildReadinessReport, signReadinessReport, verifyReadinessReport } from "./evidence.js";
|
|
61
65
|
// Cryptography policy → per-finding verdicts (A.8.24 evidence §4).
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,cAAc,YAAY,CAAC;AAE3B,qEAAqE;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAKvC,8CAA8C;AAC9C,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEzE,2EAA2E;AAC3E,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAW7D,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEvF,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAErE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAQ5D,0CAA0C;AAC1C,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE9D,6EAA6E;AAC7E,kFAAkF;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAG7C,kFAAkF;AAClF,YAAY;AACZ,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAElE,qDAAqD;AACrD,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAGvB,oEAAoE;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,yEAAyE;AACzE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGvE,kFAAkF;AAClF,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAEnE,8EAA8E;AAC9E,OAAO,EACL,kBAAkB,EAClB,4BAA4B,EAC5B,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAE3B,+BAA+B;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,sFAAsF;AACtF,6EAA6E;AAC7E,gFAAgF;AAChF,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEhG,+EAA+E;AAC/E,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEzF,aAAa;AACb,OAAO,EACL,OAAO,EACP,MAAM,EACN,aAAa,EACb,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAGrB,+DAA+D;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,8EAA8E;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,sEAAsE;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,wDAAwD;AACxD,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAUjG,mEAAmE;AACnE,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGpE,sFAAsF;AACtF,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAG1B,2DAA2D;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAG/C,2EAA2E;AAC3E,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AAGjC,4BAA4B;AAC5B,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,UAAU,CAAC","sourcesContent":["/**\n * @quantakrypto/core — public API (LOCKED CONTRACT).\n *\n * The exported NAMES and SIGNATURES below are the stable contract that\n * @quantakrypto/qscan, @quantakrypto/mcp and the GitHub Action depend on — do not change\n * them without updating all consumers. The implementations live in focused\n * modules under src/ and are re-exported here; the public surface is identical\n * to the original stub file.\n */\nexport * from \"./types.js\";\n\n// Tool version, surfaced in reports. Keep in sync with package.json.\nexport { VERSION } from \"./version.js\";\n\n// Minimal SARIF 2.1.0 log shape, defined alongside the reporters.\nexport type { SarifLog } from \"./report.js\";\n\n// Core orchestration + built-in detector set.\nexport { scan, detectors, detectFile, compareFindings } from \"./scan.js\";\n\n// Snippet-level fix verification (shared by MCP verify_fix + remediation).\nexport { verifyFix, languageToExtension } from \"./verify.js\";\nexport type { VerifyResult } from \"./verify.js\";\n\n// Agent-plane shared types + the context redactor (offline; reused by MCP).\nexport type {\n ContextLevel,\n RedactedContext,\n TriageVerdict,\n Patch,\n FixProposal,\n} from \"./agent-types.js\";\nexport { buildContext, renderPreflight } from \"./redact.js\";\nexport { TRIAGE_RUBRIC, TRIAGE_VERDICT_SCHEMA, buildTriageRequest } from \"./triage.js\";\nexport type { TriageRequest } from \"./triage.js\";\nexport {\n REMEDIATE_RUBRIC,\n FIX_REQUEST_SCHEMA,\n buildRemediateRequest,\n} from \"./remediate-request.js\";\nexport type { RemediateRequest } from \"./remediate-request.js\";\nexport { checkPatchPolicy } from \"./patch-policy.js\";\nexport type { PolicyContext, PolicyDecision } from \"./patch-policy.js\";\nexport { withWorktree } from \"./worktree.js\";\nexport { codemodRegistry, codemodFor } from \"./codemods/registry.js\";\nexport type { Codemod } from \"./codemods/registry.js\";\nexport { configToggleCodemod } from \"./codemods/config-toggle.js\";\nexport { remediateFindings } from \"./remediate-pipeline.js\";\nexport type {\n RemediateOptions,\n RemediationResult,\n VerifiedPatch,\n RejectedPatch,\n} from \"./remediate-pipeline.js\";\n\n// Scan cancellation / work-budget errors.\nexport { AbortError, BudgetExceededError } from \"./errors.js\";\n\n// Parallel scanning (worker_threads pool). The chunk/merge helpers and their\n// SizedFile/ChunkResult types are internal plumbing (not part of the public API).\nexport { scanParallel } from \"./parallel.js\";\nexport type { ScanChunk } from \"./parallel.js\";\n\n// Detector registry (plugin point). `detectorScope` and the rule-catalog type are\n// internal.\nexport { DetectorRegistry, defaultRegistry } from \"./registry.js\";\n\n// Canonical baseline (shared by qScan + the Action).\nexport {\n fingerprintFinding,\n baselineFromFindings,\n applyBaseline,\n loadBaseline,\n saveBaseline,\n BASELINE_VERSION,\n} from \"./baseline.js\";\nexport type { Baseline } from \"./baseline.js\";\n\n// Incremental scanning: changed-files helper (git-aware, tolerant).\nexport { changedFiles } from \"./changed.js\";\n\n// Optional `quantakrypto.config.json` loader (P2-9; see docs/CONFIG.md).\nexport { loadConfig, ConfigError, CONFIG_FILENAME } from \"./config.js\";\nexport type { QuantakryptoFileConfig, LoadConfigResult } from \"./config.js\";\n\n// Filesystem walker (relative POSIX paths, default ignores, size/binary filters).\nexport { walkFiles, isBinaryPath, looksMinified } from \"./walk.js\";\n\n// Analyzable-language coverage (which source languages the scanner inspects).\nexport {\n isAnalyzableSource,\n ANALYZABLE_SOURCE_EXTENSIONS,\n ANALYZABLE_LANGUAGES_LABEL,\n} from \"./detect-utils.js\";\n\n// Inventory + readiness score.\nexport { buildInventory } from \"./inventory.js\";\n\n// Vulnerable-dependency database (the manifest scanner is used internally by scan()).\n// `DEP_VULNERABLE_RULE` is the generic catalog entry for dependency findings\n// (which don't come from a Detector, so aren't in the registry's rule catalog).\nexport { vulnerableDependencies, DEP_VULNERABLE_RULE, isManifestFile } from \"./dependencies.js\";\n\n// Severity utilities (ordering, threshold, SARIF level) — shared across tools.\nexport { SEVERITY_ORDER, severityRank, meetsThreshold, sarifLevel } from \"./severity.js\";\n\n// Reporters.\nexport {\n toSarif,\n toJson,\n formatSummary,\n formatTierGuidance,\n formatProfileGuidance,\n} from \"./report.js\";\nexport type { ReportOptions } from \"./report.js\";\n\n// CycloneDX 1.6 cryptographic bill of materials (CBOM) export.\nexport { toCbom } from \"./cbom.js\";\nexport type { CycloneDxBom, CbomComponent } from \"./cbom.js\";\n// Merge multiple CBOMs (code + infra + live endpoints) into one combined BOM.\nexport { mergeCboms } from \"./cbom-merge.js\";\n// OpenVEX 0.2.0 export — quantum-readiness posture as VEX statements.\nexport { toOpenVex } from \"./vex.js\";\nexport type { OpenVexDocument, OpenVexStatement, OpenVexOptions } from \"./vex.js\";\n// ISO/IEC 27001 A.8.24 evidence-chain readiness report.\nexport { buildReadinessReport, signReadinessReport, verifyReadinessReport } from \"./evidence.js\";\nexport type {\n ReadinessReport,\n EvidenceFinding,\n ReadinessReportOptions,\n EvidenceSigner,\n SignEvidenceOptions,\n VerifyReadinessResult,\n} from \"./evidence.js\";\n\n// Cryptography policy → per-finding verdicts (A.8.24 evidence §4).\nexport { buildPolicyMapping, parseCryptoPolicy } from \"./policy.js\";\nexport type { CryptoPolicy, PolicyVerdict, PolicyMapping, PolicyFindingVerdict } from \"./policy.js\";\n\n// Remediation lookup (family + tier-aware + profile-aware) and stateful-HBS guidance.\nexport {\n remediationFor,\n remediationForTier,\n remediationForProfile,\n TIER_PARAMS,\n STATEFUL_HBS_NOTE,\n PQC_TRANSITION_NOTE,\n statefulHbsApplies,\n} from \"./remediation.js\";\nexport type { SecurityTier } from \"./remediation.js\";\n\n// Post-quantum standards source of truth + review cadence.\nexport { PQC_STANDARDS } from \"./standards.js\";\nexport type { PqcStandards, StandardsCitation, StandardsReviewStatus } from \"./standards.js\";\n\n// Selectable standards regime profiles (NIST / CNSA / BSI / ANSSI / NCSC).\nexport {\n STANDARDS_PROFILES,\n DEFAULT_PROFILE_ID,\n standardsProfileIds,\n getStandardsProfile,\n defaultStandardsProfile,\n} from \"./standards-profiles.js\";\nexport type { StandardsProfile, HybridStance } from \"./standards-profiles.js\";\n\n// CWE identifier constants.\nexport {\n CWE_BROKEN_CRYPTO,\n CWE_WEAK_STRENGTH,\n CWE_CERT_VALIDATION,\n CWE_HARDCODED_KEY,\n CWE_RISKY_PRIMITIVE,\n} from \"./cwe.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @quantakrypto/core — public API (LOCKED CONTRACT).\n *\n * The exported NAMES and SIGNATURES below are the stable contract that\n * @quantakrypto/qscan, @quantakrypto/mcp and the GitHub Action depend on — do not change\n * them without updating all consumers. The implementations live in focused\n * modules under src/ and are re-exported here; the public surface is identical\n * to the original stub file.\n */\nexport * from \"./types.js\";\n\n// Tool version, surfaced in reports. Keep in sync with package.json.\nexport { VERSION } from \"./version.js\";\n\n// Minimal SARIF 2.1.0 log shape, defined alongside the reporters.\nexport type { SarifLog } from \"./report.js\";\n\n// Core orchestration + built-in detector set.\nexport { scan, detectors, detectFile, compareFindings } from \"./scan.js\";\n\n// Snippet-level fix verification (shared by MCP verify_fix + remediation).\nexport { verifyFix, languageToExtension } from \"./verify.js\";\nexport type { VerifyResult } from \"./verify.js\";\n\n// Agent-plane shared types + the context redactor (offline; reused by MCP).\nexport type {\n ContextLevel,\n RedactedContext,\n TriageVerdict,\n Patch,\n FixProposal,\n} from \"./agent-types.js\";\nexport { buildContext, renderPreflight } from \"./redact.js\";\nexport { TRIAGE_RUBRIC, TRIAGE_VERDICT_SCHEMA, buildTriageRequest } from \"./triage.js\";\nexport type { TriageRequest } from \"./triage.js\";\nexport {\n REMEDIATE_RUBRIC,\n FIX_REQUEST_SCHEMA,\n buildRemediateRequest,\n} from \"./remediate-request.js\";\nexport type { RemediateRequest } from \"./remediate-request.js\";\nexport { checkPatchPolicy } from \"./patch-policy.js\";\nexport type { PolicyContext, PolicyDecision } from \"./patch-policy.js\";\nexport { withWorktree } from \"./worktree.js\";\nexport { codemodRegistry, codemodFor } from \"./codemods/registry.js\";\nexport type { Codemod } from \"./codemods/registry.js\";\nexport { configToggleCodemod } from \"./codemods/config-toggle.js\";\nexport { remediateFindings } from \"./remediate-pipeline.js\";\nexport type {\n RemediateOptions,\n RemediationResult,\n VerifiedPatch,\n RejectedPatch,\n} from \"./remediate-pipeline.js\";\n\n// Scan cancellation / work-budget errors.\nexport { AbortError, BudgetExceededError } from \"./errors.js\";\n\n// Parallel scanning (worker_threads pool). The chunk/merge helpers and their\n// SizedFile/ChunkResult types are internal plumbing (not part of the public API).\nexport { scanParallel } from \"./parallel.js\";\nexport type { ScanChunk } from \"./parallel.js\";\n\n// Detector registry (plugin point). `detectorScope` and the rule-catalog type are\n// internal.\nexport { DetectorRegistry, defaultRegistry } from \"./registry.js\";\n\n// Canonical baseline (shared by qScan + the Action).\nexport {\n fingerprintFinding,\n baselineFromFindings,\n applyBaseline,\n loadBaseline,\n saveBaseline,\n BASELINE_VERSION,\n} from \"./baseline.js\";\nexport type { Baseline } from \"./baseline.js\";\n\n// Incremental scanning: changed-files helper (git-aware, tolerant).\nexport { changedFiles } from \"./changed.js\";\n\n// Optional `quantakrypto.config.json` loader (P2-9; see docs/CONFIG.md).\nexport { loadConfig, ConfigError, CONFIG_FILENAME } from \"./config.js\";\nexport type { QuantakryptoFileConfig, LoadConfigResult } from \"./config.js\";\n\n// HNDL (harvest-now-decrypt-later) data-risk quantifier (see docs/HNDL.md).\nexport {\n HNDL_MODEL_VERSION,\n HNDL_FILENAME,\n SEVERITY_VULNERABILITY,\n CONFIDENCE_WEIGHT,\n CLASSIFICATION_SENSITIVITY,\n NON_HNDL_DISCOUNT,\n DEFAULT_QUANTUM_THREAT_YEARS,\n DEFAULT_MIGRATION_HORIZON_YEARS,\n DEFAULT_UNBOUND_CLASSIFICATION,\n HndlError,\n computeHndl,\n vulnerabilityFactor,\n moscaFactor,\n globMatch,\n findingFingerprint,\n findingScope,\n parseHndlMap,\n loadHndlMap,\n scaffoldHndlYaml,\n} from \"./hndl.js\";\nexport type {\n DataClassification,\n HndlScope,\n HndlDataAsset,\n HndlHorizon,\n HndlDefaults,\n HndlMap,\n ExposureRationale,\n FindingExposure,\n AssetExposure,\n HndlSummary,\n HndlReport,\n} from \"./hndl.js\";\n\n// Filesystem walker (relative POSIX paths, default ignores, size/binary filters).\nexport { walkFiles, isBinaryPath, looksMinified } from \"./walk.js\";\n\n// Analyzable-language coverage (which source languages the scanner inspects).\nexport {\n isAnalyzableSource,\n ANALYZABLE_SOURCE_EXTENSIONS,\n ANALYZABLE_LANGUAGES_LABEL,\n} from \"./detect-utils.js\";\n\n// Inventory + readiness score.\nexport { buildInventory } from \"./inventory.js\";\n\n// Vulnerable-dependency database (the manifest scanner is used internally by scan()).\n// `DEP_VULNERABLE_RULE` is the generic catalog entry for dependency findings\n// (which don't come from a Detector, so aren't in the registry's rule catalog).\nexport { vulnerableDependencies, DEP_VULNERABLE_RULE, isManifestFile } from \"./dependencies.js\";\n\n// Severity utilities (ordering, threshold, SARIF level) — shared across tools.\nexport { SEVERITY_ORDER, severityRank, meetsThreshold, sarifLevel } from \"./severity.js\";\n\n// Reporters.\nexport {\n toSarif,\n toJson,\n formatSummary,\n formatTierGuidance,\n formatProfileGuidance,\n} from \"./report.js\";\nexport type { ReportOptions } from \"./report.js\";\n\n// CycloneDX 1.6 cryptographic bill of materials (CBOM) export.\nexport { toCbom } from \"./cbom.js\";\nexport type { CycloneDxBom, CbomComponent } from \"./cbom.js\";\n// Merge multiple CBOMs (code + infra + live endpoints) into one combined BOM.\nexport { mergeCboms } from \"./cbom-merge.js\";\n// OpenVEX 0.2.0 export — quantum-readiness posture as VEX statements.\nexport { toOpenVex } from \"./vex.js\";\nexport type { OpenVexDocument, OpenVexStatement, OpenVexOptions } from \"./vex.js\";\n// Crypto-agility manifest: agent-consumable crypto-posture document.\nexport {\n buildCryptoAgilityManifest,\n validateCryptoAgilityManifest,\n CRYPTO_AGILITY_MANIFEST_VERSION,\n CRYPTO_AGILITY_WELL_KNOWN_PATH,\n} from \"./crypto-agility.js\";\nexport type {\n CryptoAgilityManifest,\n CryptoAgilityManifestOptions,\n CryptoAgilityPosture,\n CryptoAgilityCbomSummary,\n CryptoAgilityFamily,\n CryptoAgilityPolicy,\n ManifestValidation,\n} from \"./crypto-agility.js\";\n// ISO/IEC 27001 A.8.24 evidence-chain readiness report.\nexport { buildReadinessReport, signReadinessReport, verifyReadinessReport } from \"./evidence.js\";\nexport type {\n ReadinessReport,\n EvidenceFinding,\n ReadinessReportOptions,\n EvidenceSigner,\n SignEvidenceOptions,\n VerifyReadinessResult,\n} from \"./evidence.js\";\n\n// Cryptography policy → per-finding verdicts (A.8.24 evidence §4).\nexport { buildPolicyMapping, parseCryptoPolicy } from \"./policy.js\";\nexport type { CryptoPolicy, PolicyVerdict, PolicyMapping, PolicyFindingVerdict } from \"./policy.js\";\n\n// Remediation lookup (family + tier-aware + profile-aware) and stateful-HBS guidance.\nexport {\n remediationFor,\n remediationForTier,\n remediationForProfile,\n TIER_PARAMS,\n STATEFUL_HBS_NOTE,\n PQC_TRANSITION_NOTE,\n statefulHbsApplies,\n} from \"./remediation.js\";\nexport type { SecurityTier } from \"./remediation.js\";\n\n// Post-quantum standards source of truth + review cadence.\nexport { PQC_STANDARDS } from \"./standards.js\";\nexport type { PqcStandards, StandardsCitation, StandardsReviewStatus } from \"./standards.js\";\n\n// Selectable standards regime profiles (NIST / CNSA / BSI / ANSSI / NCSC).\nexport {\n STANDARDS_PROFILES,\n DEFAULT_PROFILE_ID,\n standardsProfileIds,\n getStandardsProfile,\n defaultStandardsProfile,\n} from \"./standards-profiles.js\";\nexport type { StandardsProfile, HybridStance } from \"./standards-profiles.js\";\n\n// CWE identifier constants.\nexport {\n CWE_BROKEN_CRYPTO,\n CWE_WEAK_STRENGTH,\n CWE_CERT_VALIDATION,\n CWE_HARDCODED_KEY,\n CWE_RISKY_PRIMITIVE,\n} from \"./cwe.js\";\n"]}
|
package/dist/parallel.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parallel.d.ts","sourceRoot":"","sources":["../src/parallel.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAQ3E,+CAA+C;AAC/C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,yCAAyC;AACzC,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAMD,kEAAkE;AAClE,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,CAgBzF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,CAa9E;
|
|
1
|
+
{"version":3,"file":"parallel.d.ts","sourceRoot":"","sources":["../src/parallel.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAQ3E,+CAA+C;AAC/C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,yCAAyC;AACzC,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAMD,kEAAkE;AAClE,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,CAgBzF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,CAa9E;AAwED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,CAkGpF"}
|
package/dist/parallel.js
CHANGED
|
@@ -13,7 +13,7 @@ import { existsSync } from "node:fs";
|
|
|
13
13
|
import * as os from "node:os";
|
|
14
14
|
import * as path from "node:path";
|
|
15
15
|
import { fileURLToPath } from "node:url";
|
|
16
|
-
import {
|
|
16
|
+
import { walkFilesSized } from "./walk.js";
|
|
17
17
|
import { isAnalyzableSource } from "./detect-utils.js";
|
|
18
18
|
import { buildInventory } from "./inventory.js";
|
|
19
19
|
import { compareFindings, filterExplicitFileList, scan } from "./scan.js";
|
|
@@ -87,32 +87,31 @@ function shouldParallelize(options, files) {
|
|
|
87
87
|
* explicit `files` list or the walker. Sizes power byte-balanced chunking.
|
|
88
88
|
*/
|
|
89
89
|
async function enumerateFiles(options, baseDir) {
|
|
90
|
-
const
|
|
90
|
+
const sized = [];
|
|
91
91
|
if (options.files) {
|
|
92
|
+
// Explicit file list: the walker isn't involved, so stat each once here.
|
|
92
93
|
// Apply the SAME include/exclude/binary filtering the serial path uses via
|
|
93
|
-
// `
|
|
94
|
-
for (const rel of filterExplicitFileList(options.files, options))
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
})) {
|
|
104
|
-
rels.push(rel);
|
|
94
|
+
// `filterExplicitFileList`, so `--parallel` is byte-for-byte identical to serial.
|
|
95
|
+
for (const rel of filterExplicitFileList(options.files, options)) {
|
|
96
|
+
let size = 0;
|
|
97
|
+
try {
|
|
98
|
+
size = (await stat(path.join(baseDir, ...rel.split("/")))).size;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// Unreadable now; keep with size 0 (the worker read will skip if it's gone).
|
|
102
|
+
}
|
|
103
|
+
sized.push({ rel, size });
|
|
105
104
|
}
|
|
105
|
+
return sized;
|
|
106
106
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
107
|
+
// Directory walk: reuse the size the walker already stat'd while enforcing the
|
|
108
|
+
// size limit, so files are not stat'd a second time here (double-stat fix).
|
|
109
|
+
for await (const { rel, size } of walkFilesSized(options.root, {
|
|
110
|
+
include: options.include,
|
|
111
|
+
exclude: options.exclude,
|
|
112
|
+
noDefaultIgnores: options.noDefaultIgnores,
|
|
113
|
+
maxFileSize: options.maxFileSize,
|
|
114
|
+
})) {
|
|
116
115
|
sized.push({ rel, size });
|
|
117
116
|
}
|
|
118
117
|
return sized;
|
package/dist/parallel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parallel.js","sourceRoot":"","sources":["../src/parallel.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Parallel scanning over a worker-thread pool (P2-1). The scan is embarrassingly\n * parallel: each file is read and regex-scanned independently, and the merge is\n * a concatenation + the existing deterministic sort. `Finding` is plain\n * structured-cloneable data, so it crosses the worker boundary cleanly.\n *\n * The merge and chunking logic are pure and exported for direct unit testing.\n * `scanParallel` falls back to the in-process serial path below the crossover\n * (small file counts / small total bytes) and whenever workers are unavailable.\n */\nimport { stat } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport type { Worker as NodeWorker } from \"node:worker_threads\";\n\nimport type { Finding, ParallelScanOptions, ScanResult } from \"./types.js\";\nimport { walkFiles } from \"./walk.js\";\nimport { isAnalyzableSource } from \"./detect-utils.js\";\nimport { buildInventory } from \"./inventory.js\";\nimport { compareFindings, filterExplicitFileList, scan } from \"./scan.js\";\nimport { AbortError, BudgetExceededError } from \"./errors.js\";\nimport { VERSION } from \"./version.js\";\n\n/** One unit of work dispatched to a worker. */\nexport interface ScanChunk {\n files: string[];\n}\n\n/** What a worker returns for a chunk. */\nexport interface ChunkResult {\n findings: Finding[];\n filesScanned: number;\n /** Files that couldn't be read in this chunk (optional; older workers omit it). */\n unreadable?: number;\n /** Files skipped as minified in this chunk (optional; older workers omit it). */\n skippedMinified?: number;\n}\n\nconst DEFAULT_PARALLEL_THRESHOLD_BYTES = 2 * 1024 * 1024;\nconst DEFAULT_PARALLEL_FILE_THRESHOLD = 200;\nconst DEFAULT_CHUNK_BYTES = 4 * 1024 * 1024;\n\n/** A file plus its byte size, used for byte-balanced chunking. */\nexport interface SizedFile {\n rel: string;\n size: number;\n}\n\n/**\n * Bucket files into chunks of roughly `chunkBytes` total bytes each, so one\n * large file doesn't starve a worker holding many tiny files. Pure +\n * deterministic: input order is preserved within and across chunks.\n */\nexport function chunkByBytes(files: readonly SizedFile[], chunkBytes: number): ScanChunk[] {\n const limit = Math.max(1, chunkBytes);\n const chunks: ScanChunk[] = [];\n let current: string[] = [];\n let currentBytes = 0;\n for (const f of files) {\n if (current.length > 0 && currentBytes + f.size > limit) {\n chunks.push({ files: current });\n current = [];\n currentBytes = 0;\n }\n current.push(f.rel);\n currentBytes += f.size;\n }\n if (current.length > 0) chunks.push({ files: current });\n return chunks;\n}\n\n/**\n * Merge per-chunk results into a single ordered finding set + total file count.\n * Pure: applies the SAME comparator as the serial scan, so the result is\n * byte-identical regardless of chunk completion order. Exported for unit tests.\n */\nexport function mergeChunkResults(results: readonly ChunkResult[]): ChunkResult {\n const findings: Finding[] = [];\n let filesScanned = 0;\n let unreadable = 0;\n let skippedMinified = 0;\n for (const r of results) {\n for (const f of r.findings) findings.push(f);\n filesScanned += r.filesScanned;\n unreadable += r.unreadable ?? 0;\n skippedMinified += r.skippedMinified ?? 0;\n }\n findings.sort(compareFindings);\n return { findings, filesScanned, unreadable, skippedMinified };\n}\n\n/** Resolve the worker count (>= 1). */\nfunction resolveConcurrency(options: ParallelScanOptions): number {\n const raw = options.concurrency;\n if (typeof raw === \"number\" && raw >= 1) return Math.floor(raw);\n const avail =\n typeof os.availableParallelism === \"function\" ? os.availableParallelism() : os.cpus().length;\n return Math.max(1, avail);\n}\n\n/** Decide whether the workload is large enough to justify spawning workers. */\nfunction shouldParallelize(options: ParallelScanOptions, files: SizedFile[]): boolean {\n const totalBytes = files.reduce((acc, f) => acc + f.size, 0);\n const byteFloor = options.parallelThresholdBytes ?? DEFAULT_PARALLEL_THRESHOLD_BYTES;\n const fileFloor = options.parallelFileThreshold ?? DEFAULT_PARALLEL_FILE_THRESHOLD;\n if (resolveConcurrency(options) <= 1) return false;\n return totalBytes >= byteFloor && files.length >= fileFloor;\n}\n\n/**\n * Enumerate the files to scan (relative POSIX paths + sizes), honouring an\n * explicit `files` list or the walker. Sizes power byte-balanced chunking.\n */\nasync function enumerateFiles(options: ParallelScanOptions, baseDir: string): Promise<SizedFile[]> {\n const rels: string[] = [];\n if (options.files) {\n // Apply the SAME include/exclude/binary filtering the serial path uses via\n // `filterExplicitFiles`, so `--parallel` is byte-for-byte identical to serial.\n for (const rel of filterExplicitFileList(options.files, options)) rels.push(rel);\n } else {\n for await (const rel of walkFiles(options.root, {\n include: options.include,\n exclude: options.exclude,\n noDefaultIgnores: options.noDefaultIgnores,\n maxFileSize: options.maxFileSize,\n })) {\n rels.push(rel);\n }\n }\n\n const sized: SizedFile[] = [];\n for (const rel of rels) {\n let size = 0;\n try {\n size = (await stat(path.join(baseDir, ...rel.split(\"/\")))).size;\n } catch {\n // Unreadable now; keep with size 0 — worker read will skip if it's gone.\n }\n sized.push({ rel, size });\n }\n return sized;\n}\n\n/**\n * Resolve the worker entry next to this module. In a normal build it's\n * `dist/scan-worker.js`. When running from source under a TypeScript loader\n * (tsx) the built JS doesn't exist, so fall back to `scan-worker.ts` and tell\n * the worker to load tsx as well — so the parallel scanner works in dev/source\n * mode (and is exercisable by tests), not only after a build.\n */\nfunction workerEntry(): { entry: string; execArgv?: string[] } {\n const here = fileURLToPath(import.meta.url);\n const dir = path.dirname(here);\n const js = path.join(dir, \"scan-worker.js\");\n if (existsSync(js)) return { entry: js };\n const ts = path.join(dir, \"scan-worker.ts\");\n if (existsSync(ts)) return { entry: ts, execArgv: [\"--import\", \"tsx\"] };\n return { entry: js }; // neither present: let Worker surface a clear ENOENT\n}\n\n/**\n * Scan in parallel across a worker-thread pool, falling back to the in-process\n * serial {@link scan} for small workloads or when workers can't be used. The\n * result is deterministic and identical to the serial path.\n */\nexport async function scanParallel(options: ParallelScanOptions): Promise<ScanResult> {\n const startedAt = new Date();\n\n const rootStat = await stat(options.root);\n const baseDir = rootStat.isFile() ? path.dirname(options.root) : options.root;\n\n // Single-file roots, the override-detectors path, and the scan cache always\n // run serially: detectors may not be structured-cloneable across the worker\n // boundary, and the cache read/write is owned by the in-process `scan()`.\n if (rootStat.isFile() || options.detectors || options.cacheFile) {\n return scan(options);\n }\n\n const files = await enumerateFiles(options, baseDir);\n\n // Budget + cancellation parity with the serial path. The parallel path\n // enumerates upfront, so budgets are enforced against the whole file set\n // before any worker is dispatched.\n if (options.signal?.aborted) throw new AbortError();\n if (typeof options.maxFiles === \"number\" && files.length > options.maxFiles) {\n throw new BudgetExceededError(`maxFiles budget exceeded (limit: ${options.maxFiles}).`);\n }\n if (typeof options.maxBytes === \"number\") {\n const totalBytes = files.reduce((n, f) => n + f.size, 0);\n if (totalBytes > options.maxBytes) {\n throw new BudgetExceededError(`maxBytes budget exceeded (limit: ${options.maxBytes}).`);\n }\n }\n\n if (!shouldParallelize(options, files)) {\n // In-process: reuse the exact serial path over the same file list.\n return scan({ ...options, files: files.map((f) => f.rel) });\n }\n\n let WorkerCtor: typeof import(\"node:worker_threads\").Worker;\n try {\n ({ Worker: WorkerCtor } = await import(\"node:worker_threads\"));\n } catch {\n return scan({ ...options, files: files.map((f) => f.rel) });\n }\n\n const chunks = chunkByBytes(files, options.chunkBytes ?? DEFAULT_CHUNK_BYTES);\n const concurrency = Math.min(resolveConcurrency(options), chunks.length);\n const { entry, execArgv } = workerEntry();\n\n const toggles = {\n source: options.source !== false,\n config: options.config !== false,\n deps: options.dependencies !== false,\n scanMinified: options.scanMinified === true,\n // Plain string array — structured-cloneable, so it crosses the worker boundary.\n disabledRules: options.disabledRules,\n };\n\n let results: ChunkResult[];\n try {\n results = await runPool(\n WorkerCtor,\n entry,\n execArgv,\n baseDir,\n toggles,\n chunks,\n concurrency,\n options.onFile,\n options.signal,\n );\n } catch (err) {\n // Cancellation / budget overflow must propagate, not silently degrade.\n if (err instanceof AbortError || err instanceof BudgetExceededError) throw err;\n // Any other worker failure → safe fallback to the serial path.\n return scan({ ...options, files: files.map((f) => f.rel) });\n }\n\n const merged = mergeChunkResults(results);\n const inventory = buildInventory(merged.findings);\n const finishedAt = new Date();\n\n // Coverage: count analyzable-source files in the enumerated set. Computed from\n // the file list (not per-worker) to avoid worker-boundary plumbing; on the\n // parallel path this can include a minified analyzable file the workers\n // skipped, but that is vanishingly rare and never under-reports coverage.\n const analyzedFiles = files.reduce((n, f) => (isAnalyzableSource(f.rel) ? n + 1 : n), 0);\n\n return {\n root: options.root,\n findings: merged.findings,\n filesScanned: merged.filesScanned,\n analyzedFiles,\n diagnostics: {\n unreadable: merged.unreadable ?? 0,\n skippedMinified: merged.skippedMinified ?? 0,\n },\n inventory,\n startedAt: startedAt.toISOString(),\n finishedAt: finishedAt.toISOString(),\n toolVersion: VERSION,\n };\n}\n\n/** Worker-pool driver: at most `concurrency` workers, each pulls chunks. */\nfunction runPool(\n WorkerCtor: typeof import(\"node:worker_threads\").Worker,\n entry: string,\n execArgv: string[] | undefined,\n baseDir: string,\n toggles: {\n source: boolean;\n config: boolean;\n deps: boolean;\n scanMinified: boolean;\n disabledRules?: string[];\n },\n chunks: ScanChunk[],\n concurrency: number,\n onFile?: (file: string) => void,\n signal?: AbortSignal,\n): Promise<ChunkResult[]> {\n return new Promise((resolve, reject) => {\n const results: ChunkResult[] = new Array(chunks.length);\n let next = 0;\n let done = 0;\n let failed = false;\n const workers: Array<NodeWorker> = [];\n\n const onAbort = (): void => {\n if (failed) return;\n failed = true;\n cleanup();\n reject(new AbortError());\n };\n\n const cleanup = () => {\n if (signal) signal.removeEventListener(\"abort\", onAbort);\n for (const w of workers) void w.terminate();\n };\n\n // Cooperative cancellation: stop dispatching and tear down on abort.\n if (signal) {\n if (signal.aborted) {\n reject(new AbortError());\n return;\n }\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n // Workers we intentionally terminate (no more chunks / on cleanup). Their\n // `exit` event is expected and must NOT be treated as a crash.\n const retired = new WeakSet<NodeWorker>();\n\n const dispatch = (w: NodeWorker): void => {\n if (failed) return;\n if (next >= chunks.length) {\n retired.add(w);\n void w.terminate();\n return;\n }\n const idx = next++;\n w.postMessage({ index: idx, files: chunks[idx].files });\n };\n\n const spawn = (): NodeWorker => {\n const w = new WorkerCtor(entry, {\n workerData: { baseDir, toggles },\n ...(execArgv ? { execArgv } : {}),\n });\n w.on(\n \"message\",\n (msg: { index: number; result?: ChunkResult; files?: string[]; error?: string }) => {\n if (msg.error) {\n if (!failed) {\n failed = true;\n cleanup();\n reject(new Error(msg.error));\n }\n return;\n }\n if (msg.files && onFile) for (const f of msg.files) onFile(f);\n if (msg.result) {\n results[msg.index] = msg.result;\n done++;\n if (done === chunks.length) {\n cleanup();\n resolve(results);\n return;\n }\n dispatch(w);\n }\n },\n );\n w.on(\"error\", (err) => {\n if (!failed) {\n failed = true;\n cleanup();\n reject(err);\n }\n });\n // A worker that dies WITHOUT an `error` or `message` (e.g. a `process.exit`\n // in loaded code) would otherwise leave the pool pending forever. Reject so\n // scanParallel falls back to the serial path (audit: arch #5). Expected\n // exits (retired workers, post-completion cleanup) are ignored.\n w.on(\"exit\", (code) => {\n if (failed || retired.has(w) || done === chunks.length) return;\n failed = true;\n cleanup();\n reject(new Error(`scan worker exited early (code ${code}) before completing its chunk`));\n });\n return w;\n };\n\n const n = Math.max(1, Math.min(concurrency, chunks.length));\n for (let i = 0; i < n; i++) {\n const w = spawn();\n workers.push(w);\n dispatch(w);\n }\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"parallel.js","sourceRoot":"","sources":["../src/parallel.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Parallel scanning over a worker-thread pool (P2-1). The scan is embarrassingly\n * parallel: each file is read and regex-scanned independently, and the merge is\n * a concatenation + the existing deterministic sort. `Finding` is plain\n * structured-cloneable data, so it crosses the worker boundary cleanly.\n *\n * The merge and chunking logic are pure and exported for direct unit testing.\n * `scanParallel` falls back to the in-process serial path below the crossover\n * (small file counts / small total bytes) and whenever workers are unavailable.\n */\nimport { stat } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport type { Worker as NodeWorker } from \"node:worker_threads\";\n\nimport type { Finding, ParallelScanOptions, ScanResult } from \"./types.js\";\nimport { walkFilesSized } from \"./walk.js\";\nimport { isAnalyzableSource } from \"./detect-utils.js\";\nimport { buildInventory } from \"./inventory.js\";\nimport { compareFindings, filterExplicitFileList, scan } from \"./scan.js\";\nimport { AbortError, BudgetExceededError } from \"./errors.js\";\nimport { VERSION } from \"./version.js\";\n\n/** One unit of work dispatched to a worker. */\nexport interface ScanChunk {\n files: string[];\n}\n\n/** What a worker returns for a chunk. */\nexport interface ChunkResult {\n findings: Finding[];\n filesScanned: number;\n /** Files that couldn't be read in this chunk (optional; older workers omit it). */\n unreadable?: number;\n /** Files skipped as minified in this chunk (optional; older workers omit it). */\n skippedMinified?: number;\n}\n\nconst DEFAULT_PARALLEL_THRESHOLD_BYTES = 2 * 1024 * 1024;\nconst DEFAULT_PARALLEL_FILE_THRESHOLD = 200;\nconst DEFAULT_CHUNK_BYTES = 4 * 1024 * 1024;\n\n/** A file plus its byte size, used for byte-balanced chunking. */\nexport interface SizedFile {\n rel: string;\n size: number;\n}\n\n/**\n * Bucket files into chunks of roughly `chunkBytes` total bytes each, so one\n * large file doesn't starve a worker holding many tiny files. Pure +\n * deterministic: input order is preserved within and across chunks.\n */\nexport function chunkByBytes(files: readonly SizedFile[], chunkBytes: number): ScanChunk[] {\n const limit = Math.max(1, chunkBytes);\n const chunks: ScanChunk[] = [];\n let current: string[] = [];\n let currentBytes = 0;\n for (const f of files) {\n if (current.length > 0 && currentBytes + f.size > limit) {\n chunks.push({ files: current });\n current = [];\n currentBytes = 0;\n }\n current.push(f.rel);\n currentBytes += f.size;\n }\n if (current.length > 0) chunks.push({ files: current });\n return chunks;\n}\n\n/**\n * Merge per-chunk results into a single ordered finding set + total file count.\n * Pure: applies the SAME comparator as the serial scan, so the result is\n * byte-identical regardless of chunk completion order. Exported for unit tests.\n */\nexport function mergeChunkResults(results: readonly ChunkResult[]): ChunkResult {\n const findings: Finding[] = [];\n let filesScanned = 0;\n let unreadable = 0;\n let skippedMinified = 0;\n for (const r of results) {\n for (const f of r.findings) findings.push(f);\n filesScanned += r.filesScanned;\n unreadable += r.unreadable ?? 0;\n skippedMinified += r.skippedMinified ?? 0;\n }\n findings.sort(compareFindings);\n return { findings, filesScanned, unreadable, skippedMinified };\n}\n\n/** Resolve the worker count (>= 1). */\nfunction resolveConcurrency(options: ParallelScanOptions): number {\n const raw = options.concurrency;\n if (typeof raw === \"number\" && raw >= 1) return Math.floor(raw);\n const avail =\n typeof os.availableParallelism === \"function\" ? os.availableParallelism() : os.cpus().length;\n return Math.max(1, avail);\n}\n\n/** Decide whether the workload is large enough to justify spawning workers. */\nfunction shouldParallelize(options: ParallelScanOptions, files: SizedFile[]): boolean {\n const totalBytes = files.reduce((acc, f) => acc + f.size, 0);\n const byteFloor = options.parallelThresholdBytes ?? DEFAULT_PARALLEL_THRESHOLD_BYTES;\n const fileFloor = options.parallelFileThreshold ?? DEFAULT_PARALLEL_FILE_THRESHOLD;\n if (resolveConcurrency(options) <= 1) return false;\n return totalBytes >= byteFloor && files.length >= fileFloor;\n}\n\n/**\n * Enumerate the files to scan (relative POSIX paths + sizes), honouring an\n * explicit `files` list or the walker. Sizes power byte-balanced chunking.\n */\nasync function enumerateFiles(options: ParallelScanOptions, baseDir: string): Promise<SizedFile[]> {\n const sized: SizedFile[] = [];\n if (options.files) {\n // Explicit file list: the walker isn't involved, so stat each once here.\n // Apply the SAME include/exclude/binary filtering the serial path uses via\n // `filterExplicitFileList`, so `--parallel` is byte-for-byte identical to serial.\n for (const rel of filterExplicitFileList(options.files, options)) {\n let size = 0;\n try {\n size = (await stat(path.join(baseDir, ...rel.split(\"/\")))).size;\n } catch {\n // Unreadable now; keep with size 0 (the worker read will skip if it's gone).\n }\n sized.push({ rel, size });\n }\n return sized;\n }\n\n // Directory walk: reuse the size the walker already stat'd while enforcing the\n // size limit, so files are not stat'd a second time here (double-stat fix).\n for await (const { rel, size } of walkFilesSized(options.root, {\n include: options.include,\n exclude: options.exclude,\n noDefaultIgnores: options.noDefaultIgnores,\n maxFileSize: options.maxFileSize,\n })) {\n sized.push({ rel, size });\n }\n return sized;\n}\n\n/**\n * Resolve the worker entry next to this module. In a normal build it's\n * `dist/scan-worker.js`. When running from source under a TypeScript loader\n * (tsx) the built JS doesn't exist, so fall back to `scan-worker.ts` and tell\n * the worker to load tsx as well — so the parallel scanner works in dev/source\n * mode (and is exercisable by tests), not only after a build.\n */\nfunction workerEntry(): { entry: string; execArgv?: string[] } {\n const here = fileURLToPath(import.meta.url);\n const dir = path.dirname(here);\n const js = path.join(dir, \"scan-worker.js\");\n if (existsSync(js)) return { entry: js };\n const ts = path.join(dir, \"scan-worker.ts\");\n if (existsSync(ts)) return { entry: ts, execArgv: [\"--import\", \"tsx\"] };\n return { entry: js }; // neither present: let Worker surface a clear ENOENT\n}\n\n/**\n * Scan in parallel across a worker-thread pool, falling back to the in-process\n * serial {@link scan} for small workloads or when workers can't be used. The\n * result is deterministic and identical to the serial path.\n */\nexport async function scanParallel(options: ParallelScanOptions): Promise<ScanResult> {\n const startedAt = new Date();\n\n const rootStat = await stat(options.root);\n const baseDir = rootStat.isFile() ? path.dirname(options.root) : options.root;\n\n // Single-file roots, the override-detectors path, and the scan cache always\n // run serially: detectors may not be structured-cloneable across the worker\n // boundary, and the cache read/write is owned by the in-process `scan()`.\n if (rootStat.isFile() || options.detectors || options.cacheFile) {\n return scan(options);\n }\n\n const files = await enumerateFiles(options, baseDir);\n\n // Budget + cancellation parity with the serial path. The parallel path\n // enumerates upfront, so budgets are enforced against the whole file set\n // before any worker is dispatched.\n if (options.signal?.aborted) throw new AbortError();\n if (typeof options.maxFiles === \"number\" && files.length > options.maxFiles) {\n throw new BudgetExceededError(`maxFiles budget exceeded (limit: ${options.maxFiles}).`);\n }\n if (typeof options.maxBytes === \"number\") {\n const totalBytes = files.reduce((n, f) => n + f.size, 0);\n if (totalBytes > options.maxBytes) {\n throw new BudgetExceededError(`maxBytes budget exceeded (limit: ${options.maxBytes}).`);\n }\n }\n\n if (!shouldParallelize(options, files)) {\n // In-process: reuse the exact serial path over the same file list.\n return scan({ ...options, files: files.map((f) => f.rel) });\n }\n\n let WorkerCtor: typeof import(\"node:worker_threads\").Worker;\n try {\n ({ Worker: WorkerCtor } = await import(\"node:worker_threads\"));\n } catch {\n return scan({ ...options, files: files.map((f) => f.rel) });\n }\n\n const chunks = chunkByBytes(files, options.chunkBytes ?? DEFAULT_CHUNK_BYTES);\n const concurrency = Math.min(resolveConcurrency(options), chunks.length);\n const { entry, execArgv } = workerEntry();\n\n const toggles = {\n source: options.source !== false,\n config: options.config !== false,\n deps: options.dependencies !== false,\n scanMinified: options.scanMinified === true,\n // Plain string array — structured-cloneable, so it crosses the worker boundary.\n disabledRules: options.disabledRules,\n };\n\n let results: ChunkResult[];\n try {\n results = await runPool(\n WorkerCtor,\n entry,\n execArgv,\n baseDir,\n toggles,\n chunks,\n concurrency,\n options.onFile,\n options.signal,\n );\n } catch (err) {\n // Cancellation / budget overflow must propagate, not silently degrade.\n if (err instanceof AbortError || err instanceof BudgetExceededError) throw err;\n // Any other worker failure → safe fallback to the serial path.\n return scan({ ...options, files: files.map((f) => f.rel) });\n }\n\n const merged = mergeChunkResults(results);\n const inventory = buildInventory(merged.findings);\n const finishedAt = new Date();\n\n // Coverage: count analyzable-source files in the enumerated set. Computed from\n // the file list (not per-worker) to avoid worker-boundary plumbing; on the\n // parallel path this can include a minified analyzable file the workers\n // skipped, but that is vanishingly rare and never under-reports coverage.\n const analyzedFiles = files.reduce((n, f) => (isAnalyzableSource(f.rel) ? n + 1 : n), 0);\n\n return {\n root: options.root,\n findings: merged.findings,\n filesScanned: merged.filesScanned,\n analyzedFiles,\n diagnostics: {\n unreadable: merged.unreadable ?? 0,\n skippedMinified: merged.skippedMinified ?? 0,\n },\n inventory,\n startedAt: startedAt.toISOString(),\n finishedAt: finishedAt.toISOString(),\n toolVersion: VERSION,\n };\n}\n\n/** Worker-pool driver: at most `concurrency` workers, each pulls chunks. */\nfunction runPool(\n WorkerCtor: typeof import(\"node:worker_threads\").Worker,\n entry: string,\n execArgv: string[] | undefined,\n baseDir: string,\n toggles: {\n source: boolean;\n config: boolean;\n deps: boolean;\n scanMinified: boolean;\n disabledRules?: string[];\n },\n chunks: ScanChunk[],\n concurrency: number,\n onFile?: (file: string) => void,\n signal?: AbortSignal,\n): Promise<ChunkResult[]> {\n return new Promise((resolve, reject) => {\n const results: ChunkResult[] = new Array(chunks.length);\n let next = 0;\n let done = 0;\n let failed = false;\n const workers: Array<NodeWorker> = [];\n\n const onAbort = (): void => {\n if (failed) return;\n failed = true;\n cleanup();\n reject(new AbortError());\n };\n\n const cleanup = () => {\n if (signal) signal.removeEventListener(\"abort\", onAbort);\n for (const w of workers) void w.terminate();\n };\n\n // Cooperative cancellation: stop dispatching and tear down on abort.\n if (signal) {\n if (signal.aborted) {\n reject(new AbortError());\n return;\n }\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n // Workers we intentionally terminate (no more chunks / on cleanup). Their\n // `exit` event is expected and must NOT be treated as a crash.\n const retired = new WeakSet<NodeWorker>();\n\n const dispatch = (w: NodeWorker): void => {\n if (failed) return;\n if (next >= chunks.length) {\n retired.add(w);\n void w.terminate();\n return;\n }\n const idx = next++;\n w.postMessage({ index: idx, files: chunks[idx].files });\n };\n\n const spawn = (): NodeWorker => {\n const w = new WorkerCtor(entry, {\n workerData: { baseDir, toggles },\n ...(execArgv ? { execArgv } : {}),\n });\n w.on(\n \"message\",\n (msg: { index: number; result?: ChunkResult; files?: string[]; error?: string }) => {\n if (msg.error) {\n if (!failed) {\n failed = true;\n cleanup();\n reject(new Error(msg.error));\n }\n return;\n }\n if (msg.files && onFile) for (const f of msg.files) onFile(f);\n if (msg.result) {\n results[msg.index] = msg.result;\n done++;\n if (done === chunks.length) {\n cleanup();\n resolve(results);\n return;\n }\n dispatch(w);\n }\n },\n );\n w.on(\"error\", (err) => {\n if (!failed) {\n failed = true;\n cleanup();\n reject(err);\n }\n });\n // A worker that dies WITHOUT an `error` or `message` (e.g. a `process.exit`\n // in loaded code) would otherwise leave the pool pending forever. Reject so\n // scanParallel falls back to the serial path (audit: arch #5). Expected\n // exits (retired workers, post-completion cleanup) are ignored.\n w.on(\"exit\", (code) => {\n if (failed || retired.has(w) || done === chunks.length) return;\n failed = true;\n cleanup();\n reject(new Error(`scan worker exited early (code ${code}) before completing its chunk`));\n });\n return w;\n };\n\n const n = Math.max(1, Math.min(concurrency, chunks.length));\n for (let i = 0; i < n; i++) {\n const w = spawn();\n workers.push(w);\n dispatch(w);\n }\n });\n}\n"]}
|
package/dist/report.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import type { RuleMeta, ScanResult } from "./types.js";
|
|
7
7
|
import type { SecurityTier } from "./remediation.js";
|
|
8
8
|
import type { StandardsProfile } from "./standards-profiles.js";
|
|
9
|
+
import type { HndlReport } from "./hndl.js";
|
|
9
10
|
/** Minimal SARIF 2.1.0 log shape (kept permissive on purpose). */
|
|
10
11
|
export interface SarifLog {
|
|
11
12
|
$schema: string;
|
|
@@ -29,6 +30,13 @@ export interface ReportOptions {
|
|
|
29
30
|
* {@link toJson}.
|
|
30
31
|
*/
|
|
31
32
|
catalog?: RuleMeta[];
|
|
33
|
+
/**
|
|
34
|
+
* Optional HNDL exposure analysis ({@link computeHndl}). When supplied, each
|
|
35
|
+
* finding gains its `exposure` fields (score, bound data asset, rationale)
|
|
36
|
+
* keyed by fingerprint, and the report carries the repo-level HNDL summary.
|
|
37
|
+
* Purely additive: it never changes finding identity, ordering, or exit codes.
|
|
38
|
+
*/
|
|
39
|
+
hndl?: HndlReport;
|
|
32
40
|
}
|
|
33
41
|
/** Serialize a scan result as SARIF 2.1.0. */
|
|
34
42
|
export declare function toSarif(result: ScanResult, opts?: ReportOptions): SarifLog;
|
package/dist/report.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAA4B,QAAQ,EAAE,UAAU,EAAY,MAAM,YAAY,CAAC;AAK3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,kEAAkE;AAClE,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,EAAE,CAAC;CACjB;AAED,qFAAqF;AACrF,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAA4B,QAAQ,EAAE,UAAU,EAAY,MAAM,YAAY,CAAC;AAK3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,OAAO,KAAK,EAAmB,UAAU,EAAE,MAAM,WAAW,CAAC;AAE7D,kEAAkE;AAClE,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,EAAE,CAAC;CACjB;AAED,qFAAqF;AACrF,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC;IACrB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AA+FD,8CAA8C;AAC9C,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,QAAQ,CAyI1E;AAkBD,+DAA+D;AAC/D,wBAAgB,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA6DxF;AAwCD;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,UAAU,EAClB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,YAAY,CAAA;CAAE,GACjD,MAAM,CAyGR;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,IAAI,EAAE,YAAY,GACjB,MAAM,EAAE,CAmBV;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,OAAO,EAAE,gBAAgB,GACxB,MAAM,EAAE,CAsBV"}
|