Files
PSProxmoxVE/docs/review/REVIEW_REPORT.md
T
Clint Branham 89bead7a0e fix: add -Confirm:$false to Restart-PveContainer integration test (F080, F081)
Restart-PveContainer gained ConfirmImpact.High in the F062 fix, which
correctly prompts for confirmation on destructive operations. The
integration test was missing -Confirm:$false, causing a
NullReferenceException in non-interactive CI. The cascading failure also
broke the Copy-PveContainer test (F081).

Also updates CONTRIBUTING.md to reference .NET SDK 10.0+ (was 9.0+) to
match all CI workflows and test project TFM (F083).

Includes scan-6 review report and findings database update (F001-F083).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 14:48:11 -05:00

16 KiB
Raw Blame History

PSProxmoxVE Module Review Report — Scan 6

Scan date:           2026-03-23
Prior report date:   2026-03-23 (scan-5)
PVE API spec date:   2026-03-21T15:04:50.641Z
PVE API spec SHA256: 4af79be30166209a4714b771f65e1e9540c5b738f414ff30c98454402e29d030
PVE version hint:    N/A (not set in spec)
Total API endpoints: 646
Findings DB:         docs/review/findings.json (F001F083)
Open findings:       11 (before scan) → 15 (after scan)
New this scan:       4  Resolved this scan: 0  Regressed: 0
Last CI run:         integration-tests.yml | failure | 2026-03-23T18:51:46Z | https://github.com/goodolclint/PSProxmoxVE/actions/runs/23454616043

Executive Summary

  • Delta: 0 resolved | 4 new | 0 regressed | 15 open
  • API drift: 0 breaking changes in implemented endpoints | 42 PVE 9.0 endpoints unimplemented (F061)
  • CI: Last integration run: FAILED | 2 test failures on PVE 9 + 1 infrastructure failure on PVE 8
  • Code quality: All 12 DECISIONS.md entries upheld — zero regressions detected
  • Module has 169 cmdlets, 170 markdown docs, netstandard2.0 targeting, ~800+ total tests (374 xUnit + ~400-500 Pester + 107 integration)
  • PSGallery manifest complete except IconUri (F021)
  • 77 PVE 9.0 parameter changes detected across implemented endpoints (all additive, none breaking)

Phase 1 — Repository Inventory & Structure

Project Layout

Item Present Path/Notes
Solution file Yes PSProxmoxVE.sln
Cmdlet project Yes src/PSProxmoxVE/ (netstandard2.0)
Core library Yes src/PSProxmoxVE.Core/ (netstandard2.0)
xUnit tests Yes tests/PSProxmoxVE.Core.Tests/ (net10.0;net48)
Pester tests Yes tests/PSProxmoxVE.Tests/
Module manifest Yes src/PSProxmoxVE/PSProxmoxVE.psd1
MAML help Yes src/PSProxmoxVE/PSProxmoxVE.dll-Help.xml
Format file Yes src/PSProxmoxVE/PSProxmoxVE.format.ps1xml
README.md Yes With badges (Build, Unit Tests, License, PSGallery)
CHANGELOG.md Yes Keep a Changelog format, 0.1.0-preview entry
CONTRIBUTING.md Yes References .NET SDK 9.0+ — should be 10.0+ (F083)
LICENSE Yes MIT
CODE_OF_CONDUCT.md Yes Contributor Covenant
SECURITY.md Yes Vulnerability disclosure policy
DECISIONS.md Yes 12 active decisions (D001D012)
.editorconfig Yes Present
.gitignore Yes Present
.gitattributes Yes Line ending normalization
CODEOWNERS Yes Present
Issue templates Yes Bug report (YAML), feature request (YAML), config.yml
PR template Yes .github/pull_request_template.md
dependabot.yml Yes NuGet + GitHub Actions (weekly)
CI: Build Yes .github/workflows/build.yml (3-matrix)
CI: Unit Tests Yes .github/workflows/unit-tests.yml (Pester multi-platform)
CI: Integration Yes .github/workflows/integration-tests.yml (PVE 8+9)
CI: Publish Yes .github/workflows/publish.yml (tag-triggered, PS 5.1 smoke test)
Findings DB Yes docs/review/findings.json (F001F083)

Missing Items

None — all expected files for a well-maintained open-source PowerShell module are present.


Phase 2 — PVE API Coverage Audit

Coverage by Functional Area

