Files
PSProxmoxVE/docs/review/D013-compliance.md
T
Clint Branham 10c277af10 fix: resolve F085 — PveClusterJoinInfo Nodelist/Totem D013 violations
D013 compliance scan found 2 remaining Newtonsoft type exposures:
- PveClusterJoinInfo.Nodelist: JArray → List<Dictionary<string, object?>>
- PveClusterJoinInfo.Totem: JObject → Dictionary<string, object?>

Both now use NativeListConverter/NativeDictionaryConverter for
deserialization. Full D013 compliance report added.

Updated findings.json: F085 status open with scan evidence.

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

10 KiB
Raw Blame History

D013 Compliance Report — Native Type Emission

Scan date: 2026-03-25 (scan-2, broadened scope) Directive: D013 — Cmdlets must emit only native or module-defined types Scope: All third-party dependencies (not Newtonsoft-only) Findings DB: docs/review/findings.json

Third-Party Type Inventory

Library Version Violation Types Scanned Permitted Internal Use
Newtonsoft.Json 13.0.3 JObject, JArray, JToken, JValue, JProperty, JConstructor, JRaw, JContainer [JsonProperty], [JsonConverter], [JsonIgnore] attributes; JsonConvert.* methods; local vars in private methods
SharpCompress 0.47.3 IArchive, IArchiveEntry, IReader, ReaderFactory, ArchiveFactory Local vars in private extraction methods (fully-qualified inline usage)
PowerShellStandard.Library 5.1.1 (none — build-time SDK reference, PrivateAssets="all") All types (PSCmdlet, etc.) are PowerShell SDK types, expected in public APIs

SharpCompress Usage Detail

SharpCompress is used in exactly one location: OvfMetadata.ExtractOvfFromTar() (line 86103 of src/PSProxmoxVE.Core/Models/Vms/OvfMetadata.cs). This is a private static method that uses fully-qualified type references (SharpCompress.Readers.ReaderFactory.OpenReader) — no using directive, no SharpCompress type in any return value, parameter, property, or field. Clean.

Summary

Category Files Scanned Violations Clean
Cmdlet files 195 0 195
Service files 16 0 16
Model files 51 1 50
Other Core files 16 0 16
Test files (informational) 26 0 26
Total 304 1 303

Verdict

NON-COMPLIANT — 1 violation found (2 properties in 1 model class). See findings below.

All violations are from Newtonsoft.Json. SharpCompress has zero public API surface exposure.

Violations

Finding ID Severity Library File Line Violation Type Description
F085 High Newtonsoft.Json src/PSProxmoxVE.Core/Models/Cluster/PveClusterJoinInfo.cs 23 Model property typed as JArray Nodelist property typed as JArray? — emitted via Get-PveClusterJoinInfo
F085 High Newtonsoft.Json src/PSProxmoxVE.Core/Models/Cluster/PveClusterJoinInfo.cs 35 Model property typed as JObject Totem property typed as JObject? — emitted via Get-PveClusterJoinInfo

Detail: PveClusterJoinInfo (F085)

File: src/PSProxmoxVE.Core/Models/Cluster/PveClusterJoinInfo.cs Cmdlet: GetPveClusterJoinInfoCmdlet[OutputType(typeof(PveClusterJoinInfo))] Service: ClusterConfigService.GetJoinInfo() returns PveClusterJoinInfo

The model has two Newtonsoft-typed properties:

// CURRENT (violates D013)
[JsonProperty("nodelist")]
public JArray? Nodelist { get; set; }

[JsonProperty("totem")]
public JObject? Totem { get; set; }

These flow to the PowerShell pipeline via:

var joinInfo = service.GetJoinInfo(session, Node);
WriteObject(joinInfo);  // JArray and JObject properties exposed

Scan Passes Performed

Phase 1 — Third-Party Inventory

  • Newtonsoft.Json 13.0.3: Referenced by both PSProxmoxVE and PSProxmoxVE.Core. Namespaces Newtonsoft.Json and Newtonsoft.Json.Linq are imported across 82 source files.
  • SharpCompress 0.47.3: Referenced by PSProxmoxVE.Core only. Used via fully-qualified names in 1 private method. No using directive anywhere.
  • PowerShellStandard.Library 5.1.1: Build-time SDK reference (PrivateAssets="all"). Not a third-party runtime dependency.
  • No other third-party packages found. No vendored DLLs outside bin/obj.
  • No non-standard using directives found beyond Newtonsoft.*, SharpCompress.* (inline-only), System.*, Microsoft.*, and PSProxmoxVE.*.

Phase 2a — Return type violations (services and public methods)

