KeelMatrix.NuGetReady 0.1.0

Prefix Reserved
dotnet tool install --global KeelMatrix.NuGetReady --version 0.1.0
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local KeelMatrix.NuGetReady --version 0.1.0
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=KeelMatrix.NuGetReady&version=0.1.0
                    
nuke :add-package KeelMatrix.NuGetReady --version 0.1.0
                    

KeelMatrix.NuGetReady

NuGetReady is a .NET tool that checks the exact NuGet artifacts you built and rehearses isolated consumer restore, build, execution, or tool installation before publication.

Generated library consumers use an isolated SDK/import boundary: ambient Directory.Build.*, CustomBeforeMicrosoftCommonTargets, CustomAfterMicrosoftCommonTargets, and user-extension imports are excluded without disabling the package build assets under test. Public cancellation is error/exit code 2; JSON reports use status: error and exitCode: 2, mark consumer-rehearsal as error, mark downstream checks not-run, and do not emit telemetry.

The pack-time sensitive-input guard applies the same protected filename and family rules to source and destination identities. It ignores only bin/obj container segments when evaluating generated source provenance, so generated assemblies and tool metadata remain packable while generated obj/credentials.json, obj/.env, linked inputs, renamed inputs, and wildcard-selected sensitive files remain rejected before an archive is emitted.

Before inspection, the artifact tree is bounded and checked for reparse-point ancestors or containment escapes. The accepted root and every traversed ancestor remain pinned while enumeration, attribute inspection, archive opening, hashing, snapshot copying, and final verification use handle-relative operations; a root or ancestor rebind fails closed before outside-root bytes are read. Counted archives are copied into one bounded temporary snapshot for archive, dependency, feed, consumer, and provenance checks; the original tree is verified again afterward. Generated consumers disable ambient Directory.Build.* imports.

Install

dotnet tool install --global KeelMatrix.NuGetReady

Support and Requirements

NuGetReady runs on Windows, Linux, and macOS. The installed tool targets net8.0 and requires the .NET 8 runtime. Consumer rehearsal also requires a compatible .NET SDK for restore, build, and tool installation; unavailable SDKs, runtimes, target packs, or workloads are error/exit code 2. Tool smoke execution uses a private content-bound launch image on every supported host: Windows additionally holds the copied entries with replacement-blocking sharing, while Linux and macOS revalidate the copied payload immediately before process creation. A launch-image mutation or unproven process lifecycle is error/exit code 2; a successful smoke run executes the bytes that passed provenance verification.

The supported matrix is explicit: net5.0 and later unqualified modern .NET targets run on the host; Windows-specific modern targets run only on Windows; .NET Standard targets are build-only; and .NET Framework targets such as net48 and net481 are build-only on Windows. Other or platform-incompatible targets are unsupported infrastructure (error/exit code 2). Build-only validation proves compilation and package consumption, not execution.

Quick Start

After dotnet pack, run:

nugetready check --artifacts ./artifacts/packages

The default configuration is nugetready.json in the current directory. It declares each package ID, kind, version, exact primary .nupkg, optional .snupkg, and tool smoke command. A tool command is one non-reserved executable basename without separators, roots, drive-relative forms, dot segments, or Windows device names; Windows accepts an optional .exe suffix. The resolved executable must be a direct child of the isolated tool directory and match the installed tool metadata. The complete installed tool directory is copied into a private content-bound launch image on every host and revalidated immediately before process creation; Windows also holds its entries with replacement-blocking sharing. An optional workflowPolicy.expectedNuGetUsername requires one configured literal publisher username; otherwise the checker accepts any non-empty literal NuGet/login@v1 username. NuGetReady rejects missing, extra, ambiguous, or filename/version-mismatched artifacts, inspects their metadata and layout, and rehearses them through an isolated local feed and fresh package caches. Reports use the stable states pass, warn, fail, error, not-run, and not-applicable; a blocked check never appears as pass. Workflow input is parsed before release relevance filtering, so malformed or incomplete YAML produces error/exit 2 with a safe relative workflow location; disappearance of a pinned workflow-policy node between snapshot and inspection also produces a blocking error/exit 2, never not-applicable. not-applicable means successfully inspected input was proven unrelated.

The outer artifact tree is bounded to 4,096 entries, 32 directory levels, 4,096 path characters, 256 archives, and 1 GiB of aggregate compressed archive bytes; reparse-point ancestors and containment escapes are rejected. Archive inspection is then bounded to 4,096 entries, 32 MiB expanded per entry, and 256 MiB expanded in aggregate. Limits are enforced while reading and package provenance is compared using streaming operations. Workflow-policy inspection also uses a pinned repository snapshot and descriptor-relative reads; disappearance of a pinned node, reparse points, and root, ancestor, or leaf rebinding fail closed without reading outside content. This is resource protection for inspection, not a malware sandbox.

