ToolUp.ArtefactSigning 0.22.0

Prefix Reserved
dotnet add package ToolUp.ArtefactSigning --version 0.22.0
                    
NuGet\Install-Package ToolUp.ArtefactSigning -Version 0.22.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ToolUp.ArtefactSigning" Version="0.22.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ToolUp.ArtefactSigning" Version="0.22.0" />
                    
Directory.Packages.props
<PackageReference Include="ToolUp.ArtefactSigning" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ToolUp.ArtefactSigning --version 0.22.0
                    
#r "nuget: ToolUp.ArtefactSigning, 0.22.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ToolUp.ArtefactSigning@0.22.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ToolUp.ArtefactSigning&version=0.22.0
                    
Install as a Cake Addin
#tool nuget:?package=ToolUp.ArtefactSigning&version=0.22.0
                    
Install as a Cake Tool

ToolUp.ArtefactSigning

Cryptographic artefact-signing substrate for ToolUp.Platform (Phase 40). Produces tamper-evident detached-JWS signatures over arbitrary deployment artefacts — audit packs, exported reports, model documentation — using per-deployment ECDSA P-256 or Ed25519 signing keys, and exposes a public verification-key endpoint so a relying party can validate signatures independently.

Server-only companion. Off by default and zero-cost when unused (GP 13): nothing runs until you construct a signer.

Not the same as the Phase 30a IArtifactSigner (note spelling: "Artefact" here vs "Artifact" there). Phase 30a signs module- distribution artefacts against an ArtifactManifest for the marketplace publish/install trust path. This companion signs arbitrary byte payloads for compliance non-repudiation. Different namespace (ToolUp.ArtefactSigning), no type collision.

Quick start

open ToolUp.ArtefactSigning

// Compose against the SDK's ISecretStore + IAuditLog (already present in
// any ServerApp deployment). Auto-provisions a key on first use.
let signer   = DefaultArtefactSigner.createSystem secrets audit "signing-v1" EcdsaP256
let verifier = DefaultArtefactVerifier.create secrets

// Sign arbitrary bytes — the artefact is never embedded in the signature.
match! signer.Sign auditPackBytes with
| Ok signature ->
    // signature.DetachedJws : "base64url(header)..base64url(sig)"
    do! verifier.Verify(auditPackBytes, signature)   // Ok () | Error _
| Error e -> eprintfn "%s" (SigningError.describe e)

Public verification-key endpoint

Mount the anonymous route so verifying parties can fetch the public key (serves rotated-out keys too, for archival verification):

let app = choose [ SigningKeyHandler.routes; ...existing routes... ]
// GET /_platform/signing-key/{keyId}  ->  { keyId, alg, algorithm, pem, jwk }

Helpers

  • ArtefactSigning.signAndEmbed — sign + produce a sidecar .sig file.
  • ArtefactSigning.signedJsonEnvelope / verifyJsonEnvelope — wrap a JSON payload as { payload, signature } and round-trip it.
  • ArtefactSigning.signedPdfMetadata — sign PDF bytes + return the (key, value) metadata pair to embed via your PDF toolkit.

Keys & rotation

Key material lives in ISecretStore under scope _platform, key signing/{keyId}. The signer reads it per call (never caches), so rotating through the store takes effect immediately. To rotate: construct a signer with a new keyId; new signs use it, and old signatures keep verifying because the verifier resolves the public key by the signature's keyId (the rotated-out blob stays discoverable).

For keys that must never enter process memory, wire a KMS-backed signer (Phase 22a signing flavour) — the IArtefactSigner contract is identical.

Application signing seam

Everything above signs bytes, which is the right shape for a publish pipeline. An application signing its own payloads needs three further facts on each signature, and IApplicationSigner carries them:

let provider = ApplicationSigning.inProcess secrets audit "app-signing-v1" EcdsaP256 "system"
let! signer  = ApplicationSigning.createActivated "system" provider
ApplicationSigning.registerProvider services provider |> ignore   // DI, opt-in