Area Total Endpoints Cmdlets Est. Coverage Notes
VMs (qemu) ~80 28 ~35% Core CRUD, lifecycle, guest agent, disk, config
Containers (lxc) ~45 20 ~44% Full lifecycle + snapshots + templates
Storage ~30 11 ~37% CRUD, content, upload, download, disk alloc
Network ~15 5 ~33% CRUD + apply
SDN ~45 19 ~42% Zones, VNets, subnets, IPAM, DNS, controllers, apply
Firewall (cluster) ~20 21 ~100% Rules, groups, aliases, IP sets, options, refs
Access/Users ~25 21 ~84% Users, roles, groups, domains, tokens, permissions, password
Nodes ~40 8 ~20% Status, config, DNS, start/stop VMs
Tasks ~5 4 ~80% Get, list, stop, wait
Backup ~10 6 ~60% Ad-hoc + job CRUD + compliance
Templates ~5 4 ~80% Get, create, remove, clone
CloudInit ~3 3 ~100% Get, set, regenerate
Cluster ~77 1 ~1% Only Get-PveClusterResource
Snapshots ~5 4 ~80% VM snapshots: get/new/remove/restore
Pools ~5 4 ~80% CRUD
HA ~26 0 0% F053
Ceph ~40 0 0% F054
Notifications ~32 0 0% F068
ACME/Certificates ~23 0 0% F069
Disks (LVM/ZFS) ~18 0 0% F067
Total ~646 169 ~26%

PVE 9.0 New Endpoints (42 total, 0 implemented — F061)

Key new subsystems in PVE 9.0:

Category Endpoints Description
HA Rules 5 Affinity/anti-affinity rules for HA resources
Bulk Actions 5 Cluster-wide guest start/shutdown/suspend/migrate
SDN Fabrics 13 Fabric management, node assignments
SDN Lock/Rollback 3 Transactional SDN changes
OCI Registry 1 Container image pulls from OCI registries
Node SDN 6 Per-node SDN fabric/zone/vnet inspection
Node Capabilities 2 CPU flags, migration capabilities
VM/Container 2 DBus VM state, container migration preflight
Access 1 VNC ticket creation

API Drift — PVE 9.0 Parameter Changes

77 parameter changes detected across implemented endpoints. All are additive (new optional parameters) except:

Risk Endpoint Change
Mild POST /cluster/backup -notification-policy,-notification-target (removed)
Mild PUT /cluster/backup/{id} -notification-policy,-notification-target (removed)
Additive SDN zone/vnet/subnet/controller/ipam/dns +lock-token parameter
Additive SDN zones/controllers +fabric parameter
Additive POST /nodes/{node}/qemu +allow-ksm,+intel-tdx
Additive PUT /nodes/{node}/lxc/{vmid}/config +entrypoint,+env
Additive POST /storage, PUT /storage/{storage} +snapshot-as-volume-chain,+zfs-base-path

The removed notification-policy and notification-target parameters on backup endpoints should be verified — if New-PveBackupJob or Set-PveBackupJob send these parameters, PVE 9.0 will reject them.


Phase 3 — Code Quality & Best Practices

3a. PowerShell Module Design

Check Status Evidence
Approved verbs only Pass All 169 cmdlets use standard PS verb classes
Verb class constants Pass No string literals in [Cmdlet] attributes (D011)
All classes sealed Pass 169/169 sealed (D007)
OutputType on all Pass 169/169 have [OutputType] (D005)
ShouldProcess on destructive Pass All Remove/Stop/Reset/Restart/Suspend/Restore/Template cmdlets
ConfirmImpact.High Pass All destructive cmdlets (D006)
VmId ValidateRange Pass All VmId params have [ValidateRange(100, 999999999)] (D010)
Pve noun prefix Pass All cmdlets use Pve prefix

3b. C# Code Quality

Check Status Evidence
No inline task-polling Pass Only TaskService.WaitForTask and WaitPveTaskCmdlet have while(true) — both with timeout (D001)
No bare catch blocks Pass Zero catch { } or unfiltered catch (Exception) in src/ (D004)
SecureString passwords Pass SetPveVmGuestPassword and SetPvePassword use SecureString (D002)
URL encoding Pass Uri.EscapeDataString on all path params across all services (D003)
Newtonsoft only Pass No [JsonPropertyName] attributes anywhere in src/ (D008)
No System.Text.Json dep Pass Not referenced in any .csproj
Magic strings extracted Pass Auth header names are const fields (D012)
Sync-over-async wont_fix .GetAwaiter().GetResult() — accepted PS binary module pattern (F048)

