---
phase: 13-robustness-fixes
plan: 01
type: summary
status: complete
completed: 2026-05-18
commit: 4cd7715
---

# Summary: Plan 13-01 — Robustness Fixes

## What Was Built

Three targeted defensive fixes. No new files. No interface changes.

### Task 1 — MachineFingerprint null guard (ISS-001)

**File:** `Licensing/MachineFingerprint.cs`

Both WMI property reads now use null-safe operators:
- `mo.Properties["processorID"]?.Value?.ToString() ?? string.Empty`
- `obj["SerialNumber"]?.ToString() ?? string.Empty`

Customers on hardware where WMI returns null for processorID or SerialNumber no longer get an unhandled NullReferenceException at license check startup.

### Task 2 — SHA256 provider disposed (ISS-005)

**File:** `Licensing/LicenseValidator.cs`

`SHA256CryptoServiceProvider` wrapped in `using` block inside `Validate()`. Disposed on every call — success or failure. RSACryptoServiceProvider pattern unchanged. Public key constant untouched.

### Task 3 — LSV2 connect timeout aborts socket (ISS-006)

**File:** `Cnc/Heidenhain/Lsv2Client.cs`

`Connect()` now calls `_tcp.Close()` when `ConnectAsync().Wait(timeout)` returns false. Closes the underlying socket, causing the pending task to complete with SocketException rather than holding a thread-pool slot indefinitely. No async/await introduced (Connect() stays synchronous by design).

## Acceptance Criteria Results

| AC | Description | Result |
|----|-------------|--------|
| AC-1 | WMI null returns non-null string, no throw | PASS |
| AC-2 | SHA256 provider disposed after every Validate() | PASS |
| AC-3 | Timeout branch closes socket before returning false | PASS |

## Decisions Made

- `?? string.Empty` used (not `?? "unknown"`) — fingerprint string concatenated; empty is correct fallback
- `_tcp.Close()` in bare `try { } catch { }` — same pattern as existing Disconnect() in same file
- No CancellationTokenSource pattern (ISS-006 fix note suggested it) — simpler Close() approach sufficient for .NET 4.7.2 synchronous design

## Deferred

None — all three tasks completed as planned.

## Files Modified

- `Licensing/MachineFingerprint.cs` — null guards on WMI reads
- `Licensing/LicenseValidator.cs` — SHA256 using block
- `Cnc/Heidenhain/Lsv2Client.cs` — socket close on timeout

## Issues Closed

- ISS-001 — MachineFingerprint null dereference on unusual hardware ✓
- ISS-005 — SHA256 crypto provider not disposed ✓
- ISS-006 — LSV2 connect timeout doesn't abort hung task ✓

## Commit

`4cd7715` — fix(robustness): null guard WMI reads, dispose SHA256, abort LSV2 timeout (ISS-001, ISS-005, ISS-006)