let! envelope = signer.SignPayload("invoice.issued", payloadBytes)
let! result   = signer.VerifyPayload("invoice.issued", payloadBytes, envelope)
  • Purpose binding. The signature covers a versioned, length-prefixed framing of (purpose, level, payload), so a signature minted for one use cannot be replayed as another, and relabelling the envelope breaks it.
  • Attestation level. Attribution (the key is reachable from the signing process) or IsolatedSigner (the key is held outside it and never enters its memory), plus a Reserved case for future levels. The level is bound into the signed bytes, so it cannot be upgraded after the fact. Choose the provider that matches your custody: ApplicationSigning.inProcess or ApplicationSigning.keyManaged.
  • Key lifecycle as data. ISigningKeyLedger records activation, retirement and revocation as append-only attributable events. Retirement is rotation — earlier signatures keep verifying. Revocation is distrust and reaches backwards — every signature under a revoked key is refused, carrying the recorded reason. A key with no recorded history verifies on its bytes, so a deployment that records nothing behaves exactly as it did before (GP 11).

Nothing is composed by default. A deployment that never calls ApplicationSigning.* is unchanged and pays nothing (GP 13).

The provider set

Both entry points take substrate the deployment already composed, so the provider set is the cross-product of what is already shipped rather than a new family of packages:

Entry point Key custody Level
ApplicationSigning.inProcess any ISecretStore — a local/file-backed store in development, or one of the managed-store companions in production Attribution
ApplicationSigning.keyManaged one of the key-management-backed IArtefactSigner companions (ToolUp.ArtefactSigning.{AwsKms,AzureKeyVault,GoogleCloudKms}) IsolatedSigner

Hardening the store behind inProcess does not change its level: the level records whether the private key can reach process memory, and a key fetched from a hardened store to sign locally still can.

Every provider is certified against one executable conformance pack (ISigningProviderConformance in ToolUp.ArtefactSigning.Tests), which is itself probe-verified: deliberately broken providers are run through the same pack and it must reject each at the specific case that models its defect. Adopting the seam: docs/migrations/655-application-signing-seam.md.

Portability (GP 12)

IArtefactSigner / IArtefactVerifier satisfy the six portability rules: identity by value (KeyId : string, byte[] artefacts), async at every boundary, failures-as-data (Result<_, SigningError> / Result<_, VerificationError>), stateless between calls, no cross-shard ordering, no timing-precision boundary.

License

Apache-2.0.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on ToolUp.ArtefactSigning:

Package Downloads
ToolUp.ArtefactSigning.GoogleCloudKms

GCP Cloud KMS-backed IArtefactSigner for ToolUp.ArtefactSigning — EC-P256 (ES256, EC_SIGN_P256_SHA256) detached-JWS artefact signing where the private key never leaves GCP KMS (the signer hashes locally and calls AsymmetricSign over the digest). Server-only companion.

ToolUp.ArtefactSigning.AwsKms

AWS KMS-backed IArtefactSigner for ToolUp.ArtefactSigning — ECDSA P-256 detached-JWS artefact signing where the private key never leaves AWS KMS (the signer hashes locally and calls KMS Sign over the digest). Server-only companion.

ToolUp.Facts.Server

ToolUp.Facts Server — IFactStore (append-only, bitemporal, content-addressed fact base with derived supersession + AsOf reconstruction) + BlobFactStore default. Depends on ToolUp.Platform.Server + ToolUp.Facts.Core. Phase 520.

ToolUp.ArtefactSigning.AzureKeyVault

Azure Key Vault-backed IArtefactSigner for ToolUp.ArtefactSigning — EC-P256 (ES256) detached-JWS artefact signing where the private key never leaves Azure Key Vault (the signer hashes locally and calls Key Vault Sign over the digest). Server-only companion.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.22.0 38 8/27/2026
0.21.0 74 8/26/2026
0.20.1 135 8/20/2026
0.20.0 159 8/19/2026