mirror of
https://github.com/GoodOlClint/PSProxmoxVE.git
synced 2026-08-20 09:52:17 +00:00
b4754c72a0
- README: move Set-PveStorage to Storage section, Set-PveApiToken to Access section (were miscategorized under "Access — Groups & Domains") - CHANGELOG: add Changed section with 13 architectural improvements, expand Fixed section with all ConfirmImpact and credential fixes - SECURITY.md: add SecureString detail, Input Validation section, Dependabot mention, SkipCertificateCheck warning note - CLAUDE.md: update review system reference to scan-7 - findings.json: F050 resolved (URL encoding), F031 resolved (credentials) - REVIEW_REPORT.md: scan-7 report Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
309 lines
14 KiB
Markdown
309 lines
14 KiB
Markdown
# PSProxmoxVE Module Review Report — Scan 7
|
||
|
||
```
|
||
Scan date: 2026-03-23
|
||
Prior report date: 2026-03-23 (scan-6)
|
||
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 (F001–F083)
|
||
Open findings: 12 (before scan) → 11 open + 1 regressed (after scan)
|
||
New this scan: 0 Resolved this scan: 1 (F082) Regressed: 1 (F050)
|
||
Last CI run: integration-tests.yml | success | 2026-03-23T21:42:02Z | https://github.com/goodolclint/PSProxmoxVE/actions/runs/23461565300
|
||
```
|
||
|
||
## Executive Summary
|
||
|
||
- **Delta**: 1 resolved (F082) | 0 new | 1 regressed (F050) | 11 open + 1 regressed
|
||
- **API drift**: 0 breaking changes in implemented endpoints | 42 PVE 9.0 endpoints unimplemented (F061)
|
||
- **CI**: Last integration run: **PASSED** | 0 test failures (both PVE 8 and PVE 9)
|
||
- **Code quality**: 11 of 12 DECISIONS.md entries upheld — **1 regression** (D003: URL encoding in 5 service files)
|
||
- Module has 169 cmdlets, ~170 markdown docs, netstandard2.0 targeting, 1,749 total tests (374 xUnit + 1,268 Pester + 107 integration)
|
||
- PSGallery manifest complete except IconUri (F021)
|
||
- All community/repo standards pass (issue templates, CONTRIBUTING, SECURITY, CODE_OF_CONDUCT, CODEOWNERS, etc.)
|
||
|
||
---
|
||
|
||
## 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 | Dev setup, coding standards, PR process |
|
||
| LICENSE | Yes | MIT |
|
||
| CODE_OF_CONDUCT.md | Yes | Contributor Covenant 2.1 |
|
||
| SECURITY.md | Yes | Vulnerability disclosure policy |
|
||
| DECISIONS.md | Yes | 12 active decisions (D001–D012) |
|
||
| .editorconfig | Yes | Root config with per-filetype overrides |
|
||
| .gitignore | Yes | Comprehensive |
|
||
| .gitattributes | Yes | LF enforcement, binary handling, diff drivers |
|
||
| CODEOWNERS | Yes | `* @goodolclint` |
|
||
| dependabot.yml | Yes | Automated dependency updates |
|
||
| Issue templates | Yes | Bug report + feature request (YAML forms) + config.yml |
|
||
| PR template | Yes | Summary, type, checklist, API endpoints, testing |
|
||
| CI workflows | Yes | build.yml, unit-tests.yml, integration-tests.yml, publish.yml |
|
||
| Review system | Yes | docs/review/findings.json, docs/review/REVIEW_REPORT.md |
|
||
| Cmdlet docs | Yes | ~170 markdown files in docs/cmdlets/ |
|
||
|
||
### Missing Items
|
||
|
||
| Finding ID | Item | Notes |
|
||
|---|---|---|
|
||
| F021 | IconUri in manifest PSData | PSGallery listings display placeholder without it |
|
||
|
||
---
|
||
|
||
## Phase 2 — PVE API Coverage Audit
|
||
|
||
### Coverage by Functional Area
|
||
|
||
| Area | Spec Endpoints | Covered | % | Notes |
|
||
|------|---------------|---------|---|-------|
|
||
| VMs (qemu) | 97 | ~30 | 31% | Core CRUD, lifecycle, guest agent, disk ops, config |
|
||
| Containers (lxc) | 62 | ~18 | 29% | CRUD, lifecycle, snapshots, config, interfaces |
|
||
| Nodes | 77 | ~10 | 13% | List, status, config, DNS, startall/stopall |
|
||
| Firewall | 40 | ~22 | 55% | Rules, groups, aliases, IP sets, options, refs |
|
||
| Cluster | 79 | ~3 | 4% | Resources and status only |
|
||
| SDN | 60 | ~16 | 27% | Zones, VNets, subnets, IPAM, DNS, controllers |
|
||
| Storage | 24 | ~14 | 58% | CRUD, content, upload, download, allocate |
|
||
| Backup | 6 | 6 | 100% | Full coverage |
|
||
| Access/Users | 45 | ~22 | 49% | Users, groups, roles, domains, tokens, ACL, permissions |
|
||
| Tasks | 5 | ~4 | 80% | List, status, log, stop |
|
||
| Pools | 7 | ~5 | 71% | CRUD + list |
|
||
| HA | 21 | 0 | 0% | F053 — 🆕 Rules subsystem new in PVE 9.0 |
|
||
| Ceph | 40 | 0 | 0% | F054 |
|
||
| Notifications | 25+ | 0 | 0% | F068 — New in PVE 8.1+ |
|
||
| ACME/Certs | 23 | 0 | 0% | F069 |
|
||
| Disks | 18 | 0 | 0% | F067 |
|
||
| Replication | 5 | 0 | 0% | |
|
||
| Services | 7 | 0 | 0% | |
|
||
| **Total** | **646** | **~120** | **~18.6%** | |
|
||
|
||
### API Drift Table
|
||
|
||
No breaking changes detected in endpoints the module currently implements. All changes are additive (new optional parameters).
|
||
|
||
| Finding ID | Area | Change | PVE Version | Risk |
|
||
|---|---|---|---|---|
|
||
| F061 | HA rules | New `/cluster/ha/rules` subsystem | 9.0 | Additive |
|
||
| F061 | Bulk actions | New `/cluster/bulk-action` | 9.0 | Additive |
|
||
| F061 | SDN fabrics | New `/cluster/sdn/fabrics` | 9.0 | Additive |
|
||
| — | Various | 77 additive parameter changes across implemented endpoints | 8.x–9.x | Additive |
|
||
|
||
### High-Value Uncovered Endpoints
|
||
|
||
**Priority 1 — Commonly needed:**
|
||
- `GET /access/acl` — List ACLs (only PUT covered)
|
||
- `GET /cluster/nextid` — Get next free VM ID
|
||
- `GET /cluster/ha/resources` — HA resource management
|
||
- VNC/SPICE console proxy endpoints
|
||
- `GET /nodes/{node}/subscription` — Subscription status
|
||
|
||
**Priority 2 — Frequently useful:**
|
||
- `GET /nodes/{node}/syslog` / `journal` — Log access
|
||
- `GET /nodes/{node}/hardware` — PCI passthrough info
|
||
- `GET /nodes/{node}/scan/*` — Storage discovery
|
||
- `POST /access/domains/{realm}/sync` — LDAP/AD sync
|
||
- APT package management
|
||
|
||
---
|
||
|
||
## Phase 3 — Code Quality & Best Practices
|
||
|
||
### DECISIONS.md Compliance
|
||
|
||
| Decision | Status | Notes |
|
||
|---|---|---|
|
||
| D001 — TaskService.WaitForTask | ✅ Compliant | No inline polling loops in cmdlets |
|
||
| D002 — SecureString passwords | ✅ Compliant | All 6 password params use SecureString |
|
||
| D003 — URL encoding | ❌ **REGRESSED (F050)** | 20 instances in 5 service files |
|
||
| D004 — No bare catch blocks | ✅ Compliant | All catches are specific or filtered |
|
||
| D005 — OutputType on all cmdlets | ✅ Compliant | All 169 cmdlets have OutputType |
|
||
| D006 — ConfirmImpact.High | ✅ Compliant | All destructive cmdlets confirmed |
|
||
| D007 — Sealed cmdlet classes | ✅ Compliant | All 169 cmdlets sealed |
|
||
| D008 — Newtonsoft.Json only | ✅ Compliant | No System.Text.Json attributes |
|
||
| D009 — Framework targets | ✅ Compliant | netstandard2.0 / net10.0;net48 |
|
||
| D010 — VmId ValidateRange | ✅ Compliant | All VmId params validated |
|
||
| D011 — Verb class constants | ✅ Compliant | No string literals |
|
||
| D012 — Magic string constants | ✅ Compliant | Auth headers extracted |
|
||
|
||
### D003 Regression Detail (F050)
|
||
|
||
20 instances of missing `Uri.EscapeDataString()` across 5 service files:
|
||
|
||
| File | Methods Affected | Unescaped Params |
|
||
|---|---|---|
|
||
| NodeService.cs | 7 (GetNodeStatus, GetNodeConfig, SetNodeConfig, GetDns, SetDns, StartAll, StopAll) | `node` |
|
||
| NetworkService.cs | 5 node-network (GetNetworks, CreateNetwork, SetNetwork, RemoveNetwork, ApplyNetworkConfig) | `node`, `iface` |
|
||
| NetworkService.cs | 2 SDN (RemoveSdnZone, RemoveSdnVnet) | `zone`, `vnet` |
|
||
| CloudInitService.cs | 3 (GetCloudInitConfig, SetCloudInitConfig, RegenerateCloudInitImage) | `node` |
|
||
| TaskService.cs | 2 (GetTask, GetTaskLog) | `node` |
|
||
| TemplateService.cs | 1 (CreateTemplate) | `node` |
|
||
|
||
Properly escaped services (no issues): VmService, ContainerService, SnapshotService, FirewallService, PoolService, UserService, StorageService.
|
||
|
||
### Other Code Quality Findings
|
||
|
||
- No TODO/FIXME/HACK comments
|
||
- No commented-out code
|
||
- No unused using directives detected
|
||
- HttpClient lifecycle is well-managed (1:1 ownership, proper disposal)
|
||
- `PveCmdletBase.WaitForStatusTransition` power-state polling loop is distinct from task polling (D001 compliant)
|
||
|
||
---
|
||
|
||
## Phase 4 — Testing Coverage Analysis
|
||
|
||
### Test Summary
|
||
|
||
| Category | Files | Tests |
|
||
|---|---|---|
|
||
| xUnit (C# unit) | 25 | 374 |
|
||
| Pester (PS unit) | 48 | 1,268 |
|
||
| Pester (integration) | 1 | 107 |
|
||
| **Total** | **74** | **1,749** |
|
||
|
||
### Coverage Highlights
|
||
|
||
- **100% cmdlet unit test coverage** — all 169 cmdlets have Pester parameter/metadata tests
|
||
- **xUnit service tests**: UserService (78), StorageService (40), FirewallModel (24), BackupService (23), SdnModel (21)
|
||
- **32 JSON fixture files** from real PVE 8/9 API responses for model deserialization tests
|
||
- **Integration tests**: 107 tests across connection, nodes, VMs, containers, snapshots, storage, users, firewall, SDN, backup, templates, cloud-init, guest agent
|
||
|
||
### Coverage Gaps (F046)
|
||
|
||
| Gap | Severity | Detail |
|
||
|---|---|---|
|
||
| No VmService xUnit tests | Medium | VM ops (clone, migrate, import) have complex logic untested at service layer |
|
||
| No ContainerService xUnit tests | Medium | Similar complexity to VmService |
|
||
| No NetworkService xUnit tests | Low | Thin CRUD wrappers |
|
||
| No FirewallService xUnit tests | Low | Thin CRUD wrappers |
|
||
| Pool/Cluster cmdlets lack integration tests | Low | Simple read-only operations |
|
||
|
||
---
|
||
|
||
## Phase 4b — CI Integration Test Results
|
||
|
||
### Last CI Run
|
||
|
||
| Field | Value |
|
||
|---|---|
|
||
| Run ID | 23461565300 |
|
||
| Conclusion | **SUCCESS** |
|
||
| Date | 2026-03-23T21:42:02Z |
|
||
| SHA | `1faaba0` |
|
||
| Branch | main |
|
||
|
||
All 7 jobs passed: container-image, build, provision, test(8), test(9), cleanup, cleanup-images.
|
||
|
||
### CI Findings
|
||
|
||
| Finding ID | Test / Cmdlet | Status | Notes |
|
||
|---|---|---|---|
|
||
| F080 | Restart-PveContainer | Resolved (scan-6) | ConfirmImpact.High fix applied |
|
||
| F081 | Copy-PveContainer | Resolved (scan-6) | Cascade from F080 |
|
||
| F082 | PVE 8 Docker image | **Resolved (this scan)** | Container-image job now succeeds |
|
||
|
||
---
|
||
|
||
## Phase 5 — Security Review
|
||
|
||
| Finding ID | Area | File(s) | Severity | Status | Description |
|
||
|---|---|---|---|---|---|
|
||
| F050 | URL encoding | 5 service files | Medium | **Regressed** | 20 instances of unescaped path params (see Phase 3) |
|
||
| F031 | Secrets | terraform.tfvars, CI | Low | Open | Lab IPs in terraform.tfvars (gitignored); CI uses ${{ secrets.* }} properly |
|
||
| — | Credential handling | All password cmdlets | Pass | — | SecureString with Marshal try/finally throughout |
|
||
| — | TLS/HTTPS | PveHttpClient.cs | Pass | — | HTTPS-only, SkipCertificateCheck opt-in with warning |
|
||
| — | CSRF | PveHttpClient.cs | Pass | — | CSRFPreventionToken on all mutating requests |
|
||
| — | Bare catches | All .cs files | Pass | — | No D004 violations |
|
||
| — | Boundary generation | PveHttpClient.cs | Pass | — | Uses RandomNumberGenerator (CSPRNG) |
|
||
| — | Dependencies | Both .csproj | Pass | — | Newtonsoft.Json 13.0.3, SharpCompress 0.47.3 (current) |
|
||
|
||
---
|
||
|
||
## Phase 6 — PSGallery Publication Readiness
|
||
|
||
| Finding ID | Check | Pass/Fail | Notes |
|
||
|---|---|---|---|
|
||
| — | ModuleVersion | Pass | 0.1.0, dynamically set from git tag |
|
||
| — | GUID | Pass | Present and unique |
|
||
| — | Author/CompanyName | Pass | goodolclint / Worklab |
|
||
| — | Description | Pass | Descriptive, mentions PVE 8.x/9.x |
|
||
| — | PowerShellVersion | Pass | 5.1 minimum |
|
||
| — | CompatiblePSEditions | Pass | Desktop + Core |
|
||
| — | CmdletsToExport | Pass | Explicit list of 169 cmdlets |
|
||
| — | Tags | Pass | 8 tags for discoverability |
|
||
| — | LicenseUri/ProjectUri | Pass | GitHub links |
|
||
| F021 | IconUri | **Fail** | Not set — PSGallery shows placeholder |
|
||
| — | ReleaseNotes | Pass | Present in PSData |
|
||
| — | Framework targets | Pass | netstandard2.0 for both publishable projects |
|
||
| — | Publish workflow | Pass | Tag-triggered, 3-job pipeline with PS 5.1 smoke test |
|
||
| — | CHANGELOG | Pass | Keep a Changelog format |
|
||
|
||
---
|
||
|
||
## Phase 7 — Community & Repo Maintenance Standards
|
||
|
||
| Finding ID | Check | Pass/Fail | Notes |
|
||
|---|---|---|---|
|
||
| — | Bug report template | Pass | YAML form with version fields |
|
||
| — | Feature request template | Pass | YAML form with use case |
|
||
| — | Issue template config | Pass | Disables blank issues, links to Discussions |
|
||
| — | PR template | Pass | Checklist with build, tests, psd1, changelog |
|
||
| — | CONTRIBUTING.md | Pass | Complete dev setup and coding standards |
|
||
| — | CODE_OF_CONDUCT.md | Pass | Contributor Covenant 2.1 |
|
||
| — | SECURITY.md | Pass | Responsible disclosure instructions |
|
||
| — | DECISIONS.md | Pass | 12 decisions, linked from CLAUDE.md |
|
||
| — | CODEOWNERS | Pass | `* @goodolclint` |
|
||
| — | .editorconfig | Pass | Per-filetype overrides |
|
||
| — | .gitattributes | Pass | LF enforcement, binary handling |
|
||
| — | Commit conventions | Pass | Conventional Commits consistently used |
|
||
| — | Release process | Pass | Tag-based publish with GitHub Release |
|
||
| — | Dependabot | Pass | Automated dependency PRs |
|
||
|
||
---
|
||
|
||
## Phase 9 — Prioritized Recommendations
|
||
|
||
### 🔴 Critical
|
||
|
||
No critical findings.
|
||
|
||
### 🟠 High
|
||
|
||
No high findings.
|
||
|
||
### 🟡 Medium
|
||
|
||
| Finding ID | What | Where | Why | Fix |
|
||
|---|---|---|---|---|
|
||
| F050 | **Uri.EscapeDataString missing (REGRESSED)** | NodeService, NetworkService, CloudInitService, TaskService, TemplateService | D003 violation — defense-in-depth URL encoding missing on 20 path parameter interpolations | Add `Uri.EscapeDataString()` to all `node`, `iface`, `zone`, `vnet` params in URL paths |
|
||
| F046 | Integration test coverage gaps | tests/ | VmService, ContainerService lack xUnit service-layer tests; Pools/Cluster lack integration tests | Add xUnit tests for VmService and ContainerService |
|
||
| F059 | VM/CT-level firewall 0% coverage | — | Firewall endpoints exist for VMs and containers but no cmdlets implemented | Add VM/CT-scoped firewall cmdlets |
|
||
| F060 | Cluster config 0% coverage | — | Cluster options, join/create, notifications, metrics uncovered | Add cluster config cmdlets |
|
||
| F061 | PVE 9.0 endpoints 0% coverage | — | 42 new endpoints (HA rules, bulk actions, SDN fabrics) not implemented | Prioritize HA rules and bulk actions |
|
||
|
||
### 🟢 Low
|
||
|
||
| Finding ID | What | Where | Why | Fix |
|
||
|---|---|---|---|---|
|
||
| F021 | No IconUri in manifest | PSProxmoxVE.psd1 | PSGallery listing looks less professional | Add 128x128 PNG icon and set IconUri |
|
||
| F031 | Hardcoded test IPs | terraform.tfvars, CI | Lab IPs committed (gitignored locally) | Verify tfvars not tracked in git |
|
||
| F053 | HA subsystem 0% coverage | — | No HA cmdlets | Implement when HA rules (PVE 9.0) are prioritized |
|
||
| F054 | Ceph subsystem 0% coverage | — | Large specialized surface | Low priority unless Ceph users identified |
|
||
| F067 | Disk management 0% coverage | — | Node disk ops (LVM, ZFS, init) | Useful for provisioning workflows |
|
||
| F068 | Notifications 0% coverage | — | 25+ endpoints (PVE 8.1+) | Medium-value for operational users |
|
||
| F069 | ACME/Certificates 0% coverage | — | Certificate management | Low priority |
|