3c. General Hygiene

Check Status Evidence
Framework targeting Pass Publishable: netstandard2.0. Tests: net10.0;net48 (D009)
SDK versions Pass All workflows use dotnet SDK 10.0.x
XML doc generation Pass GenerateDocumentationFile=true in Core.csproj

3d. HttpClient Lifecycle

PveHttpClient implements IPveHttpClient interface. All 14 services accept IPveHttpClient via constructor injection, enabling shared client instances per session. HttpClient is created once per PveHttpClient instance. F045 resolved in prior scan.

DECISIONS.md Compliance

All 12 decisions (D001D012) verified with no regressions detected.


Phase 4 — Testing Coverage Analysis

Test Infrastructure

Component Framework Count Notes
xUnit tests net10.0;net48 374 cases 25 files: services (214), models (133), auth (27)
Pester unit tests PS 5.1, 7.5 ~400-500 cases 46 files: parameter validation, metadata, ShouldProcess
Pester integration PS 7.x 107 cases 1 file: live PVE 8 + PVE 9 end-to-end
Total ~800+ Three-tier: unit (xUnit) + cmdlet (Pester) + integration

Test Quality Assessment

  • Three-tier strategy: xUnit validates core business logic (services, models), Pester validates cmdlet surface (parameters, metadata, parameter sets), integration validates end-to-end on live PVE
  • All 169 cmdlets have Pester tests: Parameter validation, mandatory params, ShouldProcess support, OutputType
  • Arrange/Act/Assert: xUnit tests consistently structured with Moq for IPveHttpClient mocking
  • Offline-first: 45/46 Pester test files work without network; xUnit uses mock fixtures
  • Edge cases: Null parameters, empty arrays, API errors, PVE 8 + PVE 9 response formats
  • Test isolation: xUnit uses DI via mocked IPveHttpClient; each test is independent

Coverage Gaps (F046)

All cmdlets have Pester parameter validation tests. ~64 of 169 cmdlets lack integration test coverage. The integration test suite covers 107 cases:

  • Connection, nodes, users, roles, API tokens, permissions
  • VMs (CRUD, lifecycle, config, resize, clone, snapshots)
  • Containers (CRUD, lifecycle, config, snapshots)
  • Storage (CRUD, content, upload, download)
  • Network (CRUD, apply), SDN (zones, VNets, subnets, IPAM, DNS, controllers)
  • Templates (convert, clone, remove), cloud-init, tasks
  • Firewall (rules, aliases, IP sets), backup jobs, OVA import, guest agent

Untested in integration: Guest file operations, node config/DNS, pool management, some storage operations, SDN update cmdlets.


Phase 4b — CI Integration Test Results

Last Run Summary

Field Value
Run ID 23454616043
Branch main
Conclusion failure
Created 2026-03-23T18:51:46Z
Head SHA 68dadbf

PVE 9: 104 passed, 2 failed, 1 skipped

Finding ID Test Failure Message Platform PVE Severity
F080 Should restart a container NullReferenceException — ConfirmImpact.High prompts for confirmation in non-interactive CI ubuntu/pwsh 9 High
F081 Should clone a container PveApiException: Cannot do full clones on a running container without snapshots ubuntu/pwsh 9 Medium

Root cause: F062 fix (adding ConfirmImpact.High to Restart-PveContainer) is correct behavior, but the integration test at line 983 does not pass -Confirm:$false. The container remained running after the restart failed, causing the subsequent clone test to also fail.

Fix: Add -Confirm:$false to the Restart-PveContainer call in the integration test.

PVE 8: Infrastructure failure

Finding ID Test Failure Message Platform PVE Severity
F082 Initialize containers Docker image ghcr.io/goodolclint/psproxmoxve-integration:68dadbf... not found self-hosted 8 Low

Root cause: Container image for this commit SHA was not available in GHCR. No actual test logic failures on PVE 8.


Phase 5 — Security Review