Supported Workflow Profile

Workflow-policy pass applies only to the documented closed-world release profile. The triggering tag must be the exact literal v plus the configured version, and the configured artifact filenames, packed nuspec identity, immutable validated artifact, and exact primary package selected for publication must all carry that same identity. The checker evaluates jobs with publication operations or recognized credential capability and every dependency or artifact producer that can influence them. A static tag filter alone does not create publication reachability; a reachable publishing workflow must still use the exact release tag. Credential capability includes root secrets context references inside GitHub expressions; reusable-workflow secrets bindings; complete recognized members of vars.*, inputs.*, and env.*; and recognized keys in workflow/job/step env or action/reusable-workflow with maps. For the bounded names NUGET_API_KEY, API_KEY, ACCESS_TOKEN, AUTHORIZATION, PASSWORD, SECRET, and CREDENTIAL, every non-alphanumeric character is removed and the remaining token is compared case-insensitively by exact equality. Prefixes and suffixes such as ApiKeyPath remain outside. A vars, inputs, or env member selector that is not a complete static member name is unresolvable and enters the capability boundary; unknown behavior there blocks as unsupported/unproven. The bounded expression-evaluated grammar follows GitHub Actions' Context availability table: workflow run-name, concurrency, and env values; reusable-workflow input defaults and output values; job name, concurrency, container, continue-on-error, defaults.run, env, environment, if, outputs, runs-on, secrets, services, strategy, timeout-minutes, and reusable-workflow inputs; and step name, run, if, shell, working-directory, timeout-minutes, continue-on-error, env, and action inputs, including local composite-action steps. Every scalar leaf in those named mappings and objects is traversed. Incomplete framing in those fields blocks as error with exit code 2; non-evaluated literals such as workflow name, trigger filters, workflow-level defaults, and unrelated static configuration do not enter policy merely because they contain expression-like text. Ordinary step-based jobs apply workflow, job, and step environment overrides before evaluating each active step. Literal paths or prose containing secrets do not imply the context. The same unknown action in unrelated read-only CI without a recognized credential binding stays outside release policy; an unresolved executable run step enters the boundary and blocks as unsupported/unproven even with explicit read-only permissions.

Runtime environment identity follows the certified Ubuntu target: inheritance and overrides preserve case-sensitive names, and the supported bindings are exactly KEELMATRIX_NO_TELEMETRY, DOTNET_CLI_TELEMETRY_OPTOUT, NUGET_PACKAGES, and the publish-step NUGET_API_KEY where applicable. Credential-name normalization is a separate heuristic and does not establish a process binding. The supported producer, acquisition, and validator commands use a strict PowerShell token model that preserves command position, quote delimiters, literal argument bytes, empty arguments, and operators; quoted command heads, path whitespace, grouping, punctuation, escaping, and other unmodeled forms are rejected rather than normalized. Workflow input is parsed before release relevance filtering, so malformed YAML, duplicate keys, invalid roots, and multiple documents produce error/exit 2 with a safe relative workflow location; a pinned workflow-policy node that disappears between snapshot and inspection also produces a blocking error/exit 2, never not-applicable; not-applicable requires successfully inspected non-applicability.

See the canonical Supported Release Workflow Profile for the complete specification and fail-closed result mapping.

Only dotnetTool expectations may declare smoke arguments; arguments are bounded and embedded NUL characters are rejected before execution.

Package-Execution Safety

Consumer rehearsal is not a sandbox. Package code, build assets, and tool smoke commands may execute with the caller's permissions. Use trusted package inputs and an appropriate account. NuGetReady itself does not publish packages and its configuration contains no publishing credentials.

Privacy

NuGetReady requests shared activation and heartbeat signals only after a trustworthy completed rehearsal. Its call adds no rehearsal-specific event fields and supplies no package IDs, dependency names, raw repository URLs, package contents, source paths, workflow content, failure logs, or configuration content. Customer CI may count when process and repository opt-outs are unset. KeelMatrix.Telemetry owns opt-out resolution, identity, heartbeat cadence, and delivery; see PRIVACY.md for the product boundary and the shared privacy policy for the shared contract.

For configuration, check contracts, and troubleshooting, see the repository README. See PRIVACY.md for the data boundary and SECURITY.md for security reporting and the execution boundary.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
Version Downloads Last Updated
0.1.0 53 10/5/2026

Initial release of exact artifact validation and isolated consumer rehearsal.