- 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>
8.3 KiB
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.Maintostatic async Task<int> Main(string[] args), propagateawaitthroughout
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 inProgram.csalone) - 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.csis ~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
IFocasTransferHandlerfor 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:
RSACryptoServiceProviderandSHA256CryptoServiceProviderare 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/cpuinfoordmidecode
FOCAS DLL version sensitivity:
- Risk: FOCAS API changes between Fanuc control versions;
FanucDialectDetectorauto-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:
UploadProgramByIdentifierappends toStringBuilderfor 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
FileStreaminstead 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.csorchestration or exit code behavior) - No tests for
MachineFingerprint(WMI, no mock tests) - No tests for
LicenseFileparsing 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