Finding ID Area Severity Status Description
F031 Secret scanning Low Open Hardcoded test password in CI workflow — masked, disposable VM
Credential handling Pass PSCredential, SecureString with Marshal cleanup (D002)
TLS/HTTPS Pass Enforced by default, SkipCertificateCheck opt-in with warning
URL encoding Pass Uri.EscapeDataString on all path params (D003)
Dependencies Pass Newtonsoft.Json 13.0.3, SharpCompress 0.38.0 — current
Debug scripts Pass Placeholder tokens only (F052 resolved)
Verbose logging Pass No credentials in WriteVerbose/WriteDebug output

No new security findings. All security-related DECISIONS.md entries (D002, D003) upheld.


Phase 6 — PSGallery Publication Readiness

Finding ID Check Pass/Fail Notes
ModuleVersion Pass 0.1.0
GUID Pass a3f7c2d1-84e5-4b9f-a061-3e2d8c5f1a7b
Author Pass goodolclint
Description Pass Descriptive
PowerShellVersion Pass 5.1
CompatiblePSEditions Pass Desktop, Core
LicenseUri Pass MIT license linked
ProjectUri Pass GitHub repo linked
Tags Pass 8 relevant tags
ReleaseNotes Pass Present in PSData
F021 IconUri Fail Missing — cosmetic only
Prerelease Pass 'preview' — appropriate for current state
CmdletsToExport Pass 169 cmdlets listed
AliasesToExport Pass 7 aliases
RequiredAssemblies Pass PSProxmoxVE.Core.dll, Newtonsoft.Json.dll
FormatsToProcess Pass PSProxmoxVE.format.ps1xml
MAML help Pass PSProxmoxVE.dll-Help.xml
Markdown docs Pass 170 files in docs/cmdlets/
Publish workflow Pass Tag-triggered with PS 5.1 smoke test (threshold >= 150)
netstandard2.0 only Pass Both publishable projects (D009)

Phase 7 — Community & Repo Maintenance Standards

Finding ID Check Pass/Fail Notes
README quality Pass Comprehensive with examples, badges, version table
CONTRIBUTING.md Pass Dev setup, coding standards, PR process
F083 CONTRIBUTING.md SDK version Fail References .NET SDK 9.0+ (should be 10.0+)
CODE_OF_CONDUCT.md Pass Contributor Covenant
SECURITY.md Pass Vulnerability disclosure policy
DECISIONS.md Pass 12 active decisions, linked from CLAUDE.md
Issue templates Pass Bug report + feature request (YAML) + config.yml
PR template Pass Present
CODEOWNERS Pass Present
.gitattributes Pass Line ending normalization
.editorconfig Pass Present
dependabot.yml Pass NuGet + GitHub Actions (weekly)
CHANGELOG.md Pass Keep a Changelog format
Commit conventions Pass Conventional Commits

Phase 9 — Prioritized Recommendations

Critical

(None)

High

Finding ID What Where Why Fix
F080 Restart-PveContainer CI failure Integration.Tests.ps1:983 ConfirmImpact.High prompts in non-interactive CI Add -Confirm:$false to test

Medium

Finding ID What Where Why Fix
F046 Integration test coverage gaps tests/ ~64 cmdlets untested end-to-end Add tests incrementally
F059 VM/CT-level firewall 0% ~44 endpoints for per-VM/CT firewall Implement VM/CT firewall cmdlets
F060 Cluster config 0% 10 endpoints for cluster management Implement cluster config cmdlets
F061 PVE 9.0 endpoints 0% 42 new endpoints Prioritize HA rules and bulk actions
F081 Copy-PveContainer CI failure Integration.Tests.ps1:998 Cascading from F080 Resolves when F080 is fixed

Low

Finding ID What Where Why Fix
F021 No IconUri PSProxmoxVE.psd1 Cosmetic PSGallery appearance Add IconUri
F031 Hardcoded test password integration-tests.yml Masked, disposable VM Move to secret (optional)
F053 HA subsystem 0% 21+ HA endpoints Implement HA cmdlets
F054 Ceph subsystem 0% 40 Ceph endpoints Implement Ceph cmdlets
F067 Disk management 0% 18 disk endpoints Implement disk cmdlets
F068 Notifications 0% 32 notification endpoints Implement notification cmdlets
F069 ACME/Certificates 0% 23 ACME endpoints Implement ACME cmdlets
F082 PVE 8 Docker image failure integration-tests.yml Infrastructure issue Investigate GHCR push
F083 CONTRIBUTING.md SDK version CONTRIBUTING.md:9 Wrong SDK version listed Change "9.0+" to "10.0+"