Patterns: public ... J* methodName(, Task<J*>, List<J*>, IEnumerable<J*> Result: No matches across all third-party types. All service methods return native or module-defined types.

Phase 2b — Model property type violations

Pattern: public J*? PropertyName { (and collection/array variants for all third-party types) Result: 2 matches in PveClusterJoinInfo.cs (lines 23, 35). Confirmed violation (F085). No SharpCompress types found in any model properties.

Phase 2c — OutputType attribute violations

Pattern: [OutputType(typeof(J* (and all SharpCompress types) Result: No matches.

Phase 2d — WriteObject violations

Pattern: WriteObject( (new)? <third-party-type> Result: No matches. No cmdlets pass third-party typed values directly to WriteObject.

Phase 2e — Local variable third-party type assignments in cmdlets

Pattern: <third-party-type>? varName = in cmdlet files Result: No matches for any third-party type in cmdlet files.

Phase 2f — Using directive audit

Namespace Cmdlet files Service files Model files Notes
Newtonsoft.Json 26 16 50 All use for attributes or internal deserialization only, except PveClusterJoinInfo (F085)
Newtonsoft.Json.Linq (subset of above) (subset of above) 1 Only PveClusterJoinInfo imports .Linq in models
SharpCompress.* 0 0 0 Used only via fully-qualified names in 1 private method

Phase 3 — Data flow inspection

26 cmdlet files import Newtonsoft namespaces. All were verified:

  • None declare local variables of J* types
  • None pass J* values to WriteObject
  • All use Newtonsoft only for [JsonProperty] attributes or internal JObject parsing with native value extraction
  • All 26 confirmed clean

Phase 4 — Model property deep scan

51 model files scanned. All public properties use native .NET types (string, int, long, bool, double, DateTime, List<T>, Dictionary<string, object?>) or module-defined Pve* types, except:

  • PveClusterJoinInfo.NodelistJArray? (violation)
  • PveClusterJoinInfo.TotemJObject? (violation)

No private fields typed as third-party types were found that back public properties.

File Class Member Declared Type Third-Party Library Violation? Notes
PveClusterJoinInfo.cs PveClusterJoinInfo Nodelist JArray? Newtonsoft.Json Yes F085
PveClusterJoinInfo.cs PveClusterJoinInfo Totem JObject? Newtonsoft.Json Yes F085
OvfMetadata.cs OvfMetadata (all public) native types No SharpCompress confined to private method

Clean Files (confirmed compliant)

All 303 non-violating source files were confirmed clean through static pattern scanning across all third-party type patterns. The 26 cmdlet files importing Newtonsoft.Json were individually verified to use it only for attributes or internal deserialization, with no third-party types flowing to WriteObject.

SharpCompress usage in OvfMetadata.cs is fully confined to a private static method with no type leakage.

Informational — Test File Findings

File Matches Classification
tests/PSProxmoxVE.Core.Tests/Models/NodeModelTests.cs 8 Expected/legitimate — JObject.Parse() for fixture construction
tests/PSProxmoxVE.Core.Tests/Models/StorageModelTests.cs 12 Expected/legitimate — JObject.Parse() for fixture construction
tests/PSProxmoxVE.Core.Tests/Models/FirewallModelTests.cs 22 Expected/legitimate — JObject.Parse() for fixture construction
tests/PSProxmoxVE.Core.Tests/Models/SdnModelTests.cs 20 Expected/legitimate — JObject.Parse() for fixture construction
tests/PSProxmoxVE.Core.Tests/Models/BackupModelTests.cs 9 Expected/legitimate — JObject.Parse() for fixture construction
tests/PSProxmoxVE.Core.Tests/Models/ContainerModelTests.cs 11 Expected/legitimate — JObject.Parse() for fixture construction
tests/PSProxmoxVE.Core.Tests/Models/ClusterModelTests.cs 12 Expected/legitimate — JObject.Parse() for fixture construction
tests/PSProxmoxVE.Core.Tests/Models/VmModelTests.cs 14 Expected/legitimate — JObject.Parse() for fixture construction
tests/PSProxmoxVE.Core.Tests/Models/UserModelTests.cs 13 Expected/legitimate — JObject.Parse() for fixture construction
tests/PSProxmoxVE.Core.Tests/Models/NetworkModelTests.cs 9 Expected/legitimate — JObject.Parse() for fixture construction
tests/PSProxmoxVE.Core.Tests/Models/TaskModelTests.cs 8 Expected/legitimate — JObject.Parse() for fixture construction
tests/PSProxmoxVE.Core.Tests/Models/SnapshotModelTests.cs 9 Expected/legitimate — JObject.Parse() for fixture construction

All test file J* usage is legitimate: JObject.Parse(json)["data"] to extract fixture data for deserialization tests. No tests assert against third-party type properties on cmdlet output. No SharpCompress references in test files.

Remediation Guidance

F085 — PveClusterJoinInfo model property violations

Replace JArray and JObject properties with native types and add [JsonConverter] attributes:

Before:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class PveClusterJoinInfo
{
    [JsonProperty("nodelist")]
    public JArray? Nodelist { get; set; }

    [JsonProperty("totem")]
    public JObject? Totem { get; set; }
}

After:

using System.Collections.Generic;
using Newtonsoft.Json;
using PSProxmoxVE.Core.Utilities;

public class PveClusterJoinInfo
{
    [JsonProperty("nodelist")]
    [JsonConverter(typeof(NativeListConverter))]
    public List<Dictionary<string, object?>>? Nodelist { get; set; }

    [JsonProperty("totem")]
    [JsonConverter(typeof(NativeDictionaryConverter))]
    public Dictionary<string, object?>? Totem { get; set; }
}

The ToString() override needs no change — List<T>.Count works identically to JArray.Count.

No changes needed to GetPveClusterJoinInfoCmdlet or ClusterConfigService.GetJoinInfo() — the fix is entirely in the model class.

Notes

  • F049 decisions_ref was corrected from D013 to D012 prior to this scan (F049 is about magic string constants, not type emission).
  • F085 was created during D013-scan-1 and confirmed still open during D013-scan-2 (this scan).
  • No files require manual review — all ambiguous cases resolved to Clean.