nc_program_manager/.paul/STATE.md
Davide Trentin e608977359 docs: add code review bug analysis report
Static analysis findings for nc_program_manager: 8 security criticals
(FTP plaintext, LSV2 cleartext, path traversal, license bypass),
4 functional bugs, 3 NRE risks, 3 resource leaks. See BUG_ANALYSIS.md
for prioritized fix list.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 21:53:03 +02:00

242 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Project State
## Project Reference
See: .paul/PROJECT.md (updated 2026-05-18)
**Core value:** Machinists transfer CNC programs to/from any controller without manual steps or internet
**Current focus:** v0.7 Build Hardening — formalize obfuscation pipeline + close v0.6 review findings
## Current Position
Milestone: v0.7 Build Hardening — **In Progress**
Phase: 17 of 18 (build-pipeline) — Not started
Plan: Not started
Status: Ready to plan Phase 17
Last activity: 2026-05-25 — Milestone v0.7 created (phases 17 build-pipeline, 18 review-fixes)
Progress:
- Milestone v0.1: [██████████] 100% (complete)
- Milestone v0.2: [██████████] 100% (complete)
- Milestone v0.3: [██████████] 100% (complete)
- Milestone v0.4: [██████████] 100% (complete)
- Milestone v0.5: [██████████] 100% (complete)
- Milestone v0.6: [██████████] 100% (complete)
- Milestone v0.7: [░░░░░░░░░░] 0%
- Phase 17: [░░░░░░░░░░] 0%
- Phase 18: [░░░░░░░░░░] 0%
## Loop Position
```
PLAN ──▶ APPLY ──▶ UNIFY
○ ○ ○ [Ready for Phase 17 PLAN]
```
## What Was Built (v0.6 Fagor Support — complete)
### Phase 16 — Fagor FTP
- `Cnc/Models/CncManufacturer.cs` — aggiunto `Fagor` all'enum
- `Cnc/Fagor/FagorConnectionConfig.cs` — nuovo, ProgramDirectory `/Users/Prg/`, ProgramExtension `.nc` default
- `Cnc/Fagor/IFagorFtpClient.cs` — nuovo, interfaccia mirror Siemens
- `Cnc/Fagor/FagorFtpClient.cs` — nuovo, FtpWebRequest + ASCII, mirror Siemens 1:1
- `Cnc/Fagor/FagorMachine.cs` — nuovo, implementa `ICncMachine` con `ResolvePath` adattato per `ProgramExtension` configurabile
- `Cnc/CncMachineFactory.cs` — case `Fagor` con porta default 21
- `Cnc/NcProgramValidator.cs` — refactor: helper `IsRestrictiveDialect()` (Fanuc+Mitsubishi); check generic (block 80, no tab, no lowercase, nested parens, comment 32) gated per-produttore. Case `Fagor` aggiunto in `ValidateName` (max 24 char, no `ñ`, solo lettere/cifre/spazi) e `ValidateForbiddenChars` (nessuna restrizione contenuto)
- `ArgParser.cs` — case `"fagor"` aggiunto
- `Program.cs` — help text aggiornato (manufacturer/username/password)
- `NcProgramManager.csproj` — 4 `<Compile Include>` per Cnc\Fagor\*.cs
- `NcProgramManager.Tests/Unit/FagorMachineTests.cs` — nuovo, 12 unit test con `Mock<IFagorFtpClient>` + 2 test con validator reale (`ñ`, lunghezza)
- `NcProgramManager.Tests/Integration/FagorMachineIntegrationTests.cs` — nuovo, 5 stub-based + 1 hardware skip (`FAGOR_TEST_IP`)
- `NcProgramManager.Tests/Unit/NcProgramValidatorTests.cs` — 8 nuovi test Fagor; 3 test esistenti spostati da Siemens a Fanuc dopo refactor gating
- `NcProgramManager.Tests/NcProgramManager.Tests.csproj` — 2 `<Compile Include>` aggiunti
- `README.md` — sezione "Controller Fagor" in italiano: modelli supportati (8060/8065/8070), non supportati (8055 base, 8025-8050), regole nome programma, env var test
Modelli supportati: Fagor 8060, 8065, 8070 (FTP nativo); Fagor 8055 (richiede opzione Ethernet).
Modelli non supportati: 8025/8030/8040/8050 (solo RS232, modulo seriale non implementato).
### Phase 16-02 — Fagor Fixup (post-review)
Fix derivati da code review v0.6:
- `Cnc/NcProgramValidator.cs` — Fagor `ValidateName`: split stem/extension via `LastIndexOf('.')`; whitelist letter/digit/space applicata solo allo stem (consente `.nc` o altre estensioni). Letterali `ñ` sostituiti con escape Unicode `ñ` (codepage safety)
- `NcProgramManager.Tests/Unit/NcProgramValidatorTests.cs`:
- 3 nuovi test lock Siemens (lowercase/tab/long-block ora esenti)
- 3 nuovi test lock Heidenhain (lowercase/tab/long-block ora esenti)
- 4 nuovi test Fagor (`.nc` extension success, `.pim` extension success, stem con simbolo fail, `ñ` escape)
- 1 test esistente Fagor `ñ` migrato a escape `ñ`
- `NcProgramManager.Tests/Unit/CncMachineFactoryTests.cs` — aggiunto `Create_Fagor_ReturnsFagorMachine`
- `.paul/ISSUES.md` — aggiunte ISS-012..ISS-017 da review findings (non risolti in v0.6, deferiti)
Issue follow-up aperti: ISS-012, ISS-013, ISS-014, ISS-015, ISS-016, ISS-017
## What Was Built (v0.5 Operational Quality — complete)
### Phase 15 — Logging
- `nlog.config` — rolling file target (daily, 7-day archive) + console (`levels="Info"`, `${message}` layout); `throwConfigExceptions=true`
- `packages.config` / `NcProgramManager.csproj` — NLog 5.2.8 reference + Content/CopyAlways entry
- `FanucMachine.cs`, `HeidenhainMachine.cs`, `SiemensMachine.cs`, `MitsubishiMachine.cs` — logger field + SetState catch → `_log.Warn`; Dispose catches annotated
- `Lsv2Client.cs` — logger field + Info at connect/disconnect + cleanup catch annotations
- `Program.cs` — logger field + 3× `_log.Error` in catch blocks + 103× `_log.Info` (all Console.Write/WriteLine replaced); zero Console.Write/WriteLine remain
- ISS-003 closed; ISS-004 closed
## What Was Built (v0.4 Robustness — complete)
### Phase 14 — Test Hardening
- `NcProgramManager.Tests/Integration/HardwareTestHelper.cs``GetIpOrSkip(string)` calls `Assert.Ignore` when env var missing; ISS-007 closed
- `HeidenhainMachineIntegrationTests.cs`, `SiemensMachineIntegrationTests.cs`, `MitsubishiMachineIntegrationTests.cs``Hardware_ConnectAsync_RealMachine` + `[Category("Hardware")]` added to each
- `NcProgramManager.Tests/Unit/LicenseFileTests.cs` — 4 tests covering empty, whitespace, valid base64, nonexistent path
- `LicenseValidatorTests.cs``Validate_EmptyFingerprint_ReturnsFalse` added; ISS-008 scaffold complete
### Phase 13 — Robustness Fixes
- `Licensing/MachineFingerprint.cs` — null guards on both WMI reads (`?.Value?.ToString() ?? string.Empty`); ISS-001 closed
- `Licensing/LicenseValidator.cs``SHA256CryptoServiceProvider` in `using` block inside `Validate()`; ISS-005 closed
- `Cnc/Heidenhain/Lsv2Client.cs``Connect()` calls `_tcp.Close()` on timeout branch to abort pending socket; ISS-006 closed
## What Was Built (v0.3 Code Quality — complete)
### Phase 11 — Refactor
- `ArgParser.cs` — static class, `Parse(string[]) → InputArgs`; all CLI regex parsing extracted from Program.cs
- `Program.cs` — no static state; `Scarica`/`Invia` take explicit `InputArgs`; `VediErrore` takes `bool debugMode`
- `Program.cs` — try/finally with `connected` flag in `Scarica` and `Invia`; connection leak fixed
- `Program.cs``PrintErrors(IReadOnlyList<CncError>)` helper; `CncResult.Errors` printed on every failure
- `AesCrypt.cs` — deleted (dead code, no references)
### Phase 12 — Docs CLI
- `README.md` — params table expanded from 6 → 16 entries (all CLI args documented)
- `README.md` — codici errore section: 12 error codes with causa probabile + soluzione
## What Was Built (v0.1 Multi-CN Release)
### Phase 1 — CNC Abstraction
- Namespace: `Fanuc_integration.Cnc.*``FanucProgramManager.Cnc.*` (29 files)
- `IFocasDialect` extended: `UploadStart`/`DownloadStart` accept `short fileType`
- `IFanucMachine` created: extends `ICncMachine` with tool offset + work zero R/W
- `CncManufacturer` enum: Fanuc, Heidenhain, Siemens, Mitsubishi
- All 29 `Cnc/**/*.cs` files added to csproj
### Phase 2 — Heidenhain LSV2
- `HeidenhainConnectionConfig` — IP, port 19000, credentials, timeout
- `Lsv2Client` — TCP framing, CRC-16/CCITT, login (SELECT+LOG_IN), ReceiveFile/SendFile
- `HeidenhainMachine : ICncMachine` — RunGuardedAsync pattern, state machine
### Phase 3 — Siemens + Mitsubishi FTP
- `SiemensConnectionConfig` / `SiemensFtpClient` / `SiemensMachine : ICncMachine`
- `MitsubishiConnectionConfig` / `MitsubishiFtpClient` / `MitsubishiMachine : ICncMachine`
### Phase 4 — Wiring
- `CncMachineFactory` — creates right `ICncMachine` from `InputArgs`
- `InputArgs` — added `manufacturer`, `username`, `password` fields
- `Program.cs` — full rewrite using `ICncMachine`; Fanuc 3-file via `IFanucMachine` cast
### Phase 5 — NC Validator
- `ValidationSeverity` / `ValidationError` / `ValidationResult` model types
- `INcProgramValidator` + `NcProgramValidator` (5 universal + per-manufacturer rules)
- Validator injected into all 4 machine classes; upload blocked on Error severity
- `NcProgramValidatorTests` — 30+ NUnit tests
### Test Infrastructure
- `NcProgramManager.Tests/` — NUnit 3.13.3 + Moq 4.18.4, .NET 4.7.2
- `FtpServerStub` + `Lsv2ServerStub` — in-process TCP stubs
- Unit + integration tests; Fanuc FOCAS tests `[Ignore]`d (Windows-only DLL)
## What Was Built (v0.2 NcProgramManager — complete)
### Phase 06 — Rename Cleanup
- Namespace: `FanucProgramManager.*``NcProgramManager.*` (all files)
- Project renamed, test folder renamed, dead `FANUCMachine.cs` deleted
### Phase 07 — License Core
- `IMachineFingerprint` / `ILicenseValidator` interfaces
- `MachineFingerprint` — WMI CPU/BIOS fingerprint
- `LicenseFile.TryRead` — reads `.lic` file, returns base64 signature
- `LicenseValidator.Validate` — RSA-SHA256 verify
- `LicenseValidatorTests` — 6 unit tests (testable via internal ctor injection)
### Phase 08 — License Integration
- `Program.cs` — RSA check wired at startup; `checkLicense` deleted; `license.lic` next to EXE
- `InputArgs.cs``-chiave=` field removed
### Phase 09 — License Generator
- `LicenseGenerator` standalone console tool (separate repo: `ssh://git@3nt-git.duckdns.org:222/davide.trentin/license-generator.git`)
- Commands: `keygen` (RSA 2048-bit pair), `fingerprint` (WMI, Windows), `sign` (RSA-SHA256 → .lic)
- Real public key embedded in `Licensing/LicenseValidator.cs` (PLACEHOLDER removed)
- `private.key.xml` at `~/Documents/mine/c#/LicenseGenerator/` (gitignored — keep secure)
### Phase 10 — README Docs
- `README.md` in NcProgramManager root — Italian, operator-facing: CLI args, license setup, examples, controllers table
- `README.md` in LicenseGenerator repo — Italian, vendor-facing: keygen first-run, 4-step license issuance workflow, commands table, security
## CLI Args (current — all 16)
- `-azione=` — action (Scarica/Invia)
- `-manufacturer=fanuc|heidenhain|siemens|mitsubishi` (default: fanuc)
- `-ip=` — CNC IP (Ethernet)
- `-porta=` — port (Ethernet)
- `-tipo=` — connection type: 3=Ethernet, 2=HSSB (Fanuc legacy)
- `-nodo=` — HSSB node (Fanuc only)
- `-username=` (Heidenhain/Siemens/Mitsubishi)
- `-password=` (Heidenhain/Siemens/Mitsubishi)
- `-pathprogramma=` — local file path (required for Invia)
- `-path=` — CNC program path; default 1 = //CNC_MEM/USER/PATH1/
- `-workzero=` — include work zero offset
- `-tooloffset=` — include tool offset
- `-commento=` — program comment
- `-compatibility` — compatibility mode flag
- `-debug=` — keep terminal open after operation
- `-help` — show help and exit
- License: place `license.lic` next to EXE (no CLI arg)
## Accumulated Context
### Decisions
- .NET 4.7.2 locked — max compatibility
- RSA asymmetric offline licensing: private key vendor-only, public key embedded in binary
- `license.lic` always at `AppDomain.CurrentDomain.BaseDirectory` — no CLI override
- `RSACryptoServiceProvider` + `SHA256CryptoServiceProvider` (not HashAlgorithmName) — .NET 4.7.2 compat
- Constructor injection pattern: internal ctor accepts key XML — testable without Windows WMI
- LicenseGenerator: standalone separate repo — vendor tool, never shipped to customers
- Heidenhain: LSV2 port 19000, needs real hardware testing
- Siemens: FTP `/_N_MPF_DIR/`, needs Sinumerik FTP option enabled on machine
- `#` = Warning in Fanuc/Mitsubishi — macro variable indicator
- NLog console target `levels="Info"`, `${message}` layout — all operator output through NLog; Warn/Error file only
- Cleanup catches: comment-only, no log — Dispose must not throw; logging infra can fail
### Deferred Issues
Tracked in `.paul/ISSUES.md` — 11 issues total; 7 closed (ISS-001, ISS-003, ISS-004, ISS-005, ISS-006, ISS-007, ISS-008 partial).
Key open items:
- ISS-002: Blocking .GetAwaiter().GetResult() — Medium, refactor
- ISS-008: Full closure needs real Windows hardware run with env vars set
- ISS-009/010: Heidenhain/Siemens ReadActiveProgram not implemented — deferred
- `private.key.xml` owned by root (external repo) — run `sudo chown $USER ~/Documents/mine/c#/LicenseGenerator/private.key.xml`
### Blockers/Concerns
None — v0.5 complete.
### Git State
Last commit: `68c5a55` — chore(paul): close v0.6 Fagor Support milestone, log ISS-012..017
LicenseGenerator repo: commit `2ef68dd` — feat: initial LicenseGenerator
Branch: main
Uncommitted (pre-Phase 17 work, to fold into 17-01):
- Program.cs — `#if !DEBUG` wrap license check
- NcProgramManager.csproj — Obfuscate target (Release-only)
- NcProgramManager.crproj — ConfuserEx config
- tools/ConfuserEx/ — CLI 1.6.0 (vendored; consider gitignore)
- 4 test files — `result.Error``string.Join("; ", result.Errors)` fix
## Codebase Mapped
Date: 2026-05-18
Documents: `.paul/codebase/` (7 files — STACK, ARCHITECTURE, STRUCTURE, CONVENTIONS, TESTING, INTEGRATIONS, CONCERNS)
## Session Continuity
Last session: 2026-05-25
Stopped at: Milestone v0.7 Build Hardening created (phases 17 + 18 scaffolded)
Next action: /paul:plan for Phase 17 (build-pipeline)
Resume file: .paul/ROADMAP.md
---
*STATE.md — Updated after every significant action*