Skip to content

fix: make pure calculate() tolerate omitted optional inputs#14

Open
dmchaledev wants to merge 1 commit into
mainfrom
claude/sleepy-rubin-9O4PW
Open

fix: make pure calculate() tolerate omitted optional inputs#14
dmchaledev wants to merge 1 commit into
mainfrom
claude/sleepy-rubin-9O4PW

Conversation

@dmchaledev
Copy link
Copy Markdown
Contributor

Problem

index.d.ts declares scan_window and compliance_needs as optional:

export interface VulnInputs {
  target_hosts: number;
  scan_intensity: ...;
  scan_frequency: ...;
  scan_window?: number;          // optional
  compliance_needs?: string[];   // optional
  scanning_tools: string[];
  ...
}

But the pure calculate() API — the headline DOM-free function — crashed or silently produced NaN when those documented-optional fields were omitted. So a TypeScript consumer gets green typechecking, then a runtime failure.

Reproduced against main:

Call Result on main
omit compliance_needs ❌ throws Cannot read properties of undefined (reading 'length') (in calcAsmResources)
omit scan_window ⚠️ scan_window_utilization = NaN, efficiency rating wrongly reported as "poor" (the rating chain falls through because NaN <= 60 is false)
omit scanning_tools ❌ throws Cannot read properties of undefined (reading 'includes')

The DOM web component never hit this because _collectInputs()/_run() clamp and default everything first — but the exported calculate() had no such guard. (This is the same class of issue that bit the test suite in #8, which had to manually add scan_window.)

Fix

Add a small normalizeInputs() step at the calculation entry point (calculateResources) that defaults the optional fields before they're used:

  • scan_window8 when missing or non-positive (also avoids a divide-by-zero → Infinity)
  • compliance_needs[] when missing
  • scanning_tools[] when missing/invalid — note an empty array stays a valid zero-cost state, matching the existing empty scanning_tools array does not crash test (the DOM component injects its own UI-only fallback, the pure function should not)
  • scan_intensity / scan_frequency → existing defaults made explicit
  • non-finite target_hosts1 (defensive; prevents NaN propagating through every metric)

No calculation logic changed for already-valid inputs — this only fills in omitted optional values.

Tests

npm test  (CI default): 7 tests, 7 pass
full suite:             71 tests, 71 pass

Note (out of scope)

This PR makes the regression visible in CI via the smoke test, but the broader gap — npm test not running calculate.test.mjs at all — is already tracked by open PRs #11 and #13. Worth merging one of those so the full 71-test suite gates every push.

https://claude.ai/code/session_01Aed4GvoDBzgz6fuPXSHHif


Generated by Claude Code

The public calculate() API crashed or produced NaN when called with the
fields that index.d.ts documents as optional:

- omitting `compliance_needs` threw "Cannot read properties of undefined
  (reading 'length')" in calcAsmResources
- omitting `scan_window` produced NaN scan_window_utilization and a
  misleading "poor" efficiency rating (NaN <= 60 is false, so the rating
  chain fell through to the worst bucket)
- omitting `scanning_tools` threw on `.includes`

The DOM component guards these in _collectInputs()/_run(), but the pure
calculate() — the headline programmatic API — did not, so TypeScript
consumers got green typechecking followed by a runtime crash.

Add normalizeInputs() at the calculation entry point to default the
optional fields (scan_window -> 8, compliance_needs -> [], a
missing/invalid scanning_tools -> [], a non-positive scan_window -> 8,
non-finite target_hosts -> 1). An empty scanning_tools array stays a
valid zero-cost state, matching the existing edge-case test.

Add regression coverage: 5 tests in calculate.test.mjs plus one
smoke-level test so the case is guarded by the CI `npm test` script
today (which currently runs only the smoke suite).

https://claude.ai/code/session_01Aed4GvoDBzgz6fuPXSHHif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants