diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 6d78352..b0c3e4b 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -7,6 +7,20 @@ "commands": [ "sign" ] + }, + "microsoft.sbom.dotnettool": { + "version": "4.1.5", + "commands": [ + "sbom-tool" + ], + "rollForward": true + }, + "cyclonedx": { + "version": "6.2.0", + "commands": [ + "dotnet-CycloneDX" + ], + "rollForward": true } } } diff --git a/.github/scripts/Assert-AssemblyStrongName.ps1 b/.github/scripts/Assert-AssemblyStrongName.ps1 new file mode 100644 index 0000000..0be5287 --- /dev/null +++ b/.github/scripts/Assert-AssemblyStrongName.ps1 @@ -0,0 +1,137 @@ +<# +.SYNOPSIS + Verifies that assemblies are strong-name signed with the approved Infragistics key. + +.DESCRIPTION + 'sn.exe -vf' proves only that an assembly's strong name is internally consistent, so any valid + private key passes it. This script additionally compares each assembly's public key against a + value pinned in the repository and established out of band from the signing key. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string[]]$Path, + + [Parameter(Mandatory)] + [string]$ExpectedPublicKeyPath, + + [string]$SnPath +) + +$ErrorActionPreference = 'Stop' +# Failures are aggregated per assembly, so sn.exe exit codes must not throw on their own. +$PSNativeCommandUseErrorActionPreference = $false + +function ConvertTo-HexString([byte[]]$Bytes) { + return (-join ($Bytes | ForEach-Object { $_.ToString('x2') })) +} + +if (-not (Test-Path -LiteralPath $ExpectedPublicKeyPath)) { + throw "Pinned public key file not found: $ExpectedPublicKeyPath" +} + +$hexLines = @( + Get-Content -LiteralPath $ExpectedPublicKeyPath | + ForEach-Object { $_.Trim() } | + Where-Object { $_ -and -not $_.StartsWith('#') } +) + +# A blank or malformed pin must fail loudly; otherwise the whole check silently becomes a no-op. +if ($hexLines.Count -ne 1) { + throw "$ExpectedPublicKeyPath must contain exactly one non-comment line, but contains $($hexLines.Count)." +} + +$expectedPublicKeyHex = $hexLines[0].ToLowerInvariant() +if ($expectedPublicKeyHex -notmatch '^[0-9a-f]{320,}$' -or $expectedPublicKeyHex.Length % 2 -ne 0) { + throw "$ExpectedPublicKeyPath does not hold a public key blob (expected an even number of at least 320 hex characters)." +} + +$expectedPublicKey = [byte[]]::new($expectedPublicKeyHex.Length / 2) +for ($index = 0; $index -lt $expectedPublicKey.Length; $index++) { + $expectedPublicKey[$index] = [Convert]::ToByte($expectedPublicKeyHex.Substring($index * 2, 2), 16) +} + +# SHA-1 is not a security choice here; it is the algorithm that defines a strong-name token. +$digest = [System.Security.Cryptography.SHA1]::Create().ComputeHash($expectedPublicKey) +$tokenBytes = $digest[-8..-1] +[array]::Reverse($tokenBytes) +$expectedToken = ConvertTo-HexString $tokenBytes + +if ($SnPath) { + if (-not (Test-Path -LiteralPath $SnPath -PathType Leaf)) { + throw "The specified sn.exe path does not exist: $SnPath" + } + + $strongNameTool = Get-Item -LiteralPath $SnPath +} +else { + $strongNameCommand = Get-Command sn.exe -CommandType Application -ErrorAction SilentlyContinue | + Select-Object -First 1 + + if ($null -ne $strongNameCommand) { + $strongNameTool = Get-Item -LiteralPath $strongNameCommand.Path + } + else { + $windowsSdkRoot = Join-Path ${env:ProgramFiles(x86)} 'Microsoft SDKs\Windows' + $strongNameTool = Get-ChildItem -Path $windowsSdkRoot -Filter 'sn.exe' -Recurse -ErrorAction SilentlyContinue | + Sort-Object -Property @{ + Expression = { + $match = [regex]::Match($_.FullName, '\\v(?\d+(?:\.\d+)*)A?\\', 'IgnoreCase') + if ($match.Success) { [version]$match.Groups['version'].Value } else { [version]'0.0' } + } + Descending = $true + }, @{ + Expression = { $_.FullName } + Descending = $true + } | + Select-Object -First 1 + } +} + +if ($null -eq $strongNameTool) { + throw 'Could not find sn.exe on PATH or under the Windows SDK directory. Pass -SnPath explicitly.' +} + +Write-Verbose "Using sn.exe from '$($strongNameTool.FullName)'." + +$assemblies = @(Get-ChildItem -Path $Path -Filter '*.dll' -Recurse -File) +if ($assemblies.Count -eq 0) { + throw "No assemblies were found under '$($Path -join ', ')'. Refusing to report success." +} + +$problems = @() +foreach ($assembly in $assemblies) { + $output = & $strongNameTool.FullName -vf $assembly.FullName + if ($LASTEXITCODE -ne 0) { + $problems += "$($assembly.FullName): strong-name verification failed. $(($output | Where-Object { $_ }) -join ' ')" + continue + } + + $assemblyName = [System.Reflection.AssemblyName]::GetAssemblyName($assembly.FullName) + $token = $assemblyName.GetPublicKeyToken() + if ($null -eq $token -or $token.Length -eq 0) { + $problems += "$($assembly.FullName): not strong named." + continue + } + + $actualToken = ConvertTo-HexString $token + if ($actualToken -ne $expectedToken) { + $problems += "$($assembly.FullName): public key token is $actualToken, expected $expectedToken." + continue + } + + # Best effort: the token is a truncated hash, so compare the whole key when it is available. + $publicKey = $assemblyName.GetPublicKey() + if ($null -ne $publicKey -and $publicKey.Length -gt 0) { + $actualPublicKey = ConvertTo-HexString $publicKey + if ($actualPublicKey -ne $expectedPublicKeyHex) { + $problems += "$($assembly.FullName): public key does not match $ExpectedPublicKeyPath despite a matching token." + } + } +} + +if ($problems.Count -gt 0) { + throw "Strong-name validation failed:`n$($problems -join "`n")" +} + +Write-Host "Verified $($assemblies.Count) assemblies against public key token $expectedToken." diff --git a/.github/scripts/Assert-AuthenticodeSignature.ps1 b/.github/scripts/Assert-AuthenticodeSignature.ps1 new file mode 100644 index 0000000..723c6ac --- /dev/null +++ b/.github/scripts/Assert-AuthenticodeSignature.ps1 @@ -0,0 +1,77 @@ +<# +.SYNOPSIS + Verifies that every assembly under the given path is Authenticode signed by an approved certificate. + +.DESCRIPTION + A valid Authenticode signature only proves that *someone* signed the file. This script additionally + requires the signer certificate's SHA-256 fingerprint to appear in a list pinned in the repository, + so a signature produced with any other certificate is rejected rather than trusted. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string[]]$Path, + + [Parameter(Mandatory)] + [string]$ExpectedCertificateSha256Path, + + [string]$SummaryPath = $env:GITHUB_STEP_SUMMARY +) + +$ErrorActionPreference = 'Stop' + +if (-not (Test-Path -LiteralPath $ExpectedCertificateSha256Path -PathType Leaf)) { + throw "Pinned certificate fingerprint file not found: $ExpectedCertificateSha256Path" +} + +$allowedFingerprints = @( + Get-Content -LiteralPath $ExpectedCertificateSha256Path | + ForEach-Object { $_.Trim().ToUpperInvariant() } | + Where-Object { $_ -and -not $_.StartsWith('#') } +) + +# A blank or malformed pin must fail loudly; otherwise the whole check silently becomes a no-op. +if ($allowedFingerprints.Count -eq 0 -or @($allowedFingerprints | Where-Object { $_ -notmatch '^[0-9A-F]{64}$' }).Count -gt 0) { + throw "$ExpectedCertificateSha256Path must contain at least one valid SHA-256 certificate fingerprint." +} + +$assemblies = @(Get-ChildItem -Path $Path -Filter '*.dll' -Recurse -File) +if ($assemblies.Count -eq 0) { + throw "No DLLs were found under '$($Path -join ', ')'. Refusing to report success." +} + +$problems = @() +$fingerprints = @{} +$signerNames = @{} +foreach ($assembly in $assemblies) { + $signature = Get-AuthenticodeSignature -LiteralPath $assembly.FullName + if ($signature.Status -ne 'Valid') { + $problems += "$($assembly.FullName): signature status $($signature.Status)." + continue + } + + $fingerprint = [Convert]::ToHexString( + [System.Security.Cryptography.SHA256]::HashData($signature.SignerCertificate.RawData) + ) + if ($fingerprint -notin $allowedFingerprints) { + $problems += "$($assembly.FullName): certificate SHA-256 fingerprint $fingerprint is not approved by '$ExpectedCertificateSha256Path'." + continue + } + + $fingerprints[$fingerprint] = $true + $signerNames[$signature.SignerCertificate.GetNameInfo('SimpleName', $false)] = $true +} + +if ($problems.Count -gt 0) { + throw "Authenticode validation failed:`n$($problems -join "`n")" +} + +Write-Host "All $($assemblies.Count) DLLs signed by an approved certificate." + +if ($SummaryPath) { + @( + '### Authenticode signer', + "- Subject CN: $($signerNames.Keys -join ', ')", + "- SHA-256 fingerprint: $($fingerprints.Keys -join ', ')" + ) | Add-Content -LiteralPath $SummaryPath +} diff --git a/.github/scripts/Assert-CycloneDxSbom.ps1 b/.github/scripts/Assert-CycloneDxSbom.ps1 new file mode 100644 index 0000000..99a5e02 --- /dev/null +++ b/.github/scripts/Assert-CycloneDxSbom.ps1 @@ -0,0 +1,66 @@ +<# +.SYNOPSIS + Verifies the merged CycloneDX document describes both the .NET and npm halves of the shipped package. + +.DESCRIPTION + Checks the structural fields actions/attest requires, and specifically that at least one nuget- and + one npm-ecosystem component are present. That is the concrete regression this guards against: a merge + failure that still produces a valid-looking, structurally sound, but incomplete document. License and + author coverage are reported as warnings only, same as the SPDX side - NOASSERTION/missing is a valid + value, not something this tool can require otherwise. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string]$BomPath, + + [ValidateRange(0, 1)] + [double]$MinimumLicenseCoverage = 0.9 +) + +$ErrorActionPreference = 'Stop' + +if (-not (Test-Path -LiteralPath $BomPath -PathType Leaf)) { + throw "CycloneDX document not found: $BomPath" +} + +$bom = Get-Content -LiteralPath $BomPath -Raw | ConvertFrom-Json + +# actions/attest only recognises a CycloneDX document that carries all three of these. +foreach ($required in 'bomFormat', 'specVersion', 'serialNumber') { + if (-not $bom.$required) { + throw "CycloneDX document is missing '$required', so it cannot be consumed as an SBOM predicate." + } +} + +$components = @($bom.components) +if ($components.Count -eq 0) { + throw 'CycloneDX document contains no components.' +} + +$nugetComponents = @($components | Where-Object { $_.purl -like 'pkg:nuget/*' }) +$npmComponents = @($components | Where-Object { $_.purl -like 'pkg:npm/*' }) + +if ($nugetComponents.Count -eq 0) { + throw 'Merged CycloneDX document contains no pkg:nuget components; the .NET BOM appears to be missing from the merge.' +} +if ($npmComponents.Count -eq 0) { + throw 'Merged CycloneDX document contains no pkg:npm components; the npm BOM appears to be missing from the merge.' +} + +$licensed = @($components | Where-Object { $_.licenses }) +# CycloneDX models 'authors' (people) and 'supplier' (an organisation) separately; cyclonedx-dotnet only +# ever populates the former, so this is reported as author coverage. +$authored = @($components | Where-Object { $_.authors }) +$coverage = $licensed.Count / $components.Count + +Write-Host "CycloneDX $($bom.specVersion): $($components.Count) components ($($nugetComponents.Count) NuGet, $($npmComponents.Count) npm), $($licensed.Count) licensed, $($authored.Count) with an author." + +if ($coverage -lt $MinimumLicenseCoverage) { + $unlicensed = @($components | Where-Object { -not $_.licenses } | ForEach-Object { "$($_.name)@$($_.version)" }) + Write-Warning "Only $([math]::Round($coverage * 100))% of components carry a licence (threshold $([math]::Round($MinimumLicenseCoverage * 100))%). Unresolved: $($unlicensed -join ', ')" +} + +$checksum = (Get-FileHash -LiteralPath $BomPath -Algorithm SHA256).Hash.ToLowerInvariant() +Set-Content -LiteralPath "$BomPath.sha256" -Value $checksum -NoNewline +Write-Host "Wrote checksum sidecar $BomPath.sha256." diff --git a/.github/scripts/Assert-NuGetSignature.ps1 b/.github/scripts/Assert-NuGetSignature.ps1 new file mode 100644 index 0000000..1647a0c --- /dev/null +++ b/.github/scripts/Assert-NuGetSignature.ps1 @@ -0,0 +1,46 @@ +<# +.SYNOPSIS + Verifies that a NuGet package is signed by an approved certificate. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string]$PackagePath, + + [Parameter(Mandatory)] + [string]$ExpectedCertificateSha256Path +) + +$ErrorActionPreference = 'Stop' +$PSNativeCommandUseErrorActionPreference = $false + +if (-not (Test-Path -LiteralPath $PackagePath -PathType Leaf)) { + throw "NuGet package not found: $PackagePath" +} + +if (-not (Test-Path -LiteralPath $ExpectedCertificateSha256Path -PathType Leaf)) { + throw "Pinned certificate fingerprint file not found: $ExpectedCertificateSha256Path" +} + +$allowedFingerprints = @( + Get-Content -LiteralPath $ExpectedCertificateSha256Path | + ForEach-Object { $_.Trim().ToUpperInvariant() } | + Where-Object { $_ -and -not $_.StartsWith('#') } +) + +if ($allowedFingerprints.Count -eq 0 -or @($allowedFingerprints | Where-Object { $_ -notmatch '^[0-9A-F]{64}$' }).Count -gt 0) { + throw "$ExpectedCertificateSha256Path must contain at least one valid SHA-256 certificate fingerprint." +} + +$verifyArguments = @('nuget', 'verify', $PackagePath, '--all') +foreach ($fingerprint in $allowedFingerprints) { + $verifyArguments += @('--certificate-fingerprint', $fingerprint) +} +$verifyArguments += @('--verbosity', 'quiet') + +& dotnet @verifyArguments +if ($LASTEXITCODE -ne 0) { + throw "NuGet signature validation failed or the signer is not approved by '$ExpectedCertificateSha256Path'." +} + +Write-Host "NuGet package signature matches an approved certificate." diff --git a/.github/scripts/Assert-PackageSignatures.ps1 b/.github/scripts/Assert-PackageSignatures.ps1 new file mode 100644 index 0000000..68e66e8 --- /dev/null +++ b/.github/scripts/Assert-PackageSignatures.ps1 @@ -0,0 +1,46 @@ +<# +.SYNOPSIS + Verifies the strong-name and Authenticode signatures of the assemblies inside a packed NuGet package. + +.DESCRIPTION + Packing does not sign or rebuild; -no-build just re-zips whatever bin/ output is on disk. The prior + jobs validate that loose output directly, but that is not proof the packed nupkg contains those exact + bytes. This extracts the package that will actually ship and re-runs both checks against those bytes + in a single extraction, so a pack step that picked up a stale or substituted DLL is caught either way, + not just on the weaker (SHA-1 strong-name) signal. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string]$PackagePath, + + [Parameter(Mandatory)] + [string]$ExpectedPublicKeyPath, + + [Parameter(Mandatory)] + [string]$ExpectedCertificateSha256Path, + + [string]$WorkingDirectory = (Join-Path ([System.IO.Path]::GetTempPath()) 'package-signature-validation') +) + +$ErrorActionPreference = 'Stop' + +if (-not (Test-Path -LiteralPath $PackagePath -PathType Leaf)) { + throw "NuGet package not found: $PackagePath" +} + +$extractPath = Join-Path $WorkingDirectory 'package' +# Expand-Archive only accepts .zip, so the package is copied under a name it will open. +$archivePath = Join-Path $WorkingDirectory 'package.zip' + +try { + New-Item -ItemType Directory -Path $WorkingDirectory -Force | Out-Null + Copy-Item -LiteralPath $PackagePath -Destination $archivePath -Force + Expand-Archive -LiteralPath $archivePath -DestinationPath $extractPath -Force + + & (Join-Path $PSScriptRoot 'Assert-AssemblyStrongName.ps1') -Path $extractPath -ExpectedPublicKeyPath $ExpectedPublicKeyPath + & (Join-Path $PSScriptRoot 'Assert-AuthenticodeSignature.ps1') -Path $extractPath -ExpectedCertificateSha256Path $ExpectedCertificateSha256Path +} +finally { + Remove-Item -LiteralPath $WorkingDirectory -Recurse -Force -ErrorAction SilentlyContinue +} diff --git a/.github/scripts/Assert-Sbom.ps1 b/.github/scripts/Assert-Sbom.ps1 new file mode 100644 index 0000000..fec3784 --- /dev/null +++ b/.github/scripts/Assert-Sbom.ps1 @@ -0,0 +1,167 @@ +<# +.SYNOPSIS + Verifies the generated SPDX 2.2 and 3.0 manifests and their relationship to the shipped package. + +.DESCRIPTION + Requires parseable, structurally valid documents, verifies each manifest against its SHA-256 sidecar, + and proves that the SPDX 2.2 file entry describes the exact package bytes being released. + + Also guards the two failure modes sbom-tool does not report: a manifest that ended up inside the + component scan root and so describes itself, and a ClearlyDefined outage that silently replaces every + license with NOASSERTION. Missing licenses are reported rather than fatal - NOASSERTION is a valid + SPDX value and the upstream tool offers no way to require otherwise. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string]$OutputRoot, + + [Parameter(Mandatory)] + [string]$ExpectedPackagePath, + + # Below this share of packages carrying a resolved license, the run is annotated rather than failed. + [ValidateRange(0, 1)] + [double]$MinimumLicenseCoverage = 0.8 +) + +$ErrorActionPreference = 'Stop' + +$manifests = @( + [pscustomobject]@{ + Name = 'SPDX 2.2' + Path = Join-Path $OutputRoot '_manifest/spdx_2.2/manifest.spdx.json' + }, + [pscustomobject]@{ + Name = 'SPDX 3.0' + Path = Join-Path $OutputRoot '_manifest/spdx_3.0/manifest.spdx.json' + } +) + +$problems = @() +$documents = @{} +foreach ($manifest in $manifests) { + if (-not (Test-Path -LiteralPath $manifest.Path -PathType Leaf)) { + $problems += "$($manifest.Name) document missing: $($manifest.Path)" + continue + } + + if ((Get-Item -LiteralPath $manifest.Path).Length -eq 0) { + $problems += "$($manifest.Name) document is empty: $($manifest.Path)" + continue + } + + try { + $documents[$manifest.Name] = Get-Content -LiteralPath $manifest.Path -Raw | ConvertFrom-Json -ErrorAction Stop + } + catch { + $problems += "$($manifest.Name) document is not valid JSON: $($_.Exception.Message)" + } + + $checksumPath = "$($manifest.Path).sha256" + if (-not (Test-Path -LiteralPath $checksumPath -PathType Leaf)) { + $problems += "$($manifest.Name) checksum missing: $checksumPath" + continue + } + + $recordedChecksum = (Get-Content -LiteralPath $checksumPath -Raw).Trim().ToLowerInvariant() + if ($recordedChecksum -notmatch '^[0-9a-f]{64}$') { + $problems += "$($manifest.Name) checksum sidecar does not contain one SHA-256 digest: $checksumPath" + continue + } + + $actualChecksum = (Get-FileHash -LiteralPath $manifest.Path -Algorithm SHA256).Hash.ToLowerInvariant() + if ($recordedChecksum -ne $actualChecksum) { + $problems += "$($manifest.Name) checksum is $recordedChecksum, but the document hash is $actualChecksum." + } +} + +if ($documents.ContainsKey('SPDX 2.2')) { + $spdx22 = $documents['SPDX 2.2'] + if ($spdx22.spdxVersion -ne 'SPDX-2.2') { + $problems += "SPDX 2.2 document declares version '$($spdx22.spdxVersion)'." + } + if (@($spdx22.packages).Count -eq 0) { + $problems += 'SPDX 2.2 document contains no packages.' + } + if (@($spdx22.files).Count -eq 0) { + $problems += 'SPDX 2.2 document contains no files.' + } +} + +if ($documents.ContainsKey('SPDX 3.0')) { + $spdx30 = $documents['SPDX 3.0'] + if (@($spdx30.'@context').Count -eq 0) { + $problems += 'SPDX 3.0 document contains no @context.' + } + if (@($spdx30.'@graph').Count -eq 0) { + $problems += 'SPDX 3.0 document contains no @graph entries.' + } +} + +if ($documents.ContainsKey('SPDX 2.2') -and $documents.ContainsKey('SPDX 3.0')) { + $graph = @($documents['SPDX 3.0'].'@graph') + + # Either document describing an SBOM manifest means the output landed inside the scanned tree. + $selfReferences = @( + @($documents['SPDX 2.2'].files | Where-Object { $_.fileName -like '*manifest.spdx.json' }) + + @($graph | Where-Object { $_.type -eq 'software_File' -and $_.name -like '*manifest.spdx.json' }) + ) + if ($selfReferences.Count -gt 0) { + $problems += "The SBOMs describe $($selfReferences.Count) SBOM manifest file(s) as build content. Generate them outside the component scan root." + } + + $packages22 = @($documents['SPDX 2.2'].packages).Count + $packages30 = @($graph | Where-Object { $_.type -eq 'software_Package' }).Count + if ($packages22 -ne $packages30) { + $problems += "SPDX 2.2 records $packages22 packages but SPDX 3.0 records $packages30. The two formats must describe the same build." + } +} + +if (-not (Test-Path -LiteralPath $ExpectedPackagePath -PathType Leaf)) { + $problems += "Expected NuGet package missing: $ExpectedPackagePath" +} +elseif ($documents.ContainsKey('SPDX 2.2')) { + $expectedFileName = [System.IO.Path]::GetFileName($ExpectedPackagePath) + $expectedPackageHash = (Get-FileHash -LiteralPath $ExpectedPackagePath -Algorithm SHA256).Hash.ToLowerInvariant() + $packageFiles = @( + $documents['SPDX 2.2'].files | Where-Object { + $_.fileName -and [System.IO.Path]::GetFileName([string]$_.fileName) -eq $expectedFileName + } + ) + + if ($packageFiles.Count -ne 1) { + $problems += "SPDX 2.2 document contains $($packageFiles.Count) file entries for $expectedFileName; expected exactly one." + } + else { + $recordedPackageHashes = @( + $packageFiles[0].checksums | + Where-Object { $_.algorithm -eq 'SHA256' } | + ForEach-Object { ([string]$_.checksumValue).ToLowerInvariant() } + ) + + if ($expectedPackageHash -notin $recordedPackageHashes) { + $problems += "SPDX 2.2 records SHA-256 '$($recordedPackageHashes -join ', ')' for $expectedFileName, but the package hash is $expectedPackageHash." + } + } +} + +if ($problems.Count -gt 0) { + throw "SBOM validation failed:`n- $($problems -join "`n- ")" +} + +$packages = @($documents['SPDX 2.2'].packages) +$licensed = @($packages | Where-Object { $_.licenseConcluded -and $_.licenseConcluded -ne 'NOASSERTION' }) +$coverage = if ($packages.Count -gt 0) { $licensed.Count / $packages.Count } else { 0 } + +Write-Host "SBOM covers $($packages.Count) packages and $(@($documents['SPDX 2.2'].files).Count) files, including the verified NuGet package." +Write-Host "License coverage: $($licensed.Count) of $($packages.Count) packages ($([math]::Round($coverage * 100))%)." + +if ($coverage -lt $MinimumLicenseCoverage) { + $unlicensed = @($packages | Where-Object { -not $_.licenseConcluded -or $_.licenseConcluded -eq 'NOASSERTION' } | ForEach-Object { "$($_.name)@$($_.versionInfo)" }) + Write-Warning "Only $([math]::Round($coverage * 100))% of packages carry a resolved license (threshold $([math]::Round($MinimumLicenseCoverage * 100))%). Unresolved: $($unlicensed -join ', ')" +} + +$reciprocal = @($packages | Where-Object { $_.licenseConcluded -match 'GPL|RPL|MPL|EPL|CDDL|OSL|SSPL' }) +if ($reciprocal.Count -gt 0) { + Write-Warning "Reciprocal or copyleft licenses detected: $(($reciprocal | ForEach-Object { "$($_.name)@$($_.versionInfo) ($($_.licenseConcluded))" }) -join '; ')" +} diff --git a/.github/scripts/Copy-AttestationBundles.ps1 b/.github/scripts/Copy-AttestationBundles.ps1 new file mode 100644 index 0000000..5209209 --- /dev/null +++ b/.github/scripts/Copy-AttestationBundles.ps1 @@ -0,0 +1,49 @@ +<# +.SYNOPSIS + Copies the provenance and SBOM attestation bundles next to the SBOM documents and records their URLs. + +.DESCRIPTION + actions/attest writes each bundle to a temporary path that only the producing job can read, so the + bundles are collected into the release artifact while they are still reachable. + + The two SBOM attestations carry different predicate types - https://spdx.dev/Document and + https://cyclonedx.org/bom - so a verifier can ask for either without ambiguity. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string]$ProvenanceBundlePath, + + [Parameter(Mandatory)] + [string]$SpdxBundlePath, + + [Parameter(Mandatory)] + [string]$CycloneDxBundlePath, + + [Parameter(Mandatory)] + [string]$Destination, + + [string]$ProvenanceUrl, + + [string]$SpdxUrl, + + [string]$CycloneDxUrl, + + [string]$SummaryPath = $env:GITHUB_STEP_SUMMARY +) + +$ErrorActionPreference = 'Stop' + +New-Item -ItemType Directory -Path $Destination -Force | Out-Null +Copy-Item -LiteralPath $ProvenanceBundlePath -Destination (Join-Path $Destination 'provenance.sigstore.json') -Force +Copy-Item -LiteralPath $SpdxBundlePath -Destination (Join-Path $Destination 'sbom-spdx.sigstore.json') -Force +Copy-Item -LiteralPath $CycloneDxBundlePath -Destination (Join-Path $Destination 'sbom-cyclonedx.sigstore.json') -Force + +if ($SummaryPath) { + @( + '### Attestations', + "- Provenance: $ProvenanceUrl", + "- SBOM (SPDX 2.2): $SpdxUrl", + "- SBOM (CycloneDX): $CycloneDxUrl" + ) | Add-Content -LiteralPath $SummaryPath +} diff --git a/.github/scripts/Get-PackageDigest.ps1 b/.github/scripts/Get-PackageDigest.ps1 new file mode 100644 index 0000000..e1dd126 --- /dev/null +++ b/.github/scripts/Get-PackageDigest.ps1 @@ -0,0 +1,59 @@ +<# +.SYNOPSIS + Computes a package's SHA-256 digest and, optionally, asserts it against digests recorded earlier. + +.DESCRIPTION + The digest is the identity every downstream job re-checks before acting on the package, so that a + job cannot pack, attest or publish bytes other than the ones that were signed. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string]$PackagePath, + + # Every value must match the computed digest. Empty entries are ignored so a caller can pass + # job outputs directly without branching on which of them are set. + [string[]]$ExpectedSha256 = @(), + + [string]$FailureMessage = 'Package digest changed between jobs.', + + # Writes ' ' next to the package, in the format sha256sum expects. + [switch]$WriteChecksumFile, + + [string]$GitHubOutputName, + + [string]$SummaryTitle, + + [string]$GitHubOutputPath = $env:GITHUB_OUTPUT, + + [string]$SummaryPath = $env:GITHUB_STEP_SUMMARY +) + +$ErrorActionPreference = 'Stop' + +if (-not (Test-Path -LiteralPath $PackagePath -PathType Leaf)) { + throw "NuGet package not found: $PackagePath" +} + +$name = [System.IO.Path]::GetFileName($PackagePath) +$digest = (Get-FileHash -LiteralPath $PackagePath -Algorithm SHA256).Hash.ToLowerInvariant() + +foreach ($expected in @($ExpectedSha256 | Where-Object { $_ })) { + if ($digest -ne $expected.Trim().ToLowerInvariant()) { + throw "$FailureMessage Expected $expected but found $digest for $name." + } +} + +if ($WriteChecksumFile) { + "$digest $name" | Set-Content -LiteralPath "$PackagePath.sha256" -Encoding ascii +} + +if ($GitHubOutputName -and $GitHubOutputPath) { + "$GitHubOutputName=$digest" | Add-Content -LiteralPath $GitHubOutputPath +} + +if ($SummaryTitle -and $SummaryPath) { + @("### $SummaryTitle", '```', "$digest $name", '```') | Add-Content -LiteralPath $SummaryPath +} + +Write-Host "Verified $name with digest $digest." diff --git a/.github/scripts/Invoke-DependencyScan.ps1 b/.github/scripts/Invoke-DependencyScan.ps1 new file mode 100644 index 0000000..abeb760 --- /dev/null +++ b/.github/scripts/Invoke-DependencyScan.ps1 @@ -0,0 +1,107 @@ +<# +.SYNOPSIS + Records the known vulnerabilities in the dependencies the package ships. + +.DESCRIPTION + Advisory by design. A finding is annotated and attached to the release as evidence but never holds + up the publish; the blocking gate for newly introduced vulnerable dependencies is a PR-time + dependency-review check. A scan that fails to run, however, is an error: silence must not be + mistaken for a clean result. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string]$ProjectPath, + + [Parameter(Mandatory)] + [string]$OutputDirectory, + + [string]$PackageId, + + [string]$Version, + + [string]$SummaryPath = $env:GITHUB_STEP_SUMMARY +) + +$ErrorActionPreference = 'Stop' +# The scan's exit code is inspected explicitly so a failure can be reported with context. +$PSNativeCommandUseErrorActionPreference = $false + +New-Item -ItemType Directory -Path $OutputDirectory -Force | Out-Null +$reportPath = Join-Path $OutputDirectory 'nuget-vulnerable.json' + +dotnet restore $ProjectPath | Out-Null +if ($LASTEXITCODE -ne 0) { + throw "dotnet restore failed for $ProjectPath with exit code $LASTEXITCODE." +} + +dotnet list $ProjectPath package --vulnerable --include-transitive --format json --output-version 1 | + Set-Content -LiteralPath $reportPath -Encoding utf8 +if ($LASTEXITCODE -ne 0) { + throw "dotnet list package --vulnerable failed with exit code $LASTEXITCODE." +} + +$report = Get-Content -LiteralPath $reportPath -Raw | ConvertFrom-Json +if ($report.version -ne 1 -or -not $report.projects) { + throw 'dotnet list package did not produce a valid version 1 JSON report.' +} + +$findings = @( + foreach ($project in $report.projects) { + # A framework with no findings omits the package arrays entirely, so null entries are dropped. + foreach ($framework in @($project.frameworks | Where-Object { $_ })) { + $packages = @($framework.topLevelPackages) + @($framework.transitivePackages) + foreach ($package in @($packages | Where-Object { $_ })) { + foreach ($vulnerability in @($package.vulnerabilities | Where-Object { $_ })) { + [pscustomobject]@{ + Framework = $framework.framework + Package = $package.id + Resolved = $package.resolvedVersion + Severity = $vulnerability.severity + AdvisoryUrl = $vulnerability.advisoryurl + } + } + } + } + } +) + +$table = if ($findings.Count -gt 0) { + $findings | Sort-Object Severity, Package, Framework | Format-Table -AutoSize | Out-String -Width 200 +} +else { + 'No vulnerable shipped dependencies reported.' +} + +$table | Set-Content -LiteralPath (Join-Path $OutputDirectory 'nuget-vulnerable.txt') -Encoding utf8 +Write-Host $table + +if (-not $SummaryPath) { + return +} + +$summary = @( + '### Dependency vulnerability scan' + '' + 'Advisory only - findings are recorded but do not block this release.' + '' + '
dotnet list package --vulnerable --include-transitive' + '' + '```' + $table.TrimEnd() + '```' + '' + '
' + '' +) + +if ($findings.Count -gt 0) { + $label = "$PackageId $Version".Trim() + Write-Host "::warning title=Vulnerable dependencies reported::$label was released with $($findings.Count) dependency advisories outstanding. See the run summary and the dependency-scan release asset." + $summary += "> [!WARNING]`n> $($findings.Count) vulnerable dependencies were reported for this release. Review the scan output above and open a servicing issue if a fix is required." +} +else { + $summary += '> [!NOTE]`n> No vulnerable shipped dependencies reported.' +} + +$summary | Add-Content -LiteralPath $SummaryPath diff --git a/.github/scripts/Merge-CycloneDxSbom.ps1 b/.github/scripts/Merge-CycloneDxSbom.ps1 new file mode 100644 index 0000000..2b1391f --- /dev/null +++ b/.github/scripts/Merge-CycloneDxSbom.ps1 @@ -0,0 +1,122 @@ +<# +.SYNOPSIS + Merges the .NET and npm CycloneDX SBOMs into the single document that gets checksummed and attested. + +.DESCRIPTION + There is no dependency-manager-distributed tool that merges two already-generated CycloneDX + documents: cyclonedx-cli (the only tool with a merge command) ships as GitHub-release binaries only, + and @cyclonedx/cyclonedx-library can serialize model objects to JSON but cannot deserialize existing + CycloneDX JSON back into models, so it can't load two finished documents to combine them either. + This performs the merge directly against the JSON structure instead of depending on either. + + The merge is hierarchical: a new top-level component identifies the published package, each input + document's own metadata.component becomes a direct child of it (added to the flat 'components' array, + linked via 'dependencies', not nested inside 'components[].components' - CycloneDX's own convention + for expressing "these are all the parts, here is how they relate" is the dependency graph, not + structural nesting), and each input's own components/dependencies are carried over unchanged. That + keeps which ecosystem a component came from traceable in the dependency graph, instead of flattening + both into one undifferentiated list with no record of provenance. + + Metadata 'tools' entries are deliberately dropped rather than merged: the array-vs-object shape of + that field changed across CycloneDX spec versions, and getting it wrong risks a malformed document + for a field that carries no information this fix needs. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string]$DotNetBomPath, + + [Parameter(Mandatory)] + [string]$NpmBomPath, + + [Parameter(Mandatory)] + [string]$PackageId, + + [Parameter(Mandatory)] + [string]$PackageVersion, + + [Parameter(Mandatory)] + [string]$OutputFile, + + [string]$Group = 'Infragistics', + + [string]$SpecVersion = '1.6' +) + +$ErrorActionPreference = 'Stop' + +function Import-CycloneDxBom { + param( + [Parameter(Mandatory)] + [string]$Path, + + [Parameter(Mandatory)] + [string]$Label + ) + + if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) { + throw "Required file not found: $Path" + } + + $bom = Get-Content -LiteralPath $Path -Raw | ConvertFrom-Json -Depth 100 + if (-not $bom.metadata -or -not $bom.metadata.component) { + throw "$Label document has no metadata.component; cannot nest it under the merged root." + } + if (-not $bom.metadata.component.'bom-ref') { + throw "$Label document's metadata.component has no bom-ref; cannot link it into the merged dependency graph." + } + + $bom +} + +$dotnetBom = Import-CycloneDxBom -Path $DotNetBomPath -Label '.NET' +$npmBom = Import-CycloneDxBom -Path $NpmBomPath -Label 'npm' + +$rootBomRef = "root-$([guid]::NewGuid())" +$rootComponent = [ordered]@{ + type = 'library' + 'bom-ref' = $rootBomRef + group = $Group + name = $PackageId + version = $PackageVersion +} + +$mergedComponents = [System.Collections.Generic.List[object]]::new() +$mergedDependencies = [System.Collections.Generic.List[object]]::new() +$childBomRefs = [System.Collections.Generic.List[string]]::new() + +foreach ($side in @($dotnetBom, $npmBom)) { + $mergedComponents.Add($side.metadata.component) + $childBomRefs.Add($side.metadata.component.'bom-ref') + + foreach ($component in @($side.components)) { + $mergedComponents.Add($component) + } + foreach ($dependency in @($side.dependencies)) { + $mergedDependencies.Add($dependency) + } +} + +$mergedDependencies.Add([ordered]@{ ref = $rootBomRef; dependsOn = @($childBomRefs) }) + +$merged = [ordered]@{ + bomFormat = 'CycloneDX' + specVersion = $SpecVersion + serialNumber = "urn:uuid:$([guid]::NewGuid())" + version = 1 + metadata = [ordered]@{ + timestamp = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ') + component = $rootComponent + } + components = $mergedComponents + dependencies = $mergedDependencies +} + +$outputDirectory = Split-Path -Path $OutputFile -Parent +if ($outputDirectory) { + New-Item -ItemType Directory -Path $outputDirectory -Force | Out-Null +} + +$merged | ConvertTo-Json -Depth 100 | Set-Content -LiteralPath $OutputFile -Encoding utf8 + +Write-Host "Merged .NET ($($dotnetBom.components.Count + 1) components) and npm ($($npmBom.components.Count + 1) components) CycloneDX documents into $OutputFile." diff --git a/.github/scripts/New-CycloneDxSbom.ps1 b/.github/scripts/New-CycloneDxSbom.ps1 new file mode 100644 index 0000000..82604ed --- /dev/null +++ b/.github/scripts/New-CycloneDxSbom.ps1 @@ -0,0 +1,84 @@ +<# +.SYNOPSIS + Generates a CycloneDX SBOM for the project's .NET dependencies via dotnet-CycloneDX. + +.DESCRIPTION + This is the .NET half of the CycloneDX picture only: dotnet-CycloneDX has no notion of npm packages, + so it cannot see the Vite-bundled JS or the igniteui-webcomponents theme CSS the .nupkg also ships. + New-NpmCycloneDxSbom.ps1 covers that half, and Merge-CycloneDxSbom.ps1 combines the two into the + single document that is actually checksummed and attested; this script's output is an intermediate. + + dotnet-CycloneDX reads licence expressions and authors from each package's nuspec; when GitHub licence + resolution is enabled below, unresolved file-based licences can additionally require authenticated + GitHub API requests. This is what fills in fields the ClearlyDefined-backed SPDX documents otherwise + leave as NOASSERTION whenever that service is degraded. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string]$ProjectPath, + + [Parameter(Mandatory)] + [string]$PackageId, + + [Parameter(Mandatory)] + [string]$PackageVersion, + + [Parameter(Mandatory)] + [string]$OutputDirectory, + + # Resolves licences for packages whose nuspec points at a licence file instead of an SPDX expression. + # In Actions, supply secrets.GITHUB_TOKEN; without it those packages are left unlicensed. + [string]$GitHubBearerToken, + + # Pinned to match cyclonedx-npm's max supported version (1.6, vs this tool's own default of 1.7), so + # Merge-CycloneDxSbom.ps1 combines two documents of the same spec version rather than mismatched ones. + [string]$SpecVersion = '1.6' +) + +$ErrorActionPreference = 'Stop' +$PSNativeCommandUseErrorActionPreference = $true + +New-Item -ItemType Directory -Path $OutputDirectory -Force | Out-Null + +$arguments = @( + $ProjectPath + '--output', $OutputDirectory + '--json' + '--set-name', $PackageId + '--set-version', $PackageVersion + '--set-type', 'Library' + '--spec-version', $SpecVersion + '--exclude-dev' + '--include-license-text' +) + +if ($GitHubBearerToken) { + $env:CYCLONEDX_GITHUB_BEARER_TOKEN = $GitHubBearerToken + $arguments += '--enable-github-licenses' +} +else { + Write-Warning 'No GitHub token supplied; packages that declare a licence file rather than an SPDX expression will be left unlicensed.' +} + +try { + dotnet tool run dotnet-CycloneDX -- @arguments +} +finally { + Remove-Item Env:\CYCLONEDX_GITHUB_BEARER_TOKEN -ErrorAction SilentlyContinue +} + +$bomPath = Join-Path $OutputDirectory 'bom.json' +if (-not (Test-Path -LiteralPath $bomPath -PathType Leaf)) { + throw "CycloneDX did not produce a document at $bomPath." +} + +$bom = Get-Content -LiteralPath $bomPath -Raw | ConvertFrom-Json +$components = @($bom.components) + +if ($components.Count -eq 0) { + throw '.NET CycloneDX document contains no components.' +} + +Write-Host ".NET CycloneDX $($bom.specVersion): $($components.Count) components, $(@($bom.dependencies).Count) dependency edges." + diff --git a/.github/scripts/New-NpmCycloneDxSbom.ps1 b/.github/scripts/New-NpmCycloneDxSbom.ps1 new file mode 100644 index 0000000..136054a --- /dev/null +++ b/.github/scripts/New-NpmCycloneDxSbom.ps1 @@ -0,0 +1,66 @@ +<# +.SYNOPSIS + Generates a CycloneDX SBOM for the project's npm runtime dependency tree, via cyclonedx-npm. + +.DESCRIPTION + dotnet-CycloneDX only inventories the .csproj; it has no notion of the Vite-bundled JS or the + igniteui-webcomponents theme CSS the .nupkg also ships. This covers that half of the shipped + artifact so the merged document (see Merge-CycloneDxSbom.ps1) describes both ecosystems. + + cyclonedx-npm is a pinned package.json devDependency, restored by 'npm ci' like every other build + tool here. npx only resolves a local install by walking up from the current directory, so this runs + it from the manifest's own directory - not the caller's cwd - to avoid falling back to a registry + fetch of an ad-hoc version. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string]$ManifestPath, + + [Parameter(Mandatory)] + [string]$OutputFile, + + [string]$SpecVersion = '1.6' +) + +$ErrorActionPreference = 'Stop' +$PSNativeCommandUseErrorActionPreference = $true + +if (-not (Test-Path -LiteralPath $ManifestPath -PathType Leaf)) { + throw "npm package manifest not found: $ManifestPath" +} + +$outputDirectory = Split-Path -Path $OutputFile -Parent +if ($outputDirectory) { + New-Item -ItemType Directory -Path $outputDirectory -Force | Out-Null +} + +$resolvedOutputFile = [System.IO.Path]::GetFullPath($OutputFile) +$projectDirectory = Split-Path -Path (Resolve-Path -LiteralPath $ManifestPath) -Parent + +Push-Location -LiteralPath $projectDirectory +try { + # --omit dev excludes vite/terser (build tooling, never shipped); igniteui-grid-lite and its resolved + # runtime tree (igniteui-webcomponents, lit, @lit/context, @lit-labs/virtualizer) are not devDependencies. + npx --no-install cyclonedx-npm ` + --omit dev ` + --spec-version $SpecVersion ` + --output-format JSON ` + --output-file $resolvedOutputFile +} +finally { + Pop-Location +} + +if (-not (Test-Path -LiteralPath $OutputFile -PathType Leaf) -or (Get-Item -LiteralPath $OutputFile).Length -eq 0) { + throw "cyclonedx-npm did not produce a document at $OutputFile." +} + +$bom = Get-Content -LiteralPath $OutputFile -Raw | ConvertFrom-Json +$components = @($bom.components) + +if ($components.Count -eq 0) { + throw 'npm CycloneDX document contains no components.' +} + +Write-Host "npm CycloneDX $($bom.specVersion): $($components.Count) production components." diff --git a/.github/scripts/New-Sbom.ps1 b/.github/scripts/New-Sbom.ps1 new file mode 100644 index 0000000..befd0d9 --- /dev/null +++ b/.github/scripts/New-Sbom.ps1 @@ -0,0 +1,174 @@ +<# +.SYNOPSIS + Generates SPDX 2.2 and SPDX 3.0 SBOMs for a packed NuGet package with the pinned sbom-tool. + +.DESCRIPTION + Both formats come out of a single sbom-tool invocation. Generating them separately made the two + documents disagree: each invocation performed its own ClearlyDefined lookup, so one document could + carry licenses while the other carried none, and the second scan detected the first document's + manifest as a component of the build. + + sbom-tool degrades silently when ClearlyDefined is unreachable - it logs a warning, writes + NOASSERTION licenses and still exits 0. ClearlyDefined harvests package definitions on demand, so a + coordinate it has not seen before can stall until the gateway times out, while the same request + succeeds once the definition is cached. Generation is therefore retried while coverage improves. + +.OUTPUTS + Manifests are written to $OutputRoot/_manifest/spdx_2.2 and $OutputRoot/_manifest/spdx_3.0. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string]$PackageId, + + [Parameter(Mandatory)] + [string]$PackageVersion, + + # -b: files under this path are hashed into the SBOM's files section. + [Parameter(Mandatory)] + [string]$BuildDropPath, + + # -bc: root the component detectors scan to build the dependency graph. + [Parameter(Mandatory)] + [string]$BuildComponentPath, + + # Must sit outside BuildComponentPath, or the generated manifests become components of the build. + [Parameter(Mandatory)] + [string]$OutputRoot, + + [string]$Supplier = 'Infragistics Inc.', + + [string]$NamespaceBaseUri, + + # External license lookup is a network call per component; bound it or turn it off. + [bool]$ResolveLicenses = $true, + + [int]$LicenseTimeoutSeconds = 180, + + [ValidateRange(1, 5)] + [int]$MaxAttempts = 3, + + [int]$RetryDelaySeconds = 15 +) + +$ErrorActionPreference = 'Stop' +$PSNativeCommandUseErrorActionPreference = $true + +if (-not $NamespaceBaseUri) { + $NamespaceBaseUri = "http://spdx.org/spdxdocs/$PackageId" +} + +$resolvedOutputRoot = [System.IO.Path]::GetFullPath($OutputRoot) +$resolvedComponentPath = [System.IO.Path]::GetFullPath($BuildComponentPath) + +function Test-PathIsWithin { + param( + [Parameter(Mandatory)] + [string]$Path, + + [Parameter(Mandatory)] + [string]$PotentialParent + ) + + # Compares directory segments rather than a raw string prefix, so a sibling directory whose name + # merely starts with the same characters (e.g. 'repo-output' next to 'repo') is not flagged as nested. + [char[]]$separators = [System.IO.Path]::DirectorySeparatorChar, [System.IO.Path]::AltDirectorySeparatorChar + $pathSegments = $Path.Split($separators, [System.StringSplitOptions]::RemoveEmptyEntries) + $parentSegments = $PotentialParent.Split($separators, [System.StringSplitOptions]::RemoveEmptyEntries) + + if ($pathSegments.Count -lt $parentSegments.Count) { + return $false + } + + for ($i = 0; $i -lt $parentSegments.Count; $i++) { + # PowerShell string comparison operators are case-insensitive by default. + if ($pathSegments[$i] -ne $parentSegments[$i]) { + return $false + } + } + + return $true +} + +if (Test-PathIsWithin -Path $resolvedOutputRoot -PotentialParent $resolvedComponentPath) { + throw "OutputRoot '$resolvedOutputRoot' is inside BuildComponentPath '$resolvedComponentPath'. The generated manifests would be scanned as components of the build." +} + +$spdx22Manifest = Join-Path $resolvedOutputRoot '_manifest/spdx_2.2/manifest.spdx.json' + +function Get-LicenseCoverage { + param([string]$ManifestPath) + + if (-not (Test-Path -LiteralPath $ManifestPath -PathType Leaf)) { + return [pscustomobject]@{ Total = 0; Licensed = 0 } + } + + $packages = @((Get-Content -LiteralPath $ManifestPath -Raw | ConvertFrom-Json).packages) + + [pscustomobject]@{ + Total = $packages.Count + Licensed = @($packages | Where-Object { $_.licenseConcluded -and $_.licenseConcluded -ne 'NOASSERTION' }).Count + } +} + +$best = [pscustomobject]@{ Total = 0; Licensed = -1 } +$staging = "$resolvedOutputRoot.attempt" + +for ($attempt = 1; $attempt -le $MaxAttempts; $attempt++) { + # Each attempt is generated aside and only promoted if it improves on the one already kept, so a + # degraded retry can never replace a better document. sbom-tool also will not create -m itself. + Remove-Item -LiteralPath $staging -Recurse -Force -ErrorAction SilentlyContinue + New-Item -ItemType Directory -Path $staging -Force | Out-Null + + Write-Host "Generating SPDX 2.2 and SPDX 3.0 SBOMs (attempt $attempt of $MaxAttempts)..." + + # /Verbosity has to precede the remaining switches or the parser binds its value to another argument. + dotnet tool run sbom-tool -- generate ` + /Verbosity:Information ` + -b $BuildDropPath ` + -bc $BuildComponentPath ` + -m $staging ` + -pn $PackageId ` + -pv $PackageVersion ` + -ps $Supplier ` + -nsb $NamespaceBaseUri ` + -mi 'SPDX:2.2,SPDX:3.0' ` + -li $ResolveLicenses.ToString().ToLowerInvariant() ` + -lto $LicenseTimeoutSeconds ` + -pm true + + $coverage = Get-LicenseCoverage -ManifestPath (Join-Path $staging '_manifest/spdx_2.2/manifest.spdx.json') + Write-Host "Attempt ${attempt}: $($coverage.Licensed) of $($coverage.Total) packages carry a resolved license." + + if ($coverage.Licensed -gt $best.Licensed) { + Remove-Item -LiteralPath $resolvedOutputRoot -Recurse -Force -ErrorAction SilentlyContinue + Move-Item -LiteralPath $staging -Destination $resolvedOutputRoot -Force + $best = $coverage + } + else { + Remove-Item -LiteralPath $staging -Recurse -Force -ErrorAction SilentlyContinue + # Zero is an outage rather than a plateau: a coordinate ClearlyDefined has never harvested only + # becomes available after the request that triggered the harvest has already failed. + if ($coverage.Licensed -gt 0) { + Write-Host 'License coverage stopped improving; keeping the document already generated.' + break + } + } + + if (-not $ResolveLicenses -or ($best.Total -gt 0 -and $best.Licensed -eq $best.Total)) { + break + } + + if ($attempt -lt $MaxAttempts) { + Write-Host "Retrying in $RetryDelaySeconds seconds to let ClearlyDefined harvest the missing definitions..." + Start-Sleep -Seconds $RetryDelaySeconds + } +} + +if (-not (Test-Path -LiteralPath $spdx22Manifest -PathType Leaf)) { + throw "sbom-tool produced no SPDX 2.2 document at $spdx22Manifest." +} + +if ($ResolveLicenses -and $best.Licensed -lt $best.Total) { + Write-Warning "$($best.Total - $best.Licensed) of $($best.Total) packages have no resolved license and are recorded as NOASSERTION." +} diff --git a/.github/scripts/Publish-NuGetPackage.ps1 b/.github/scripts/Publish-NuGetPackage.ps1 new file mode 100644 index 0000000..c526a28 --- /dev/null +++ b/.github/scripts/Publish-NuGetPackage.ps1 @@ -0,0 +1,69 @@ +<# +.SYNOPSIS + Pushes the signed package to NuGet.org, refusing to overwrite a version that is already published. + +.DESCRIPTION + Deliberately not --skip-duplicate: a rerun produces newly signed bytes, so skipping the duplicate + would attach this run's SBOM, attestations and checksum to a release whose published package is a + different build. The API key is sourced from NUGET_API_KEY rather than embedded in the workflow command. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string]$PackagePath, + + [Parameter(Mandatory)] + [string]$PackageId, + + [Parameter(Mandatory)] + [string]$Version, + + [string]$Source = 'https://api.nuget.org/v3/index.json', + + [string]$FlatContainerBaseUrl = 'https://api.nuget.org/v3-flatcontainer' +) + +$ErrorActionPreference = 'Stop' +# Pinned: a failed push is inspected through $LASTEXITCODE below rather than terminating the script. +$PSNativeCommandUseErrorActionPreference = $false + +if ([string]::IsNullOrWhiteSpace($env:NUGET_API_KEY)) { + throw 'NUGET_API_KEY is not set. The publish step must expose the token from the NuGet login step.' +} + +if (-not (Test-Path -LiteralPath $PackagePath -PathType Leaf)) { + throw "NuGet package not found: $PackagePath" +} + +$id = $PackageId.ToLowerInvariant() +$normalizedVersion = $Version.ToLowerInvariant() +$feedUrl = "$FlatContainerBaseUrl/$id/$normalizedVersion/$id.$normalizedVersion.nupkg" + +# The flat container lags a push by seconds to minutes, so the retries stop a duplicate +# rejection from being reported as a package that never reached the feed. +function Test-Published([int[]]$RetryDelaysSeconds = @()) { + foreach ($delay in @(0) + $RetryDelaysSeconds) { + if ($delay -gt 0) { Start-Sleep -Seconds $delay } + if ((Invoke-WebRequest -Uri $feedUrl -Method Head -SkipHttpErrorCheck).StatusCode -eq 200) { return $true } + } + return $false +} + +$recovery = "NuGet.org will not accept this version again. If a previous run published it but failed before attaching evidence, attach that run's retained nupkg-signed and sbom artifacts to the release manually." + +if (Test-Published) { + throw "$PackageId $Version is already on NuGet.org, so this run must not attach its evidence to the release: the published package may be a different build. $recovery" +} + +dotnet nuget push $PackagePath --api-key $env:NUGET_API_KEY --source $Source +if ($LASTEXITCODE -eq 0) { + Write-Host "Published $PackageId $Version." + exit 0 +} + +Write-Host "::warning title=Push reported a failure::Checking whether the package reached NuGet.org anyway." +if (Test-Published -RetryDelaysSeconds @(5, 15, 30)) { + throw "dotnet nuget push reported a failure but $PackageId $Version is on NuGet.org. $recovery" +} + +throw "dotnet nuget push failed and $PackageId $Version is not on NuGet.org." diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2c30ab8..5ca0870 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -2,50 +2,140 @@ name: Publish NuGet Package on: release: - types: [created] + types: [published] + +permissions: {} + +concurrency: + group: release-${{ github.ref_name }} env: - VERSION: ${{ github.ref_name }} BUILD_CONFIGURATION: Release + DOTNET_VERSION: '10.0.x' + VERSION: ${{ github.ref_name }} + PACKAGE_ID: IgniteUI.Blazor.GridLite + PROJECT_PATH: src/IgniteUI.Blazor.GridLite/IgniteUI.Blazor.GridLite.csproj + PROJECT_DIR: src/IgniteUI.Blazor.GridLite + REPOSITORY_URL: https://github.com/IgniteUI/IgniteUI.Blazor.GridLite + # Public, deliberately pinned identities. + EXPECTED_CERT_SHA256_PATH: 'eng/IG.authenticode-certificates.sha256' + EXPECTED_PUBLIC_KEY_PATH: 'eng/IG.publickey.hex' + # Bound sbom-tool's external license lookup. + SBOM_LICENSE_TIMEOUT_SECONDS: '180' jobs: - publish: + # Holds the strong-name key, but no OIDC token, no Key Vault access and no publishing rights. + build: + name: Build runs-on: windows-latest - environment: NuGet Deploy + timeout-minutes: 20 + environment: Release build permissions: - id-token: write # enable GitHub OIDC token issuance for this job contents: read steps: - - uses: actions/checkout@v7 + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false - name: Setup .NET - uses: actions/setup-dotnet@v6 + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 with: - dotnet-version: "10.0.x" + dotnet-version: ${{ env.DOTNET_VERSION }} - - uses: actions/setup-node@v7.0.0 + - name: Setup Node.js + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: '22' - registry-url: 'https://registry.npmjs.org' - - run: npm ci - working-directory: src/IgniteUI.Blazor.GridLite + - name: Restore JavaScript dependencies + run: npm ci + working-directory: ${{ env.PROJECT_DIR }} + + - name: Build JavaScript bundle + run: npm run build + working-directory: ${{ env.PROJECT_DIR }} + + - name: Restore .NET dependencies + run: dotnet restore ${{ env.PROJECT_PATH }} - - run: npm run build - working-directory: src/IgniteUI.Blazor.GridLite + - name: Restore strong-name key + shell: pwsh + env: + STRONG_NAME_KEY_BASE64: ${{ secrets.IG_STRONG_NAME_KEY }} + run: | + if ([string]::IsNullOrWhiteSpace($env:STRONG_NAME_KEY_BASE64)) { + throw "The IG_STRONG_NAME_KEY organization secret is empty or unavailable to this repository." + } - - name: Restore dependencies - run: dotnet restore src/IgniteUI.Blazor.GridLite/IgniteUI.Blazor.GridLite.csproj + $keyBytes = [Convert]::FromBase64String($env:STRONG_NAME_KEY_BASE64) + [System.IO.File]::WriteAllBytes("${{ runner.temp }}\IG.StrongName.snk", $keyBytes) + + - name: Build strong-named assemblies + shell: pwsh + run: > + dotnet build ${{ env.PROJECT_PATH }} + --configuration ${{ env.BUILD_CONFIGURATION }} + --no-restore + "-p:Version=$env:VERSION" + -p:RunNodeBuild=false + -p:GeneratePackageOnBuild=false + -p:ContinuousIntegrationBuild=true + -p:SignAssembly=true + -p:AssemblyOriginatorKeyFile="${{ runner.temp }}\IG.StrongName.snk" + + - name: Delete strong-name key + if: always() + shell: pwsh + run: Remove-Item "${{ runner.temp }}\IG.StrongName.snk" -Force -ErrorAction SilentlyContinue + + - name: Upload build output + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: build-output + path: | + src/IgniteUI.Blazor.GridLite/bin/** + src/IgniteUI.Blazor.GridLite/obj/** + src/IgniteUI.Blazor.GridLite/wwwroot/js/** + src/IgniteUI.Blazor.GridLite/wwwroot/css/themes/** + include-hidden-files: true + retention-days: 1 + if-no-files-found: error + + sign-assemblies: + name: Sign assemblies + needs: build + runs-on: windows-latest + timeout-minutes: 20 + environment: NuGet Deploy + permissions: + contents: read + id-token: write + + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + + - name: Setup .NET + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Download build output + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: build-output + path: src/IgniteUI.Blazor.GridLite + digest-mismatch: error - name: Restore .NET local tools run: dotnet tool restore - - name: Build - run: dotnet build src/IgniteUI.Blazor.GridLite/IgniteUI.Blazor.GridLite.csproj --configuration ${{ env.BUILD_CONFIGURATION }} -p:Version=${{ env.VERSION }} -p:RunNodeBuild=false -p:GeneratePackageOnBuild=false - - name: Authenticate to Azure - uses: azure/login@f5d393ae46f8fde4be8b75f32e3fc50e654ad0ca # v3.0.1 + uses: azure/login@f5d393ae46f8fde4be8b75f32e3fc50e654ad0ca # v3.0.1 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} @@ -63,27 +153,94 @@ jobs: - name: Validate DLL signatures shell: pwsh - run: | - $dlls = Get-ChildItem -Path "${{ github.workspace }}/src/IgniteUI.Blazor.GridLite/bin/${{ env.BUILD_CONFIGURATION }}" -Filter "*.dll" -Recurse - if (-not $dlls -or $dlls.Count -eq 0) { - Write-Error "No DLLs found under '${{ github.workspace }}/src/IgniteUI.Blazor.GridLite/bin/${{ env.BUILD_CONFIGURATION }}' to validate." - exit 1 - } - $failed = @() - foreach ($dll in $dlls) { - $sig = Get-AuthenticodeSignature $dll.FullName - if ($sig.Status -ne 'Valid') { - $failed += $dll.FullName - } - } - if ($failed.Count -gt 0) { - Write-Error "Unsigned DLLs found:`n$($failed -join "`n")" - exit 1 - } - Write-Host "All DLLs signed successfully." + run: > + .github/scripts/Assert-AuthenticodeSignature.ps1 + -Path "${{ github.workspace }}/${{ env.PROJECT_DIR }}/bin/${{ env.BUILD_CONFIGURATION }}" + -ExpectedCertificateSha256Path "${{ env.EXPECTED_CERT_SHA256_PATH }}" + + - name: Upload signed assemblies + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: signed-assemblies + path: | + src/IgniteUI.Blazor.GridLite/bin/** + src/IgniteUI.Blazor.GridLite/obj/** + src/IgniteUI.Blazor.GridLite/wwwroot/js/** + src/IgniteUI.Blazor.GridLite/wwwroot/css/themes/** + include-hidden-files: true + retention-days: 1 + if-no-files-found: error + + pack: + name: Pack and sign package + needs: sign-assemblies + runs-on: windows-latest + timeout-minutes: 20 + environment: NuGet Deploy + permissions: + contents: read + id-token: write + outputs: + nupkg-sha256: ${{ steps.digest.outputs.nupkg-sha256 }} + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + + - name: Setup .NET + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Download signed assemblies + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: signed-assemblies + path: src/IgniteUI.Blazor.GridLite + digest-mismatch: error + + # Pack re-resolves package assets whenever the downloaded obj cache is treated as stale, and + # then needs the packages on this runner. Restoring is not a rebuild: the signed DLLs stand. + - name: Restore .NET dependencies + run: dotnet restore ${{ env.PROJECT_PATH }} + + # Repository url and commit are passed explicitly so the nuspec never carries a commit + # without a url (or vice versa) depending on what the checkout leaves in .git. - name: Pack NuGet package - run: dotnet pack src/IgniteUI.Blazor.GridLite/IgniteUI.Blazor.GridLite.csproj --configuration ${{ env.BUILD_CONFIGURATION }} --no-build --no-restore -p:PackageVersion=${{ env.VERSION }} -o ./artifacts + run: > + dotnet pack ${{ env.PROJECT_PATH }} + --configuration ${{ env.BUILD_CONFIGURATION }} + --no-build + --no-restore + "-p:PackageVersion=$env:VERSION" + -p:RepositoryUrl=${{ env.REPOSITORY_URL }} + -p:RepositoryType=git + -p:RepositoryCommit=${{ github.sha }} + -o "${{ github.workspace }}/artifacts" + + # The gate that runs on the actual shipped bytes: bin/ output was already checked once, but + # packing only re-zips it, so this re-validates both signals against the extracted nupkg + # instead of trusting that pack couldn't have picked up something else. + - name: Validate packaged assembly signatures + shell: pwsh + run: > + .github/scripts/Assert-PackageSignatures.ps1 + -PackagePath "${env:GITHUB_WORKSPACE}/artifacts/${env:PACKAGE_ID}.${env:VERSION}.nupkg" + -ExpectedPublicKeyPath "${{ env.EXPECTED_PUBLIC_KEY_PATH }}" + -ExpectedCertificateSha256Path "${{ env.EXPECTED_CERT_SHA256_PATH }}" + -WorkingDirectory "${{ runner.temp }}/package-signature-validation" + + - name: Restore .NET local tools + run: dotnet tool restore + + - name: Authenticate to Azure + uses: azure/login@f5d393ae46f8fde4be8b75f32e3fc50e654ad0ca # v3.0.1 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - name: Sign NuGet package shell: pwsh @@ -97,14 +254,355 @@ jobs: --verbosity Warning - name: Validate NuGet package signature - run: dotnet nuget verify "${{ github.workspace }}/artifacts/IgniteUI.Blazor.GridLite.${{ env.VERSION }}.nupkg" - # Get a short-lived NuGet API key - - name: NuGet login (OIDC → temp API key) - uses: NuGet/login@8d196754b4036150537f80ac539e15c2f1028841 # v1 - id: login + shell: pwsh + run: > + .github/scripts/Assert-NuGetSignature.ps1 + -PackagePath "${env:GITHUB_WORKSPACE}/artifacts/${env:PACKAGE_ID}.${env:VERSION}.nupkg" + -ExpectedCertificateSha256Path "${{ env.EXPECTED_CERT_SHA256_PATH }}" + + # This digest is the identity every downstream job re-checks before acting on the package. + - name: Record package digest + id: digest + shell: pwsh + run: > + .github/scripts/Get-PackageDigest.ps1 + -PackagePath "${env:GITHUB_WORKSPACE}/artifacts/${env:PACKAGE_ID}.${env:VERSION}.nupkg" + -WriteChecksumFile + -GitHubOutputName 'nupkg-sha256' + -SummaryTitle 'Signed package digest' + + - name: Upload signed package + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: nupkg-signed + path: artifacts/* + retention-days: 30 + if-no-files-found: error + + # Advisory by design. A finding is annotated and attached to the release as evidence, but never + # holds up the publish. Task scope is limited to publish.yml, so there is no PR-time blocking + # dependency-review job pairing this one yet. + dependency-scan: + name: Scan dependencies + needs: pack + runs-on: ubuntu-latest + timeout-minutes: 15 + permissions: + contents: read + + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + + - name: Setup .NET + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Scan NuGet dependencies + shell: pwsh + run: > + .github/scripts/Invoke-DependencyScan.ps1 + -ProjectPath "${{ env.PROJECT_PATH }}" + -OutputDirectory "${{ github.workspace }}/artifacts/dependency-scan" + -PackageId "${{ env.PACKAGE_ID }}" + -Version "$env:VERSION" + + - name: Upload dependency scan + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: dependency-scan + path: artifacts/dependency-scan/* + retention-days: 30 + if-no-files-found: error + + sbom: + name: Generate SBOM and attest + needs: pack + runs-on: windows-latest + timeout-minutes: 20 + permissions: + contents: read + id-token: write + attestations: write + outputs: + attested-sha256: ${{ steps.verify-before-attestation.outputs.nupkg-sha256 }} + + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + + - name: Setup .NET + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Setup Node.js + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: '22' + + - name: Download signed package + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: nupkg-signed + path: artifacts + + - name: Verify signed package digest + shell: pwsh + run: > + .github/scripts/Get-PackageDigest.ps1 + -PackagePath "${env:GITHUB_WORKSPACE}/artifacts/${env:PACKAGE_ID}.${env:VERSION}.nupkg" + -ExpectedSha256 "${{ needs.pack.outputs.nupkg-sha256 }}" + + - name: Restore .NET dependencies + run: dotnet restore ${{ env.PROJECT_PATH }} + + # sbom-tool's component detector needs node_modules to see the JavaScript dependency graph too. + - name: Restore JavaScript dependencies + run: npm ci --ignore-scripts + working-directory: ${{ env.PROJECT_DIR }} + + - name: Restore .NET local tools + run: dotnet tool restore + + - name: Generate SBOMs + shell: pwsh + run: > + .github/scripts/New-Sbom.ps1 + -PackageId "${{ env.PACKAGE_ID }}" + -PackageVersion "$env:VERSION" + -BuildDropPath "${{ github.workspace }}/artifacts" + -BuildComponentPath "${{ github.workspace }}/${{ env.PROJECT_DIR }}" + -OutputRoot "${{ runner.temp }}/sbom" + -LicenseTimeoutSeconds ${{ env.SBOM_LICENSE_TIMEOUT_SECONDS }} + + - name: Verify SBOM output + shell: pwsh + run: > + .github/scripts/Assert-Sbom.ps1 + -OutputRoot "${{ runner.temp }}/sbom" + -ExpectedPackagePath "${env:GITHUB_WORKSPACE}/artifacts/${env:PACKAGE_ID}.${env:VERSION}.nupkg" + + # CycloneDX reads licences and authors from each package's own nuspec, so it fills the fields the + # ClearlyDefined-backed SPDX documents leave as NOASSERTION whenever that service is degraded. + # This is the .NET half only - dotnet-CycloneDX has no notion of npm packages. + - name: Generate .NET CycloneDX SBOM + shell: pwsh + env: + GH_TOKEN_FOR_LICENSES: ${{ github.token }} + run: > + .github/scripts/New-CycloneDxSbom.ps1 + -ProjectPath "${{ env.PROJECT_PATH }}" + -PackageId "${{ env.PACKAGE_ID }}" + -PackageVersion "$env:VERSION" + -OutputDirectory "${{ runner.temp }}/sbom/cyclonedx/dotnet" + -GitHubBearerToken "$env:GH_TOKEN_FOR_LICENSES" + + # The npm half: the .nupkg also ships the Vite-bundled JS and copied igniteui-webcomponents theme + # CSS, neither of which the .NET-only BOM above can see. cyclonedx-npm is a locked devDependency + # of package.json, restored by the npm ci above; 'npx cyclonedx-npm' resolves that local install. + - name: Generate npm CycloneDX SBOM + shell: pwsh + run: > + .github/scripts/New-NpmCycloneDxSbom.ps1 + -ManifestPath "${{ env.PROJECT_DIR }}/package.json" + -OutputFile "${{ runner.temp }}/sbom/cyclonedx/npm/bom.json" + + # Pure PowerShell JSON merge, not an external tool: cyclonedx-cli (the only tool with a merge + # command) has no package-manager distribution, and cyclonedx-npm's own library can serialize but + # not deserialize CycloneDX JSON, so it can't load two finished documents either. + - name: Merge CycloneDX SBOMs + shell: pwsh + run: > + .github/scripts/Merge-CycloneDxSbom.ps1 + -DotNetBomPath "${{ runner.temp }}/sbom/cyclonedx/dotnet/bom.json" + -NpmBomPath "${{ runner.temp }}/sbom/cyclonedx/npm/bom.json" + -PackageId "${{ env.PACKAGE_ID }}" + -PackageVersion "$env:VERSION" + -OutputFile "${{ runner.temp }}/sbom/cyclonedx/${{ env.PACKAGE_ID }}.$env:VERSION.cdx.json" + + - name: Verify CycloneDX SBOM output + shell: pwsh + run: > + .github/scripts/Assert-CycloneDxSbom.ps1 + -BomPath "${{ runner.temp }}/sbom/cyclonedx/${{ env.PACKAGE_ID }}.$env:VERSION.cdx.json" + + # An attestation binds to a digest rather than a path, so the bytes are re-hashed here and that + # value is what gets attested, re-checked before publishing, and reported on the release. + - name: Reverify package before attestation + id: verify-before-attestation + shell: pwsh + run: > + .github/scripts/Get-PackageDigest.ps1 + -PackagePath "${env:GITHUB_WORKSPACE}/artifacts/${env:PACKAGE_ID}.${env:VERSION}.nupkg" + -ExpectedSha256 "${{ needs.pack.outputs.nupkg-sha256 }}" + -FailureMessage 'Package changed before attestation.' + -GitHubOutputName 'nupkg-sha256' + + - name: Attest build provenance + id: attest-provenance + uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2 + with: + subject-name: ${{ env.PACKAGE_ID }}.${{ env.VERSION }}.nupkg + subject-digest: sha256:${{ steps.verify-before-attestation.outputs.nupkg-sha256 }} + + # actions/attest derives the predicate from an SPDX 2.x or CycloneDX document; SPDX 3.0 ships as evidence only. + - name: Attest SPDX SBOM + id: attest-sbom-spdx + uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2 + with: + subject-name: ${{ env.PACKAGE_ID }}.${{ env.VERSION }}.nupkg + subject-digest: sha256:${{ steps.verify-before-attestation.outputs.nupkg-sha256 }} + sbom-path: ${{ runner.temp }}/sbom/_manifest/spdx_2.2/manifest.spdx.json + + # Distinct predicate type from the SPDX attestation, so both bind to the same digest without colliding. + - name: Attest CycloneDX SBOM + id: attest-sbom-cyclonedx + uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2 + with: + subject-name: ${{ env.PACKAGE_ID }}.${{ env.VERSION }}.nupkg + subject-digest: sha256:${{ steps.verify-before-attestation.outputs.nupkg-sha256 }} + sbom-path: ${{ runner.temp }}/sbom/cyclonedx/${{ env.PACKAGE_ID }}.${{ env.VERSION }}.cdx.json + + - name: Collect attestation bundles + shell: pwsh + run: > + .github/scripts/Copy-AttestationBundles.ps1 + -ProvenanceBundlePath "${{ steps.attest-provenance.outputs.bundle-path }}" + -SpdxBundlePath "${{ steps.attest-sbom-spdx.outputs.bundle-path }}" + -CycloneDxBundlePath "${{ steps.attest-sbom-cyclonedx.outputs.bundle-path }}" + -Destination "${{ runner.temp }}/sbom/attestations" + -ProvenanceUrl "${{ steps.attest-provenance.outputs.attestation-url }}" + -SpdxUrl "${{ steps.attest-sbom-spdx.outputs.attestation-url }}" + -CycloneDxUrl "${{ steps.attest-sbom-cyclonedx.outputs.attestation-url }}" + + - name: Upload SBOM and attestations + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: sbom + path: ${{ runner.temp }}/sbom/** + retention-days: 30 + if-no-files-found: error + + # The only job that can publish. It restores nothing and compiles nothing; its checkout is a + # scripts-only sparse one so the publish gate itself is version-controlled and reviewable. + publish: + name: Publish to NuGet.org + needs: [pack, sbom, dependency-scan] + runs-on: windows-latest + timeout-minutes: 15 + environment: NuGet Deploy + permissions: + id-token: write + + steps: + - name: Checkout release scripts + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + sparse-checkout: | + .github/scripts + eng/IG.authenticode-certificates.sha256 + sparse-checkout-cone-mode: false + + - name: Setup .NET + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Download signed package + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: nupkg-signed + path: artifacts + + - name: Verify the package that was packed, signed, and attested + shell: pwsh + run: > + .github/scripts/Get-PackageDigest.ps1 + -PackagePath "${env:GITHUB_WORKSPACE}/artifacts/${env:PACKAGE_ID}.${env:VERSION}.nupkg" + -ExpectedSha256 "${{ needs.pack.outputs.nupkg-sha256 }}","${{ needs.sbom.outputs.attested-sha256 }}" + -FailureMessage 'Refusing to publish.' + + - name: Validate NuGet package signature + shell: pwsh + run: > + .github/scripts/Assert-NuGetSignature.ps1 + -PackagePath "${env:GITHUB_WORKSPACE}/artifacts/${env:PACKAGE_ID}.${env:VERSION}.nupkg" + -ExpectedCertificateSha256Path "${{ env.EXPECTED_CERT_SHA256_PATH }}" + + - name: NuGet login (OIDC Trusted Publishing) + uses: NuGet/login@8d196754b4036150537f80ac539e15c2f1028841 # v1 + id: nuget-login with: user: ${{ secrets.INFRAGISTICS_NUGET_ORG_USER }} - # Push the package - - name: NuGet push - run: dotnet nuget push artifacts/IgniteUI.Blazor.GridLite.${{ env.VERSION }}.nupkg --api-key ${{steps.login.outputs.NUGET_API_KEY}} --source "https://api.nuget.org/v3/index.json" + # Refuses to publish over an existing version instead of using --skip-duplicate: a full rerun + # produces newly signed bytes, so skipping the duplicate would attach this run's SBOM, + # attestations and checksum to a release whose published package is a different build. + - name: Publish to NuGet.org + shell: pwsh + env: + NUGET_API_KEY: ${{ steps.nuget-login.outputs.NUGET_API_KEY }} + run: > + .github/scripts/Publish-NuGetPackage.ps1 + -PackagePath "${env:GITHUB_WORKSPACE}/artifacts/${env:PACKAGE_ID}.${env:VERSION}.nupkg" + -PackageId "${{ env.PACKAGE_ID }}" + -Version "$env:VERSION" + + attach-to-release: + name: Attach release evidence + needs: [pack, sbom, dependency-scan, publish] + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: write + + steps: + - name: Download signed package + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: nupkg-signed + path: artifacts + + - name: Download SBOM and attestations + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: sbom + path: sbom + + - name: Download dependency scan + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: dependency-scan + path: evidence/dependency-scan + + - name: Attach evidence to the release + env: + GH_TOKEN: ${{ github.token }} + TAG: ${{ github.ref_name }} + PACKAGE_ID: IgniteUI.Blazor.GridLite + run: | + set -euo pipefail + + (cd sbom/_manifest/spdx_2.2 && zip -r "${GITHUB_WORKSPACE}/${PACKAGE_ID}.${TAG}.spdx-2.2.zip" .) + (cd sbom/_manifest/spdx_3.0 && zip -r "${GITHUB_WORKSPACE}/${PACKAGE_ID}.${TAG}.spdx-3.0.zip" .) + (cd evidence/dependency-scan && zip -r "${GITHUB_WORKSPACE}/${PACKAGE_ID}.${TAG}.dependency-scan.zip" .) + + gh release upload "$TAG" --clobber -R "${{ github.repository }}" \ + "artifacts/${PACKAGE_ID}.${TAG}.nupkg" \ + "artifacts/${PACKAGE_ID}.${TAG}.nupkg.sha256" \ + "${PACKAGE_ID}.${TAG}.spdx-2.2.zip" \ + "${PACKAGE_ID}.${TAG}.spdx-3.0.zip" \ + "${PACKAGE_ID}.${TAG}.dependency-scan.zip" \ + "sbom/cyclonedx/${PACKAGE_ID}.${TAG}.cdx.json" \ + "sbom/cyclonedx/${PACKAGE_ID}.${TAG}.cdx.json.sha256" \ + "sbom/attestations/provenance.sigstore.json" \ + "sbom/attestations/sbom-spdx.sigstore.json" \ + "sbom/attestations/sbom-cyclonedx.sigstore.json" + diff --git a/eng/IG.authenticode-certificates.sha256 b/eng/IG.authenticode-certificates.sha256 new file mode 100644 index 0000000..01307c5 --- /dev/null +++ b/eng/IG.authenticode-certificates.sha256 @@ -0,0 +1,3 @@ +# Approved Authenticode signing certificates, one SHA-256 fingerprint per line. +# Fingerprints are computed over the certificate's DER-encoded RawData. +7F0D4484D1D3C797FDC85801CACE18DB5249D61AFFB17DA5C1644D8BEA24630D \ No newline at end of file diff --git a/eng/IG.publickey.hex b/eng/IG.publickey.hex new file mode 100644 index 0000000..197343d --- /dev/null +++ b/eng/IG.publickey.hex @@ -0,0 +1,8 @@ +# Infragistics strong-name public key, as the raw public key blob in hex. +# +# This is public data embedded in every assembly. It is pinned here so signing with a different key +# fails the release instead of silently establishing a new binary identity. +# +# Public key token: 7dd5c3163f2cd0cb +# Re-derive with: sn -Tp +002400000480000094000000060200000024000052534131000400000100010001afa6285b0af5cdd03aa2b6fdaf33fc4759cf9cd9bcf8b778ae60b9fcf71fc8126b78dbf930519614013b7999297907dd9c00bcc487a14f4c6733fe9adb96c053f005d7148f1666fcb882a0f9ba4307c85694b3322889dab357ad5cefd72ccc45e1b6973bdd2f15b2a300077b8d9de30739200887c5407c8a68c90345cbc4f1 \ No newline at end of file diff --git a/src/IgniteUI.Blazor.GridLite/package-lock.json b/src/IgniteUI.Blazor.GridLite/package-lock.json index c08c1b8..cfa22b8 100644 --- a/src/IgniteUI.Blazor.GridLite/package-lock.json +++ b/src/IgniteUI.Blazor.GridLite/package-lock.json @@ -12,10 +12,103 @@ "igniteui-grid-lite": "~0.9.0" }, "devDependencies": { + "@cyclonedx/cyclonedx-npm": "6.0.1", "terser": "^5.44.1", "vite": "^7.3.6" } }, + "node_modules/@cyclonedx/cyclonedx-library": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@cyclonedx/cyclonedx-library/-/cyclonedx-library-10.2.0.tgz", + "integrity": "sha512-hGeo1XXM0zuIeTyzJihxPxnEOeNBmgZkuPRmTR28RktlAqF9xLneonHRCzahZHLgCq/LOmtCs5vyojJlnmJ87w==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://owasp.org/donate/?reponame=www-project-cyclonedx&title=OWASP+CycloneDX" + } + ], + "license": "Apache-2.0", + "engines": { + "node": ">=20.18.0" + }, + "peerDependencies": { + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "ajv-formats-draft2019": "^1.6.1", + "libxmljs2": "^0.35||^0.37", + "packageurl-js": "*", + "spdx-expression-parse": "*", + "xmlbuilder2": "^3.0.2||^4.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + }, + "ajv-formats": { + "optional": true + }, + "ajv-formats-draft2019": { + "optional": true + }, + "libxmljs2": { + "optional": true + }, + "packageurl-js": { + "optional": true + }, + "spdx-expression-parse": { + "optional": true + }, + "xmlbuilder2": { + "optional": true + } + } + }, + "node_modules/@cyclonedx/cyclonedx-npm": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@cyclonedx/cyclonedx-npm/-/cyclonedx-npm-6.0.1.tgz", + "integrity": "sha512-/aU3bBC6qP6cV/qQ5SfUSygE/+2hQhwgg6sJML31/gZ96NyMvIUuwdk637H4z+LS/NryRT2kjR2wtD0qBEVVHQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://owasp.org/donate/?reponame=www-project-cyclonedx&title=OWASP+CycloneDX" + } + ], + "license": "Apache-2.0", + "dependencies": { + "@cyclonedx/cyclonedx-library": "^10.0.0", + "commander": "^14.0.0", + "normalize-package-data": "^7.0.0 || ^8.0.0", + "packageurl-js": "^2.0.1", + "spdx-expression-parse": "^3.0.1 || ^4.0.0", + "xmlbuilder2": "^3.0.2 || ^4.0.3" + }, + "bin": { + "cyclonedx-npm": "bin/cyclonedx-npm-cli.js" + }, + "engines": { + "node": ">=20.18.0", + "npm": ">=9" + }, + "optionalDependencies": { + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "ajv-formats-draft2019": "^1.6.1", + "libxmljs2": "^0.35||^0.37" + } + }, + "node_modules/@cyclonedx/cyclonedx-npm/node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.27.7", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", @@ -483,6 +576,39 @@ "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==", "license": "MIT" }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -567,6 +693,101 @@ "@lit-labs/ssr-dom-shim": "^1.5.0" } }, + "node_modules/@npmcli/agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz", + "integrity": "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/fs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@oozcitak/dom": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-2.0.2.tgz", + "integrity": "sha512-GjpKhkSYC3Mj4+lfwEyI1dqnsKTgwGy48ytZEhm4A/xnH/8z9M3ZVXKr/YGQi3uCLs1AEBS+x5T2JPiueEDW8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oozcitak/infra": "^2.0.2", + "@oozcitak/url": "^3.0.0", + "@oozcitak/util": "^10.0.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@oozcitak/infra": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-2.0.2.tgz", + "integrity": "sha512-2g+E7hoE2dgCz/APPOEK5s3rMhJvNxSMBrP+U+j1OWsIbtSpWxxlUjq1lU8RIsFJNYv7NMlnVsCuHcUzJW+8vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oozcitak/util": "^10.0.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@oozcitak/url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-3.0.0.tgz", + "integrity": "sha512-ZKfET8Ak1wsLAiLWNfFkZc/BraDccuTJKR6svTYc7sVjbR+Iu0vtXdiDMY4o6jaFl5TW2TlS7jbLl4VovtAJWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oozcitak/infra": "^2.0.2", + "@oozcitak/util": "^10.0.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@oozcitak/util": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-10.0.0.tgz", + "integrity": "sha512-hAX0pT/73190NLqBPPWSdBVGtbY6VOhWYK3qqHqtXQ1gK7kS2yz4+ivsN07hpJ6I3aeMtKP6J6npsEKOAzuTLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.62.3", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.3.tgz", @@ -969,6 +1190,17 @@ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", "license": "MIT" }, + "node_modules/abbrev": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", + "dev": true, + "license": "ISC", + "optional": true, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -982,337 +1214,2211 @@ "node": ">=0.4.0" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 14" + } }, - "node_modules/esbuild": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", - "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, - "hasInstallScript": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" + "optional": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.7", - "@esbuild/android-arm": "0.27.7", - "@esbuild/android-arm64": "0.27.7", - "@esbuild/android-x64": "0.27.7", - "@esbuild/darwin-arm64": "0.27.7", - "@esbuild/darwin-x64": "0.27.7", - "@esbuild/freebsd-arm64": "0.27.7", - "@esbuild/freebsd-x64": "0.27.7", - "@esbuild/linux-arm": "0.27.7", - "@esbuild/linux-arm64": "0.27.7", - "@esbuild/linux-ia32": "0.27.7", - "@esbuild/linux-loong64": "0.27.7", - "@esbuild/linux-mips64el": "0.27.7", - "@esbuild/linux-ppc64": "0.27.7", - "@esbuild/linux-riscv64": "0.27.7", - "@esbuild/linux-s390x": "0.27.7", - "@esbuild/linux-x64": "0.27.7", - "@esbuild/netbsd-arm64": "0.27.7", - "@esbuild/netbsd-x64": "0.27.7", - "@esbuild/openbsd-arm64": "0.27.7", - "@esbuild/openbsd-x64": "0.27.7", - "@esbuild/openharmony-arm64": "0.27.7", - "@esbuild/sunos-x64": "0.27.7", - "@esbuild/win32-arm64": "0.27.7", - "@esbuild/win32-ia32": "0.27.7", - "@esbuild/win32-x64": "0.27.7" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12.0.0" + "optional": true, + "dependencies": { + "ajv": "^8.0.0" }, "peerDependencies": { - "picomatch": "^3 || ^4" + "ajv": "^8.0.0" }, "peerDependenciesMeta": { - "picomatch": { + "ajv": { "optional": true } } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/ajv-formats-draft2019": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ajv-formats-draft2019/-/ajv-formats-draft2019-1.6.1.tgz", + "integrity": "sha512-JQPvavpkWDvIsBp2Z33UkYCtXCSpW4HD3tAZ+oL4iEFOk9obQZffx0yANwECt6vzr6ET+7HN5czRyqXbnq/u0Q==", "dev": true, - "hasInstallScript": true, "license": "MIT", "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/igniteui-grid-lite": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/igniteui-grid-lite/-/igniteui-grid-lite-0.9.0.tgz", - "integrity": "sha512-pW6MPniC0Up5YmbdB2QVTpPdIp0lkapPfQbnQQmqhtrvGO8Cpf84FQf1s7uMxatCC6FV5w7fgGpriy3t88yNng==", - "license": "MIT", "dependencies": { - "@lit-labs/virtualizer": "~2.1.0", - "@lit/context": "~1.1.5", - "igniteui-webcomponents": "~7.2.0", - "lit": "^3.3.0" + "punycode": "^2.1.1", + "schemes": "^1.4.0", + "smtp-address-parser": "^1.0.3", + "uri-js": "^4.4.1" }, - "engines": { - "node": ">=22" + "peerDependencies": { + "ajv": "*" } }, - "node_modules/igniteui-i18n-core": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/igniteui-i18n-core/-/igniteui-i18n-core-1.0.5.tgz", - "integrity": "sha512-CO5Rqo5uqgyAfIHbFVuBEmo+fYXgLQ7zxRShqAu+ng8kDS5uwWjKeSGWVZjKMBgxmc6ZWMMbdcWIpGZUSOkPsw==", + "node_modules/ansi-regex": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", + "dev": true, "license": "MIT", - "peerDependencies": { - "igniteui-i18n-resources": "1.0.5" + "optional": true, + "engines": { + "node": ">=12" }, - "peerDependenciesMeta": { - "igniteui-i18n-resources": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/igniteui-webcomponents": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/igniteui-webcomponents/-/igniteui-webcomponents-7.2.4.tgz", - "integrity": "sha512-h5hrroBn0kSYCYpj5OH4sKXkFZvdOeqpYnNTKMB5PsqsWexhQICkH5xKjDDj3VPbd135OvzWX5XQN0Nclj2qAQ==", + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, "license": "MIT", - "dependencies": { - "@floating-ui/dom": "^1.7.0", - "@lit-labs/virtualizer": "^2.1.0", - "@lit/context": "^1.1.0", - "igniteui-i18n-core": "^1.0.5", - "lit": "^3.3.0" - }, + "optional": true, "engines": { - "node": ">=22" - }, - "peerDependencies": { - "dompurify": "^3.3.0", - "igniteui-i18n-resources": "^1.0.5", - "marked": "^17.0.0", - "marked-shiki": "^1.2.0", - "shiki": "^3.20.0" + "node": ">=12" }, - "peerDependenciesMeta": { - "dompurify": { - "optional": true - }, - "igniteui-i18n-resources": { - "optional": true - }, - "marked": { - "optional": true - }, - "marked-shiki": { - "optional": true - }, - "shiki": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/lit": { + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/brace-expansion": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cacache": { + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", + "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/fs": "^4.0.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/content-type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz", + "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "license": "(MIT OR WTFPL)", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "dev": true, + "license": "Apache-2.0", + "optional": true + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/fast-uri": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz", + "integrity": "sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/hosted-git-info": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.3.tgz", + "integrity": "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^11.1.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/igniteui-grid-lite": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/igniteui-grid-lite/-/igniteui-grid-lite-0.9.0.tgz", + "integrity": "sha512-pW6MPniC0Up5YmbdB2QVTpPdIp0lkapPfQbnQQmqhtrvGO8Cpf84FQf1s7uMxatCC6FV5w7fgGpriy3t88yNng==", + "license": "MIT", + "dependencies": { + "@lit-labs/virtualizer": "~2.1.0", + "@lit/context": "~1.1.5", + "igniteui-webcomponents": "~7.2.0", + "lit": "^3.3.0" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/igniteui-i18n-core": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/igniteui-i18n-core/-/igniteui-i18n-core-1.0.5.tgz", + "integrity": "sha512-CO5Rqo5uqgyAfIHbFVuBEmo+fYXgLQ7zxRShqAu+ng8kDS5uwWjKeSGWVZjKMBgxmc6ZWMMbdcWIpGZUSOkPsw==", + "license": "MIT", + "peerDependencies": { + "igniteui-i18n-resources": "1.0.5" + }, + "peerDependenciesMeta": { + "igniteui-i18n-resources": { + "optional": true + } + } + }, + "node_modules/igniteui-webcomponents": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/igniteui-webcomponents/-/igniteui-webcomponents-7.2.4.tgz", + "integrity": "sha512-h5hrroBn0kSYCYpj5OH4sKXkFZvdOeqpYnNTKMB5PsqsWexhQICkH5xKjDDj3VPbd135OvzWX5XQN0Nclj2qAQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.0", + "@lit-labs/virtualizer": "^2.1.0", + "@lit/context": "^1.1.0", + "igniteui-i18n-core": "^1.0.5", + "lit": "^3.3.0" + }, + "engines": { + "node": ">=22" + }, + "peerDependencies": { + "dompurify": "^3.3.0", + "igniteui-i18n-resources": "^1.0.5", + "marked": "^17.0.0", + "marked-shiki": "^1.2.0", + "shiki": "^3.20.0" + }, + "peerDependenciesMeta": { + "dompurify": { + "optional": true + }, + "igniteui-i18n-resources": { + "optional": true + }, + "marked": { + "optional": true + }, + "marked-shiki": { + "optional": true + }, + "shiki": { + "optional": true + } + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/ip-address": { + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.0.tgz", + "integrity": "sha512-BGFsyJd5mpXp3rK6jIdADLNgpJUK1jnjzvYF8lK+VyDab9JAmqN0YOKDdP17HlgKb2+ehPgDc8EtnRLbGCAMhA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.5.tgz", + "integrity": "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==", + "dev": true, + "license": "BlueOak-1.0.0", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "optional": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/libxmljs2": { + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/libxmljs2/-/libxmljs2-0.37.0.tgz", + "integrity": "sha512-Xb78V8GZouoZFrq8cCwx7+G3WYOcJG0xb3YUbweSyE4z2EIrQCZMr3Ye/dHn4mESs6YxUMeQeUZm5IXg+iLHog==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bindings": "~1.5.0", + "nan": "~2.22.2", + "node-gyp": "^11.2.0", + "prebuild-install": "^7.1.3" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/lit": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.3.tgz", "integrity": "sha512-fycuvZg/hkpozL00lm1pEJH5nN/lr9ZXd6mJI2HSN4+Bzc+LDNdEApJ6HFbPkdFNHLvOplIIuJvxkS4XUxqirw==", "license": "BSD-3-Clause", "dependencies": { - "@lit/reactive-element": "^2.1.0", - "lit-element": "^4.2.0", - "lit-html": "^3.3.0" + "@lit/reactive-element": "^2.1.0", + "lit-element": "^4.2.0", + "lit-html": "^3.3.0" + } + }, + "node_modules/lit-element": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.2.tgz", + "integrity": "sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.5.0", + "@lit/reactive-element": "^2.1.0", + "lit-html": "^3.3.0" + } + }, + "node_modules/lit-html": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.3.tgz", + "integrity": "sha512-el8M6jK2o3RXBnrSHX3ZKrsN8zEV63pSExTO1wYJz7QndGYZ8353e2a5PPX+qHe2aGayfnchQmkAojaWAREOIA==", + "license": "BSD-3-Clause", + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/make-fetch-happen": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", + "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "ssri": "^12.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "optional": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-fetch": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.1.tgz", + "integrity": "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^3.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.7.tgz", + "integrity": "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==", + "dev": true, + "license": "BlueOak-1.0.0", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/moo": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.3.tgz", + "integrity": "sha512-m2fmM2dDm7GZQsY7KK2cme8agi+AAljILjQnof7p1ZMDe6dQ4bdnSMx0cPppudoeNv5hEFQirN6u+O4fDE0IWA==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/nan": { + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.2.tgz", + "integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/nanoid": { + "version": "3.3.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/nearley": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6" + }, + "bin": { + "nearley-railroad": "bin/nearley-railroad.js", + "nearley-test": "bin/nearley-test.js", + "nearley-unparse": "bin/nearley-unparse.js", + "nearleyc": "bin/nearleyc.js" + }, + "funding": { + "type": "individual", + "url": "https://nearley.js.org/#give-to-nearley" + } + }, + "node_modules/negotiator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.1.0.tgz", + "integrity": "sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "content-type": "^2.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/node-abi": { + "version": "3.96.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.96.0.tgz", + "integrity": "sha512-rebQ/lz7i0EkoLzUVSrKRzA69zMkwLp95kKMWoMDkkM00Suxz0D7zEQPwRml5fQum24mj7bPvmlgLAmu2JCiYg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp": { + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.5.0.tgz", + "integrity": "sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^14.0.3", + "nopt": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "tar": "^7.4.3", + "tinyglobby": "^0.2.12", + "which": "^5.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/nopt": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "^3.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/normalize-package-data": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-8.0.0.tgz", + "integrity": "sha512-RWk+PI433eESQ7ounYxIp67CYuVsS1uYSonX3kA6ps/3LWfjVQa/ptEg6Y3T6uAMq1mWpX9PQ+qx+QaHpsc7gQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^9.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-map": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.7.tgz", + "integrity": "sha512-VaWRu2i4FJNRtiRWCuuQRgfQ1B7a6+gMSrO+3j0EQi/k0ULfS9kosRxGoiqwzIjZTDI02tGfk5mXXltLg6QtfQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0", + "optional": true + }, + "node_modules/packageurl-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/packageurl-js/-/packageurl-js-2.0.1.tgz", + "integrity": "sha512-N5ixXjzTy4QDQH0Q9YFjqIWd6zH6936Djpl2m9QNFmDv5Fum8q8BjkpAcHNMzOFE0IwQrFhJWex3AN6kS0OSwg==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "optional": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.24", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.24.tgz", + "integrity": "sha512-8RyVklq0owXUTa4xlpzu4l9AaVKIdQvAcOHZWaMh98HgySsUtxRVf/chRe3dsSLqb6i40BzGRzEUddRaI+9TSw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proc-log": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", + "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", + "dev": true, + "license": "ISC", + "optional": true, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==", + "dev": true, + "license": "CC0-1.0", + "optional": true + }, + "node_modules/randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rollup": { + "version": "4.62.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.3.tgz", + "integrity": "sha512-Gu0c0iH9FzgX1L1t7ByIbbS3Vmdz+6KHm/EsqmmC71gUQ82yvZRkTK6XzrFObSka91WUVdynqp6nsfilzr5k6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.3", + "@rollup/rollup-android-arm64": "4.62.3", + "@rollup/rollup-darwin-arm64": "4.62.3", + "@rollup/rollup-darwin-x64": "4.62.3", + "@rollup/rollup-freebsd-arm64": "4.62.3", + "@rollup/rollup-freebsd-x64": "4.62.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.3", + "@rollup/rollup-linux-arm-musleabihf": "4.62.3", + "@rollup/rollup-linux-arm64-gnu": "4.62.3", + "@rollup/rollup-linux-arm64-musl": "4.62.3", + "@rollup/rollup-linux-loong64-gnu": "4.62.3", + "@rollup/rollup-linux-loong64-musl": "4.62.3", + "@rollup/rollup-linux-ppc64-gnu": "4.62.3", + "@rollup/rollup-linux-ppc64-musl": "4.62.3", + "@rollup/rollup-linux-riscv64-gnu": "4.62.3", + "@rollup/rollup-linux-riscv64-musl": "4.62.3", + "@rollup/rollup-linux-s390x-gnu": "4.62.3", + "@rollup/rollup-linux-x64-gnu": "4.62.3", + "@rollup/rollup-linux-x64-musl": "4.62.3", + "@rollup/rollup-openbsd-x64": "4.62.3", + "@rollup/rollup-openharmony-arm64": "4.62.3", + "@rollup/rollup-win32-arm64-msvc": "4.62.3", + "@rollup/rollup-win32-ia32-msvc": "4.62.3", + "@rollup/rollup-win32-x64-gnu": "4.62.3", + "@rollup/rollup-win32-x64-msvc": "4.62.3", + "fsevents": "~2.3.2" } }, - "node_modules/lit-element": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.2.tgz", - "integrity": "sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==", - "license": "BSD-3-Clause", + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/schemes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/schemes/-/schemes-1.4.0.tgz", + "integrity": "sha512-ImFy9FbCsQlVgnE3TCWmLPCFnVzx0lHL/l+umHplDqAKd0dzFpnS6lFZIpagBlYhKwzVmlV36ec0Y1XTu8JBAQ==", + "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.5.0", - "@lit/reactive-element": "^2.1.0", - "lit-html": "^3.3.0" + "extend": "^3.0.0" } }, - "node_modules/lit-html": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.3.tgz", - "integrity": "sha512-el8M6jK2o3RXBnrSHX3ZKrsN8zEV63pSExTO1wYJz7QndGYZ8353e2a5PPX+qHe2aGayfnchQmkAojaWAREOIA==", + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "optional": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/smtp-address-parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/smtp-address-parser/-/smtp-address-parser-1.1.0.tgz", + "integrity": "sha512-Gz11jbNU0plrReU9Sj7fmshSBxxJ9ShdD2q4ktHIHo/rpTH6lFyQoYHYKINPJtPe8aHFnsbtW46Ls0tCCBsIZg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "nearley": "^2.20.1" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/socks": { + "version": "2.8.10", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.10.tgz", + "integrity": "sha512-e0VyvkVTwVYViNovRkZ9aodhxVlyoMn7eJhVUPxZ+eK9P/7CBkxvvsBOHqFPEH416726W8tLXXXjKwqgTErrCQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ip-address": "^10.1.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", "dependencies": { - "@types/trusted-types": "^2.0.2" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-correct/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/ssri": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/nanoid": { - "version": "3.3.16", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", - "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, + "optional": true, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=8" } }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, - "license": "ISC" + "license": "MIT", + "optional": true }, - "node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^6.2.2" + }, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/postcss": { - "version": "8.5.24", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.24.tgz", - "integrity": "sha512-8RyVklq0owXUTa4xlpzu4l9AaVKIdQvAcOHZWaMh98HgySsUtxRVf/chRe3dsSLqb6i40BzGRzEUddRaI+9TSw==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", + "optional": true, "dependencies": { - "nanoid": "^3.3.16", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" + "ansi-regex": "^5.0.1" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=8" } }, - "node_modules/rollup": { - "version": "4.62.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.3.tgz", - "integrity": "sha512-Gu0c0iH9FzgX1L1t7ByIbbS3Vmdz+6KHm/EsqmmC71gUQ82yvZRkTK6XzrFObSka91WUVdynqp6nsfilzr5k6Q==", + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", - "dependencies": { - "@types/estree": "1.0.9" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, + "optional": true, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.62.3", - "@rollup/rollup-android-arm64": "4.62.3", - "@rollup/rollup-darwin-arm64": "4.62.3", - "@rollup/rollup-darwin-x64": "4.62.3", - "@rollup/rollup-freebsd-arm64": "4.62.3", - "@rollup/rollup-freebsd-x64": "4.62.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.62.3", - "@rollup/rollup-linux-arm-musleabihf": "4.62.3", - "@rollup/rollup-linux-arm64-gnu": "4.62.3", - "@rollup/rollup-linux-arm64-musl": "4.62.3", - "@rollup/rollup-linux-loong64-gnu": "4.62.3", - "@rollup/rollup-linux-loong64-musl": "4.62.3", - "@rollup/rollup-linux-ppc64-gnu": "4.62.3", - "@rollup/rollup-linux-ppc64-musl": "4.62.3", - "@rollup/rollup-linux-riscv64-gnu": "4.62.3", - "@rollup/rollup-linux-riscv64-musl": "4.62.3", - "@rollup/rollup-linux-s390x-gnu": "4.62.3", - "@rollup/rollup-linux-x64-gnu": "4.62.3", - "@rollup/rollup-linux-x64-musl": "4.62.3", - "@rollup/rollup-openbsd-x64": "4.62.3", - "@rollup/rollup-openharmony-arm64": "4.62.3", - "@rollup/rollup-win32-arm64-msvc": "4.62.3", - "@rollup/rollup-win32-ia32-msvc": "4.62.3", - "@rollup/rollup-win32-x64-gnu": "4.62.3", - "@rollup/rollup-win32-x64-msvc": "4.62.3", - "fsevents": "~2.3.2" + "node": ">=8" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "optional": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "node_modules/tar": { + "version": "7.5.22", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz", + "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==", "dev": true, - "license": "BSD-3-Clause", + "license": "BlueOak-1.0.0", + "optional": true, + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/tar-fs": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz", + "integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" } }, "node_modules/terser": { @@ -1357,6 +3463,89 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/unique-filename": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "unique-slug": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/unique-slug": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, "node_modules/vite": { "version": "7.3.6", "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz", @@ -1431,6 +3620,163 @@ "optional": true } } + }, + "node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/xmlbuilder2": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-4.0.3.tgz", + "integrity": "sha512-bx8Q1STctnNaaDymWnkfQLKofs0mGNN7rLLapJlGuV3VlvegD7Ls4ggMjE3aUSWItCCzU0PEv45lI87iSigiCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oozcitak/dom": "^2.0.2", + "@oozcitak/infra": "^2.0.2", + "@oozcitak/util": "^10.0.0", + "js-yaml": "^4.1.1" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "optional": true, + "engines": { + "node": ">=18" + } } } } diff --git a/src/IgniteUI.Blazor.GridLite/package.json b/src/IgniteUI.Blazor.GridLite/package.json index aa50b9a..0752406 100644 --- a/src/IgniteUI.Blazor.GridLite/package.json +++ b/src/IgniteUI.Blazor.GridLite/package.json @@ -12,6 +12,7 @@ "dev": "vite build --watch" }, "devDependencies": { + "@cyclonedx/cyclonedx-npm": "6.0.1", "terser": "^5.44.1", "vite": "^7.3.6" },