External Dependencies¶
This document tracks the external NuGet packages used by DLLPickle and their update policies.
Runtime Baseline¶
DLLPickle now targets PowerShell 7.4+ with a single net8.0 runtime profile. Legacy Windows PowerShell 5.1 and .NET Framework dependency paths are no longer supported.
The automated fix (Import-DPLibrary / Import-DPBaseProfile) requires
PowerShell 7.4+ / .NET 8 because it depends on AssemblyLoadContext. The
inspection / diagnostic helpers (Find-DLLInPSModulePath,
Get-ModuleImportCandidate, Get-ModulesWithDependency,
Get-ModulesWithVersionSortedIdentityClient, Test-DPLibraryConflict) are
intentionally cross-edition — from a PowerShell 7.4+ session they still inspect
the current-user Windows PowerShell roots (for example
Documents\WindowsPowerShell\Modules), and when actually running on 5.1 they
also auto-seed the all-users WinPS root. That lets a Windows PowerShell 5.1
user still discover which module to load first and apply the conflict
workaround manually. See
Architecture.md §1.2 for the full platform-support
contract.
Purpose¶
DLLPickle deliberately maintains current Microsoft authentication and identity libraries to resolve DLL version conflicts in mixed-module PowerShell sessions. This is a core feature, not a bug: we want the newest compatible versions loaded first.
For usage guidance, see README.md and docs/index.md.
Dependency Management Strategy¶
Every tracked-dependency release is first checked for target-framework
alignment: it must restore, build, and pass tests on net8.0 under
--locked-mode, and ship a net8.0-consumable assembly asset (for example
net8.0, netstandard2.0, or netstandard2.1, as verified by
tools/Test-DLLPickleTfmAlignment.ps1). Only then does the severity of the
version jump decide how it ships:
| Update Type | Policy |
|---|---|
| Patch / Minor (x.Y.Z) | After the TFM-alignment + test gate, approve and merge with a detailed PR comment. Identity-library bumps are the module’s core deliverable, so they ship as a minor module release — Dependabot’s deps: commit is a recognized minor release prefix, so an auto-merged bump publishes a minor release on its own. |
| Major (X.y.z) | Still fully tested and TFM-verified, with the conflict surface re-adjudicated, but opened as a draft PR with fully detailed notes — not auto-merged and not auto-published. A maintainer promotes and merges it, publishing a major release (breaking:). |
| Upstream PowerShell module drift | Candidate PR or issue after the scheduled inventory + drift check. |
Publish note. A merged dependency PR publishes a new gallery version only when its commit also carries a release-worthy Conventional Commit prefix (see Versioning, below). Dependabot’s NuGet commits use the
deps:prefix, whichGet-VersionBump.ps1recognizes as a minor release prefix, so an auto-merged minor/patch bump publishes a minor release on its own. Major dependency PRs are converted to a reviewed draft with detailed notes (not auto-merged or auto-published) and merged carrying abreaking:prefix; an explicit TFM-alignment check (tools/Test-DLLPickleTfmAlignment.ps1) runs fail-closed in the candidate flow. See Architecture.md §8.2.
The automation that supports this: Dependabot opens NuGet update PRs; the
Dependabot-Auto-Approve workflow auto-approves and squash-merges patch/minor
updates (restricted to the exact DLLPickle.csproj / packages.lock.json
allow-list, and only after the Build gate, Validate upstream compatibility
tooling, and dependency-review required checks pass) and excludes major
updates from auto-merge, converting them to a reviewed draft PR with detailed
notes instead.
Versioning¶
DLLPickle follows Semantic Versioning (MAJOR.MINOR.PATCH).
Releases are cut automatically by the Release-and-Publish workflow, which
derives the bump solely from the Conventional Commit
prefixes of the commits since the last tag (see
../.github/ci-scripts/Get-VersionBump.ps1):
| Bump | Commit prefix |
|---|---|
MAJOR (X.y.z) |
BREAKING CHANGE:, breaking:, or major-release |
MINOR (x.Y.z) |
feat: (or minor:), and deps: (Dependabot’s NuGet bumps) |
PATCH (x.y.Z) |
fix:, perf:, refactor:, security:, or chore: |
The bump is decided by the commit prefix alone — there is no separate
detection of dependency or MSAL version changes. The automated MSAL /
identity-library bumps that are the module’s core purpose land as deps:
(Dependabot’s NuGet prefix), which Get-VersionBump.ps1 maps to a minor
release, so an auto-merged minor/patch bump produces a minor release on its own.
A bundled-library major jump is reviewed as a draft PR and merged carrying a
breaking: prefix. See Architecture.md §8.2 for the
full lifecycle.
A new PowerShell Gallery version is published only when a change affects the
published module bundle (src/DLLPickle/** or the bundled package set). CI-,
docs-, policy-, and tooling-only changes do not trigger a release. See
CHANGELOG.md for the released history.
Upstream Compatibility Automation¶
Dependabot tracks NuGet package releases, but DLLPickle also tracks the DLLs
bundled by upstream PowerShell modules. The scheduled Upstream Compatibility
workflow uses build/dependency-policy.json and tools under tools/ to
inventory latest PSGallery releases and propose safe candidate pin updates.
Monitored modules:
Microsoft.Graph.AuthenticationExchangeOnlineManagementAz.StorageAz.AccountsMicrosoftTeamsAz.Resources
Az.Resources is monitored explicitly because it is the observed collision
source for the #193 Microsoft.Extensions.* transitive-assembly conflict.
The workflow is fail-closed: it only opens a candidate PR after inventory, candidate generation, restore, build, and issue reproduction tests pass.
NuGet Package Dependencies¶
Version strategy in DLLPickle.csproj is major-locked floating (N.*); the
lock file pins the concrete resolved version.
| Package | Version Strategy | Notes |
|---|---|---|
Microsoft.Identity.Client |
4.* (major-locked float) |
Aligns base profile MSAL line |
Microsoft.Identity.Client.Broker |
4.* (major-locked float) |
Kept aligned with MSAL |
Microsoft.Identity.Client.Extensions.Msal |
4.* (major-locked float) |
Kept aligned with MSAL cache helper line |
Microsoft.Identity.Client.NativeInterop |
0.* (major-locked float) |
Includes native runtime files; tracks the broker requirement |
Microsoft.IdentityModel.Abstractions |
8.* |
Identity model support |
Microsoft.IdentityModel.Logging |
8.* |
Identity diagnostics/logging |
Microsoft.IdentityModel.JsonWebTokens |
8.* |
JWT handling |
Microsoft.IdentityModel.Tokens |
8.* |
Token validation/processing |
System.IdentityModel.Tokens.Jwt |
8.* |
JWT handlers |
Upstream package documentation¶
The libraries DLLPickle tracks for preloading are maintained and documented by their own code owners:
- Microsoft.Identity.Abstractions
- Microsoft.Identity.Client
- Microsoft.IdentityModel.Abstractions
- Microsoft.IdentityModel.JsonWebTokens
- Microsoft.IdentityModel.Logging
- Microsoft.IdentityModel.Tokens
- System.IdentityModel.Tokens.Jwt
Version Pinning Rationale¶
- The MSAL managed family (
Microsoft.Identity.Clientand friends) and the IdentityModel family use major-locked floating references (4.*,0.*,8.*) inDLLPickle.csproj: Dependabot can move the minor/patch within the major, but a major jump is a deliberate, reviewed change.packages.lock.jsonpins the concrete resolved version, so every build and restore (--locked-mode) is reproducible. This matters because mixed-module sessions can fail when one module binds to a lower, incompatible assembly. - Candidate pin updates are generated from upstream module inventories and still require full validation before publication.
Azure.Coreis intentionally not preloaded on the PowerShell 7.4+ (net8.0) profile. Az.Accounts 5.x isolates its Azure SDK stack in a privateAssemblyLoadContext; preloadingAzure.Coreinto the default load context splits the identity ofAzure.Core.TokenRequestContextacross load contexts and breaksConnect-AzAccountwith aMissingMethodExceptiononInteractiveBrowserCredential.AuthenticateAsync. Graph, Exchange, and Teams resolve a compatibleAzure.Corethemselves on .NET 8, so the preload is unnecessary.Azure.Coreremains report-only in policy for monitoring. The original net48-onlyAzure.Corepreload (#183) does not apply to the net8.0 baseline.- OData families remain report-only in policy because preloading them by default can break compatibility when upstream modules require different OData identities.
Lock File Workflow¶
- Restore in CI and local build runs in
--locked-mode. - When package references change in
src/DLLPickle.Build/DLLPickle.csproj, refresh the lock file:
- Commit the updated
src/DLLPickle.Build/packages.lock.jsonin the same change. - Validate lock consistency:
Supply Chain Security¶
Protections in place:
- Dependabot monitoring and update PRs
- Dependency Review checks
- OSSF Scorecard monitoring
- Package lock file for reproducible restore
- Automated build and test validation
- CODEOWNERS review gates
- Upstream compatibility inventory + candidate PR workflow
Manual review required for:
- Major version upgrades
- New package additions
- Changes to version strategy