nc_program_manager/.paul/codebase/CONCERNS.md
dtrentin dabcf989d9 docs: map existing codebase
- STACK.md - Technologies and dependencies (.NET 4.7.2, NuGet, Costura.Fody)
- ARCHITECTURE.md - Layered CLI with ICncMachine factory pattern
- STRUCTURE.md - Directory layout and where to add new code
- CONVENTIONS.md - C# style, naming, result wrapper pattern
- TESTING.md - NUnit 3 + Moq, stubs, ignored FOCAS tests
- INTEGRATIONS.md - FOCAS, LSV2, FTP, RSA licensing
- CONCERNS.md - Blocking async, silent catch, no logging, Windows-only

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 22:48:20 +02:00

152 lines
8.3 KiB
Markdown

# Codebase Concerns
**Analysis Date:** 2026-05-18
## Tech Debt
**Blocking async calls at CLI boundary:**
- Issue: 56+ `.GetAwaiter().GetResult()` calls block async operations synchronously
- Files: `Program.cs` (lines 90, 101, 122, 142, 166, 200, 221, 240, 262), machine classes
- Why: Main() was not async when initially written; .NET 4.7.2 supports async Main via C# 7.1
- Impact: Thread pool starvation risk, deadlock risk in certain SynchronizationContext scenarios, harder debugging
- Fix: Refactor `Program.Main` to `static async Task<int> Main(string[] args)`, propagate `await` throughout
**Silent exception handlers (catch without logging):**
- Issue: `try { ... } catch { }` swallows exceptions with no trace
- Files: `Cnc/Fanuc/FanucMachine.cs` (disconnect cleanup), `Cnc/Siemens/SiemensMachine.cs`, `Cnc/Heidenhain/HeidenhainMachine.cs`, `Cnc/Heidenhain/Lsv2Client.cs`
- Why: Cleanup paths (disconnect, logout) should not propagate to caller; silence was intentional
- Impact: Resource leaks masked, production issues undiagnosable, disconnect failures invisible
- Fix: Log at minimum to debug/trace: `catch (Exception ex) { /* log ex */ }`. Add logging framework.
**No structured logging framework:**
- Issue: Entire codebase uses `Console.WriteLine` (98+ calls in `Program.cs` alone)
- Files: `Program.cs`, all machine implementations
- Why: MVP simplicity; tool was always a CLI
- Impact: No log levels, no timestamps, no file logging, production issues undiagnosable
- Fix: Add Serilog or NLog. Replace Console.WriteLine with `_logger.Information()`. Add request/response tracing to FOCAS calls.
**Large monolithic FanucMachine:**
- Issue: `Cnc/Fanuc/FanucMachine.cs` is ~740 lines with complex state management
- Files: `Cnc/Fanuc/FanucMachine.cs`
- Why: FOCAS protocol has many edge cases; chunked transfer and offset handling grew organically
- Impact: Hard to test individual branches; buffer handling edge cases unclear
- Fix: Extract `IFocasTransferHandler` for chunk upload/download logic; separate offset data reader
**`string.Format()` over `$""` interpolation:**
- Issue: Old string formatting style throughout validator and some machine code
- Files: `Cnc/NcProgramValidator.cs`, `Program.cs`
- Why: Legacy code predates C# 6 adoption on this project
- Impact: Cosmetic; harder to read format strings
- Fix: Opportunistic migration to `$""` during edits
## Known Issues / Incomplete Implementations
**Heidenhain ReadActiveProgramAsync / SelectMainProgram not implemented:**
- Symptoms: Returns `CncResult.Fail("Not supported via basic LSV2")`
- Files: `Cnc/Heidenhain/HeidenhainMachine.cs`
- Root cause: LSV2 protocol complexity; feature not required for initial release
- Workaround: Users specify program path explicitly
**Siemens ReadActiveProgramAsync / SelectMainProgram not implemented:**
- Symptoms: Returns stub failure
- Files: `Cnc/Siemens/SiemensMachine.cs`
- Root cause: FTP protocol doesn't expose active program info
- Workaround: Users specify program path explicitly
**MachineSnapshot returns stub data for Heidenhain/Siemens/Mitsubishi:**
- Files: `Cnc/Heidenhain/HeidenhainMachine.cs`, `Cnc/Siemens/SiemensMachine.cs`, `Cnc/Mitsubishi/MitsubishiMachine.cs`
- Issue: All snapshot fields return Unknown/empty; no real machine state read
- Impact: No diagnostic info available for non-Fanuc machines
## Security Considerations
**RSA public key hardcoded in binary:**
- Risk: Key embedded as const string in binary; cannot be rotated without recompile and redeploy
- Files: `Licensing/LicenseValidator.cs`
- Current mitigation: Asymmetric RSA — private key is vendor-only; hardcoded public key is acceptable for this use case
- Recommendation: Document key rotation procedure; consider adding license version/expiration metadata for future revocation
**MachineFingerprint null dereference on unusual hardware:**
- Risk: `mo.Properties["processorID"].Value.ToString()` throws NullReferenceException if WMI property missing
- Files: `Licensing/MachineFingerprint.cs`
- Current mitigation: None
- Fix: `mo.Properties["processorID"]?.Value?.ToString() ?? "unknown"`
**Obsolete crypto APIs:**
- Risk: `RSACryptoServiceProvider` and `SHA256CryptoServiceProvider` are obsolete in .NET 6+
- Files: `Licensing/LicenseValidator.cs`
- Current mitigation: .NET 4.7.2 target — obsolete warning only, not broken
- Fix when upgrading: Use `RSA.Create()` + `VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)`
**SHA256 provider not explicitly disposed:**
- Risk: Minor resource leak in license validation path
- Files: `Licensing/LicenseValidator.cs`
- Fix: Wrap in `using (var sha = new SHA256CryptoServiceProvider()) { ... }`
## Platform Constraints
**Windows-only (hard constraint):**
- FOCAS1 DLL (`Fwlib32.dll`) is 32-bit Windows native — no Linux/macOS support
- WMI (`System.Management`) Windows-only — licensing system non-functional on Linux
- Files: `Cnc/Fanuc/libs/`, `Licensing/MachineFingerprint.cs`, `fwlib32.cs`
- Impact: Cannot run on Linux/macOS; CI on Linux can only test non-FOCAS paths
- Action if cross-platform needed: Abstract fingerprinting behind `IMachineFingerprint`; already done — add Linux implementation using `/proc/cpuinfo` or `dmidecode`
**FOCAS DLL version sensitivity:**
- Risk: FOCAS API changes between Fanuc control versions; `FanucDialectDetector` auto-detects but may fail on unknown versions
- Files: `Cnc/Fanuc/FanucDialectDetector.cs`, `Cnc/Fanuc/FanucMachine.cs`
- Mitigation: Dialect abstraction layer (`IFocasDialect`) isolates version differences
## Performance Bottlenecks
**In-memory accumulation for large NC programs:**
- Issue: `UploadProgramByIdentifier` appends to `StringBuilder` for entire program before writing
- Files: `Cnc/Fanuc/FanucMachine.cs`
- Impact: For programs >10MB, high memory allocation; streaming to file would be more efficient
- Fix: Write chunks directly to `FileStream` instead of accumulating in memory
**Polling with 100ms busy-wait during transfer:**
- Issue: `ct.WaitHandle.WaitOne(100)` loops during buffer waits
- Files: `Cnc/Fanuc/FanucMachine.cs`
- Impact: Wastes thread-pool slot; CPU cycles during transfer
- Fix: Use `await Task.Delay(100, ct)` instead of blocking WaitOne
**Network connection timeout via `.Wait()` with boolean return:**
- Issue: `_tcp.ConnectAsync().Wait(timeout)` — if task never completes, does not abort it
- Files: `Cnc/Heidenhain/Lsv2Client.cs`
- Fix: `await Task.WhenAny(connectTask, Task.Delay(timeout, ct))` + cancellation
## Fragile Areas
**FOCAS dialect detection (`FanucDialectDetector`):**
- Files: `Cnc/Fanuc/FanucDialectDetector.cs`
- Why fragile: Relies on probing specific FOCAS API calls to detect version; untested against full range of Fanuc control generations
- Safe modification: Always test against physical hardware after changes; log detected dialect version
**License validation (no recovery path):**
- Files: `Licensing/LicenseValidator.cs`, `Licensing/MachineFingerprint.cs`
- Why fragile: Any WMI failure or file read error produces a hard exit with no diagnostic for user
- Safe modification: Add exception handling with user-facing error message; distinguish "no license file" from "invalid license" from "fingerprint failure"
**Integration tests with hardcoded IPs:**
- Files: `NcProgramManager.Tests/Integration/SiemensMachineIntegrationTests.cs`, `HeidenhainMachineIntegrationTests.cs`, `MitsubishiMachineIntegrationTests.cs`
- Why fragile: Tests will fail in CI without physical hardware at specific IPs
- Fix: Make IPs configurable via environment variables; skip integration tests in CI by default
## Missing / Not Covered
- No CLI-level tests (no test for `Program.cs` orchestration or exit code behavior)
- No tests for `MachineFingerprint` (WMI, no mock tests)
- No tests for `LicenseFile` parsing edge cases (corrupt Base64, empty file)
- No structured logging or diagnostics framework
- No error code documentation in code (only in `README.md`)
- No architecture documentation (FOCAS dialect selection logic undocumented in code)
---
**Overall Assessment:** Architecture is solid — clean machine abstraction, well-structured interfaces, good error propagation via `CncResult<T>`. Main concerns are operational (logging, blocking async, empty catch blocks) rather than structural. Platform constraints (Windows, FOCAS DLL) are intentional for the target environment.
---
*Concerns analysis: 2026-05-18*
*Update as issues are resolved or discovered*