From b6619231e59b73a52007147f67603dce09bd2353 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Wed, 29 Jul 2026 15:39:49 +0200 Subject: [PATCH 01/13] Add Microsoft .NET redistribution notice (#84) --- MICROSOFT-DOTNET-REDISTRIBUTION.txt | 98 +++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 MICROSOFT-DOTNET-REDISTRIBUTION.txt diff --git a/MICROSOFT-DOTNET-REDISTRIBUTION.txt b/MICROSOFT-DOTNET-REDISTRIBUTION.txt new file mode 100644 index 00000000..a894c485 --- /dev/null +++ b/MICROSOFT-DOTNET-REDISTRIBUTION.txt @@ -0,0 +1,98 @@ +SIGHTADAPT MICROSOFT .NET REDISTRIBUTION NOTICE + +Reviewed release configuration + +SightAdapt version: 0.5.0.50-alpha +.NET SDK used to build: 8.0.423 +.NET Runtime: 8.0.29 +Windows Desktop Runtime: 8.0.29 +Target framework: net8.0-windows10.0.19041.0 +Runtime identifier: win-x64 +Publication: self-contained, single-file Windows application +Maintainer review date: 2026-07-29 + +1. Separate licenses + +SightAdapt's own source code is licensed under the MIT License in LICENSE.txt. +That license does not replace, expand or modify the separate terms governing +Microsoft .NET components included in the binary distribution. + +The Microsoft license text and exact release evidence are provided in: + +- DOTNET-LICENSE-NOTICE.txt +- THIRD-PARTY-NOTICES.txt +- DOTNET-NOTICE-METADATA.json + +If this summary conflicts with those files or Microsoft's authoritative terms, +the authoritative Microsoft terms control for Microsoft components. + +2. How Microsoft components are distributed + +Microsoft .NET components are included in object-code form only as part of the +SightAdapt application. They are not offered, branded or distributed by the +SightAdapt project as a standalone Microsoft .NET product. + +SightAdapt and its distributors must preserve this notice, the imported +Microsoft license text and all applicable third-party notices in every copy of +the application package. + +3. Recipient conditions for Microsoft components + +To the extent permitted by applicable law, recipients and downstream +distributors must not: + +- remove, minimize, block or alter Microsoft or supplier notices; +- work around technical limitations in Microsoft components; +- reverse engineer, decompile or disassemble Microsoft components except where + applicable law or third-party licensing terms expressly permit it; +- use Microsoft trademarks in a product name or imply that SightAdapt is made, + sponsored, certified or endorsed by Microsoft; +- redistribute Microsoft components as a standalone offering; +- use or distribute Microsoft components unlawfully or contrary to applicable + export-control restrictions; +- impose source-disclosure or reciprocal-license conditions on Microsoft + distributable code where Microsoft's terms prohibit doing so. + +A downstream distributor may redistribute the included Microsoft components +only as part of an intact SightAdapt application distribution, under terms that +protect those components at least as much as Microsoft's applicable agreement. +The downstream distributor is responsible for claims arising from its own +packaging, representations, modifications or distribution, except to the extent +a claim is based solely on unmodified Microsoft distributable code. + +4. No Microsoft endorsement or support + +Microsoft does not publish, sponsor, certify or endorse SightAdapt. Microsoft +trademarks and product names identify compatibility or included components only. +Support for SightAdapt is provided, if at all, by the SightAdapt project and not +by Microsoft. + +5. Warranty and liability for Microsoft components + +Microsoft components are licensed on an "as-is" basis under Microsoft's terms. +Microsoft provides no additional warranty, guarantee or support through +SightAdapt. Microsoft's warranty exclusions and limitations of remedies apply +subject to mandatory consumer and other rights that cannot lawfully be excluded +in the recipient's jurisdiction. + +6. Authoritative sources + +Microsoft .NET product-distribution licensing model: +https://github.com/dotnet/core/blob/main/license-information.md + +Microsoft .NET Library License Terms: +https://dotnet.microsoft.com/en-us/dotnet_library_license.htm + +The exact source package, version mapping and checksums used by this build are +recorded in DOTNET-NOTICE-METADATA.json. + +7. Review status and release gate + +This notice records the project's technical compliance implementation and a +maintainer review of the identified distribution terms. It is not a legal +opinion and does not claim review by qualified legal counsel. + +Before any official production or paid distribution, the complete resulting +text and package must receive the qualified legal review required by SightAdapt +Issue #93. Until that sign-off exists, production and paid distribution remain +blocked. From 21e441ad60f504576dafd0f2681c81f4610983b4 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Wed, 29 Jul 2026 15:41:01 +0200 Subject: [PATCH 02/13] Document .NET redistribution analysis (#84) --- docs/legal/DOTNET-REDISTRIBUTION.md | 116 ++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 docs/legal/DOTNET-REDISTRIBUTION.md diff --git a/docs/legal/DOTNET-REDISTRIBUTION.md b/docs/legal/DOTNET-REDISTRIBUTION.md new file mode 100644 index 00000000..5e05f983 --- /dev/null +++ b/docs/legal/DOTNET-REDISTRIBUTION.md @@ -0,0 +1,116 @@ +# Microsoft .NET redistribution analysis + +## Status + +| Field | Value | +|---|---| +| Maintainer review date | 2026-07-29 | +| SightAdapt version | `0.5.0.50-alpha` | +| .NET SDK | `8.0.423` | +| .NET Runtime | `8.0.29` | +| Windows Desktop Runtime | `8.0.29` | +| Target framework | `net8.0-windows10.0.19041.0` | +| Runtime identifier | `win-x64` | +| Publish mode | self-contained, single-file | +| Professional legal review | Required before production or paid distribution under Issue #93; not yet claimed by this document | + +This document records the project's technical redistribution analysis. It is not legal advice and is not evidence of review by qualified legal counsel. + +## Authoritative sources + +The review uses these official Microsoft sources: + +1. [.NET license information](https://github.com/dotnet/core/blob/main/license-information.md), which states that Windows product distributions and runtime packs use the .NET Library License and that self-contained applications embed parts of the runtime; +2. [.NET Library License Terms](https://dotnet.microsoft.com/en-us/dotnet_library_license.htm), which contains the applicable distribution rights, requirements, restrictions, warranty terms and regional qualifications; +3. the exact [.NET 8 release metadata](https://builds.dotnet.microsoft.com/dotnet/release-metadata/8.0/releases.json), which maps runtime `8.0.29`, Windows Desktop Runtime `8.0.29` and SDK `8.0.423`; +4. the hash-verified official SDK archive identified in each package's `DOTNET-NOTICE-METADATA.json`, which supplies the exact imported Microsoft license and third-party notice text; +5. the actual `project.assets.json` produced by restore, which identifies the runtime packs selected for the release build. + +The generated files in the final package preserve the authoritative text and evidence. This analysis paraphrases operational requirements and does not replace those files. + +## Microsoft-origin component inventory + +### Included in the self-contained binary + +The current application has no direct third-party NuGet package references. The Microsoft-origin runtime content is selected by the SDK through these exact runtime-pack identities: + +| Component family | Exact release identity | Included purpose | Distribution position | +|---|---|---|---| +| .NET application host and host policy | `Microsoft.NETCore.App.Runtime.win-x64/8.0.29` and associated host assets | Starts and hosts the self-contained managed application | Distributed in object-code form only as part of SightAdapt under the .NET Library License | +| .NET managed runtime and base libraries | `Microsoft.NETCore.App.Runtime.win-x64/8.0.29` | CLR, garbage collector, framework libraries and native runtime support | Distributed in object-code form only as part of SightAdapt under the .NET Library License and imported third-party notices | +| Windows Desktop / Windows Forms runtime | `Microsoft.WindowsDesktop.App.Runtime.win-x64/8.0.29` | Windows Forms UI and Windows desktop framework support | Distributed in object-code form only as part of SightAdapt under the .NET Library License and imported third-party notices | +| Runtime third-party components | Components covered by the official `ThirdPartyNotices.txt` for the `.NET 8.0.29 / SDK 8.0.423` release train | Native and managed dependencies incorporated into the Microsoft runtime packs | Governed by the separate licenses and notices preserved in `THIRD-PARTY-NOTICES.txt` | + +The precise restore identities are recorded in `DOTNET-NOTICE-METADATA.json`. The single-file publisher may embed managed assemblies and native components inside `SightAdapt.exe`; embedding does not change their separate licensing status. + +The SDK may record `Microsoft.AspNetCore.App.Runtime.win-x64/8.0.29` as a framework download dependency. SightAdapt does not use ASP.NET Core APIs. That restore record is preserved for auditability, but a component is classified as shipped only when the final package/SBOM identifies it as present. + +### Microsoft-origin dependencies not redistributed as product components + +| Component | Role | Distribution status | +|---|---|---| +| .NET SDK `8.0.423` | Restore, compile, test and publish; source of matching legal-text bundle | Build infrastructure, not shipped as the SightAdapt application | +| `Microsoft.Windows.SDK.NET.Ref` reference pack | Compile-time Windows API metadata | Reference/build input, not shipped as an independent runtime component | +| `Microsoft.NET.Test.Sdk`, MSTest adapter/framework | Automated test infrastructure | Test-only dependencies, not shipped | +| GitHub Actions maintained by GitHub/Microsoft | CI checkout, SDK setup and artifact upload | CI infrastructure, not shipped in the application | +| Windows operating-system APIs and system DLLs | Magnification, window management, shell, monitor, input and process services | Supplied by Windows; referenced at runtime but not copied into the package as SightAdapt redistributables | + +## Applicable terms and redistribution conditions + +Microsoft's Windows .NET product distributions and runtime packs use the .NET Library License. For the reviewed configuration, the project adopts these controls: + +1. Microsoft components are distributed in object-code form only as part of SightAdapt, never as a standalone .NET distribution. +2. The package preserves Microsoft's license text, the exact-version third-party notices and machine-readable source/checksum evidence. +3. The SightAdapt MIT License is clearly limited to SightAdapt project code. It does not purport to relicense Microsoft components. +4. Recipients and downstream distributors receive `MICROSOFT-DOTNET-REDISTRIBUTION.txt`, containing conditions intended to protect Microsoft distributable code at least as much as the applicable Microsoft agreement. +5. Downstream redistribution must preserve the complete legal bundle and keep Microsoft components within an intact application distribution. +6. The project does not use Microsoft trademarks in the application name and does not imply Microsoft sponsorship, certification or endorsement. +7. The project does not modify Microsoft distributable source code or subject Microsoft code to a reciprocal or source-disclosure license. +8. Recipients may not remove notices, bypass technical limitations, redistribute the Microsoft components standalone or use them unlawfully. +9. Distributors are responsible for claims arising from their own application distribution except where a claim is based solely on unmodified Microsoft distributable code, reflecting the distributor responsibility in Microsoft's terms. +10. Applicable export-control obligations and non-waivable local consumer rights remain in force. +11. Microsoft components are provided under Microsoft's as-is, support, warranty and remedy provisions, subject to mandatory regional law. + +## Package implementation + +Every SightAdapt binary package must include these separate files at its root: + +| File | Function | +|---|---| +| `LICENSE.txt` | MIT License for SightAdapt project code | +| `MICROSOFT-DOTNET-REDISTRIBUTION.txt` | Operational end-user and downstream-distributor notice for Microsoft components | +| `DOTNET-LICENSE-NOTICE.txt` | Exact Microsoft license text imported from the hash-verified official SDK archive | +| `THIRD-PARTY-NOTICES.txt` | Exact Microsoft/.NET third-party notices imported from the same archive | +| `DOTNET-NOTICE-METADATA.json` | Exact versions, runtime packs, source URLs and checksums | +| `DEPENDENCIES.md` | Human-readable shipped/build/platform dependency inventory | + +The files are readable without executing SightAdapt. `release/required-files.txt` and `tools/test-release-package.ps1` enforce their presence and consistency in the final ZIP. + +## Review triggers + +Repeat this analysis and update the package notice when any of the following changes: + +- .NET SDK version; +- .NET Runtime or Windows Desktop Runtime version; +- target framework or minimum Windows target; +- runtime identifier or architecture; +- framework-dependent versus self-contained publication; +- single-file, trimming, ReadyToRun, Native AOT or extraction settings; +- restored runtime-pack inventory; +- any new Microsoft package, SDK, native binary or redistributable; +- product name, Microsoft compatibility claims or distribution channels; +- Microsoft licensing, privacy, export or support terms. + +The verifier intentionally embeds the reviewed versions and configuration in the package notice. A version or publish-setting change therefore fails CI until the redistribution notice and analysis are reviewed and updated. + +## Professional review gate + +This implementation satisfies the repository's engineering and documentation controls, but it does not replace professional legal advice. Before an official production release, paid distribution, commercial support offering or bundled redistribution by a commercial partner, qualified legal counsel must review: + +- this analysis; +- `MICROSOFT-DOTNET-REDISTRIBUTION.txt`; +- the exact generated package legal bundle; +- the intended distribution channels and end-user terms; +- any regional consumer, export or commercial-law implications. + +That external sign-off is the explicit release gate tracked by Issue #93. No statement in this repository should be interpreted as claiming that the sign-off has already occurred. From 6920a9cc1ac59f92dfa1d09b8d02b7d950a74015 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Wed, 29 Jul 2026 15:41:40 +0200 Subject: [PATCH 03/13] Verify .NET redistribution controls (#84) --- tools/verify-dotnet-redistribution.ps1 | 100 +++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 tools/verify-dotnet-redistribution.ps1 diff --git a/tools/verify-dotnet-redistribution.ps1 b/tools/verify-dotnet-redistribution.ps1 new file mode 100644 index 00000000..45c49238 --- /dev/null +++ b/tools/verify-dotnet-redistribution.ps1 @@ -0,0 +1,100 @@ +[CmdletBinding()] +param() + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +$root = Split-Path -Parent $PSScriptRoot +$noticePath = Join-Path $root 'MICROSOFT-DOTNET-REDISTRIBUTION.txt' +$analysisPath = Join-Path $root 'docs\legal\DOTNET-REDISTRIBUTION.md' +$manifestPath = Join-Path $root 'release\required-files.txt' +$projectPath = Join-Path $root 'src\SightAdapt\SightAdapt.csproj' + +[xml]$props = Get-Content -LiteralPath (Join-Path $root 'Directory.Build.props') +$group = $props.Project.PropertyGroup +$productVersion = [string]$group.SightAdaptProductVersion +$sdkVersion = [string]$group.SightAdaptDotNetSdkVersion +$runtimeVersion = [string]$group.SightAdaptDotNetRuntimeVersion +$rid = [string]$group.SightAdaptRuntimeIdentifier +$publishMode = [string]$group.SightAdaptPublishMode + +[xml]$project = Get-Content -LiteralPath $projectPath +$projectGroup = @($project.Project.PropertyGroup) | Select-Object -First 1 +$targetFramework = [string]$projectGroup.TargetFramework + +$notice = Get-Content -LiteralPath $noticePath -Raw +$analysis = Get-Content -LiteralPath $analysisPath -Raw +$manifest = Get-Content -LiteralPath $manifestPath -Raw +$projectText = Get-Content -LiteralPath $projectPath -Raw + +$noticeExpectations = @( + "SightAdapt version: $productVersion", + ".NET SDK used to build: $sdkVersion", + ".NET Runtime: $runtimeVersion", + "Windows Desktop Runtime: $runtimeVersion", + "Target framework: $targetFramework", + "Runtime identifier: $rid", + 'Publication: self-contained, single-file Windows application', + 'Microsoft .NET components are included in object-code form only as part of the', + 'not offered, branded or distributed by the', + 'standalone Microsoft .NET product', + 'does not replace, expand or modify the separate terms', + 'Microsoft does not publish, sponsor, certify or endorse SightAdapt', + 'https://github.com/dotnet/core/blob/main/license-information.md', + 'https://dotnet.microsoft.com/en-us/dotnet_library_license.htm', + 'not a legal opinion', + 'Issue #93' +) +foreach ($expectation in $noticeExpectations) { + if (-not $notice.Contains($expectation, [StringComparison]::Ordinal)) { + throw "MICROSOFT-DOTNET-REDISTRIBUTION.txt is missing required text: '$expectation'." + } +} + +$analysisExpectations = @( + "| .NET SDK | `$sdkVersion` |", + "| .NET Runtime | `$runtimeVersion` |", + "| Windows Desktop Runtime | `$runtimeVersion` |", + "| Target framework | `$targetFramework` |", + "| Runtime identifier | `$rid` |", + "Microsoft.NETCore.App.Runtime.$rid/$runtimeVersion", + "Microsoft.WindowsDesktop.App.Runtime.$rid/$runtimeVersion", + 'Maintainer review date | 2026-07-29', + 'Professional legal review | Required before production or paid distribution under Issue #93', + 'The SightAdapt MIT License is clearly limited to SightAdapt project code', + 'Repeat this analysis and update the package notice' +) +foreach ($expectation in $analysisExpectations) { + if (-not $analysis.Contains($expectation, [StringComparison]::Ordinal)) { + throw "docs/legal/DOTNET-REDISTRIBUTION.md is missing required text: '$expectation'." + } +} + +if (-not $manifest.Contains( + 'MICROSOFT-DOTNET-REDISTRIBUTION.txt', + [StringComparison]::Ordinal)) { + throw 'The release manifest does not require MICROSOFT-DOTNET-REDISTRIBUTION.txt.' +} + +if (-not $projectText.Contains( + '..\..\MICROSOFT-DOTNET-REDISTRIBUTION.txt', + [StringComparison]::Ordinal) -or + -not $projectText.Contains( + 'Link="MICROSOFT-DOTNET-REDISTRIBUTION.txt"', + [StringComparison]::Ordinal)) { + throw 'SightAdapt.csproj does not publish MICROSOFT-DOTNET-REDISTRIBUTION.txt.' +} + +$forbiddenPlaceholders = @('TODO', 'TBD', '', '', '[insert') +foreach ($placeholder in $forbiddenPlaceholders) { + if ($notice.Contains($placeholder, [StringComparison]::OrdinalIgnoreCase) -or + $analysis.Contains($placeholder, [StringComparison]::OrdinalIgnoreCase)) { + throw "Redistribution documentation contains unresolved placeholder '$placeholder'." + } +} + +if ($publishMode -ne 'self-contained-single-file') { + throw "The reviewed notice assumes self-contained-single-file, but Directory.Build.props specifies '$publishMode'." +} + +Write-Host "Microsoft .NET redistribution controls verified for SightAdapt $productVersion, SDK $sdkVersion, runtime $runtimeVersion, $rid." From d3e8bb432b95d37595b528c42eb10b60fe036eaa Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Wed, 29 Jul 2026 15:42:05 +0200 Subject: [PATCH 04/13] Publish Microsoft redistribution notice (#84) --- src/SightAdapt/SightAdapt.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/SightAdapt/SightAdapt.csproj b/src/SightAdapt/SightAdapt.csproj index f30c95b8..a2566d73 100644 --- a/src/SightAdapt/SightAdapt.csproj +++ b/src/SightAdapt/SightAdapt.csproj @@ -47,6 +47,10 @@ Link="DOTNET-LICENSE-NOTICE.txt" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" /> + Date: Wed, 29 Jul 2026 15:42:17 +0200 Subject: [PATCH 05/13] Require Microsoft redistribution notice (#84) --- release/required-files.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/release/required-files.txt b/release/required-files.txt index 54f25859..74c414cd 100644 --- a/release/required-files.txt +++ b/release/required-files.txt @@ -5,5 +5,6 @@ LICENSE.txt THIRD-PARTY-NOTICES.txt DOTNET-LICENSE-NOTICE.txt DOTNET-NOTICE-METADATA.json +MICROSOFT-DOTNET-REDISTRIBUTION.txt DEPENDENCIES.md PRIVACY.md From 6596ced9484a875e169e2dc2ecbba004d9f0a6b4 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Wed, 29 Jul 2026 15:43:12 +0200 Subject: [PATCH 06/13] Validate Microsoft redistribution terms in final archive (#84) --- tools/test-release-package.ps1 | 48 ++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/tools/test-release-package.ps1 b/tools/test-release-package.ps1 index 43b3eb59..ae83aea0 100644 --- a/tools/test-release-package.ps1 +++ b/tools/test-release-package.ps1 @@ -35,12 +35,15 @@ if ($requiredFiles.Count -eq 0) { [xml]$props = Get-Content -LiteralPath (Join-Path $root 'Directory.Build.props') $group = $props.Project.PropertyGroup +[xml]$project = Get-Content -LiteralPath (Join-Path $root 'src\SightAdapt\SightAdapt.csproj') +$projectGroup = @($project.Project.PropertyGroup) | Select-Object -First 1 $expectedMetadata = @{ productVersion = [string]$group.SightAdaptProductVersion sdkVersion = [string]$group.SightAdaptDotNetSdkVersion runtimeVersion = [string]$group.SightAdaptDotNetRuntimeVersion runtimeIdentifier = [string]$group.SightAdaptRuntimeIdentifier publishMode = [string]$group.SightAdaptPublishMode + targetFramework = [string]$projectGroup.TargetFramework } $failures = [System.Collections.Generic.List[string]]::new() @@ -125,11 +128,17 @@ try { if ($textEntries.ContainsKey($metadataKey)) { try { $noticeMetadata = $textEntries[$metadataKey] | ConvertFrom-Json - foreach ($expected in $expectedMetadata.GetEnumerator()) { - $actual = [string]$noticeMetadata.($expected.Key) - if ($actual -ne [string]$expected.Value) { + foreach ($expectedName in @( + 'productVersion', + 'sdkVersion', + 'runtimeVersion', + 'runtimeIdentifier', + 'publishMode')) { + $actual = [string]$noticeMetadata.($expectedName) + $expected = [string]$expectedMetadata[$expectedName] + if ($actual -ne $expected) { $failures.Add( - "DOTNET-NOTICE-METADATA.json has $($expected.Key)='$actual'; expected '$($expected.Value)'.") + "DOTNET-NOTICE-METADATA.json has $expectedName='$actual'; expected '$expected'.") } } @@ -175,6 +184,35 @@ try { $failures.Add('THIRD-PARTY-NOTICES.txt does not identify the pinned runtime version.') } } + + $redistributionKey = 'microsoft-dotnet-redistribution.txt' + if ($textEntries.ContainsKey($redistributionKey)) { + $redistributionText = [string]$textEntries[$redistributionKey] + $redistributionExpectations = @( + "SightAdapt version: $($expectedMetadata.productVersion)", + ".NET SDK used to build: $($expectedMetadata.sdkVersion)", + ".NET Runtime: $($expectedMetadata.runtimeVersion)", + "Windows Desktop Runtime: $($expectedMetadata.runtimeVersion)", + "Target framework: $($expectedMetadata.targetFramework)", + "Runtime identifier: $($expectedMetadata.runtimeIdentifier)", + 'Publication: self-contained, single-file Windows application', + 'SightAdapt''s own source code is licensed under the MIT License', + 'not offered, branded or distributed by the', + 'standalone Microsoft .NET product', + 'Microsoft does not publish, sponsor, certify or endorse SightAdapt', + 'https://dotnet.microsoft.com/en-us/dotnet_library_license.htm', + 'not a legal opinion', + 'Issue #93' + ) + foreach ($expectation in $redistributionExpectations) { + if (-not $redistributionText.Contains( + $expectation, + [StringComparison]::Ordinal)) { + $failures.Add( + "MICROSOFT-DOTNET-REDISTRIBUTION.txt is missing required text '$expectation'.") + } + } + } } finally { $archive.Dispose() @@ -186,6 +224,6 @@ if ($failures.Count -gt 0) { } Write-Host ( - "Release package verified: {0} required files are present, readable and consistent with the pinned .NET release in {1}." -f + "Release package verified: {0} required files are present, readable and consistent with the pinned .NET release and redistribution controls in {1}." -f $requiredFiles.Count, $resolvedArchive) From 86eac287e033eb5f2724971f5e72bc2a66b174bf Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Wed, 29 Jul 2026 15:43:48 +0200 Subject: [PATCH 07/13] Verify .NET redistribution position in CI (#84) --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c96389ec..f954b2a2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,6 +37,10 @@ jobs: shell: pwsh run: .\tools\verify-release-metadata.ps1 -WriteGitHubOutput + - name: Verify Microsoft .NET redistribution controls + shell: pwsh + run: .\tools\verify-dotnet-redistribution.ps1 + - name: Restore application run: dotnet restore src/SightAdapt/SightAdapt.csproj From 44086816357b2a876619e0283f204dbdd58d0af6 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Wed, 29 Jul 2026 15:45:15 +0200 Subject: [PATCH 08/13] Document Microsoft redistribution package terms (#84) --- docs/PACKAGING.md | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/docs/PACKAGING.md b/docs/PACKAGING.md index 9a81a5b0..93c7177c 100644 --- a/docs/PACKAGING.md +++ b/docs/PACKAGING.md @@ -15,10 +15,11 @@ Every package must place the following files at the package root so they can be | File | Purpose | |---|---| | `SightAdapt.exe` | Application executable | -| `LICENSE.txt` | SightAdapt MIT License | +| `LICENSE.txt` | SightAdapt MIT License; applies to SightAdapt project code, not Microsoft redistributables | | `THIRD-PARTY-NOTICES.txt` | Exact-version notices imported from the reviewed Microsoft .NET release distribution | | `DOTNET-LICENSE-NOTICE.txt` | Exact-version Microsoft .NET license text and source metadata | | `DOTNET-NOTICE-METADATA.json` | Machine-readable SDK, runtime, RID, runtime-pack, source and checksum evidence | +| `MICROSOFT-DOTNET-REDISTRIBUTION.txt` | End-user and downstream-distributor conditions that keep Microsoft components separate from SightAdapt's MIT license | | `DEPENDENCIES.md` | Human-readable inventory of shipped, platform and development dependencies | | `PRIVACY.md` | Application privacy and local-data notice | @@ -37,11 +38,11 @@ The same legal-document bundle is required for: Installers and store packages may additionally display or register legal information through platform-specific metadata, but that does not replace including the files in the installed or unpacked application directory. -Release mirrors must copy the verified archive without removing, renaming or replacing the legal files. A third-party repackager must preserve the notices and add any notices required by its own packaging layer. +Release mirrors must copy the verified archive without removing, renaming or replacing the legal files. A downstream distributor may redistribute Microsoft components only as part of an intact SightAdapt application package and must preserve terms that protect the Microsoft distributable code at least as much as the applicable Microsoft agreement. ## Publish behavior -`src/SightAdapt/SightAdapt.csproj` copies the legal baseline into the publish directory. `tools/generate-dotnet-notices.ps1` must then replace the baseline .NET files with exact-version material and add the metadata record before packaging. +`src/SightAdapt/SightAdapt.csproj` copies the legal baseline and redistribution notice into the publish directory. `tools/generate-dotnet-notices.ps1` then replaces the baseline .NET files with exact-version material and adds the metadata record before packaging. The expected publish layout begins with: @@ -52,6 +53,7 @@ artifacts/win-x64/ ├── THIRD-PARTY-NOTICES.txt ├── DOTNET-LICENSE-NOTICE.txt ├── DOTNET-NOTICE-METADATA.json +├── MICROSOFT-DOTNET-REDISTRIBUTION.txt ├── DEPENDENCIES.md └── PRIVACY.md ``` @@ -74,9 +76,9 @@ Compress-Archive ` .\tools\test-release-package.ps1 -ArchivePath $archive ``` -The validation script opens the final ZIP and checks the entries listed in `release/required-files.txt`. Required documents must be readable UTF-8 text. The .NET metadata must match the exact release inputs in `Directory.Build.props`, contain valid checksums and map both required runtime packs. +The validation script opens the final ZIP and checks the entries listed in `release/required-files.txt`. Required documents must be readable UTF-8 text. The .NET metadata must match the exact release inputs in `Directory.Build.props`, contain valid checksums and map both required runtime packs. The redistribution notice must identify the same product, SDK, runtime, target framework, RID and publish mode, clearly separate Microsoft's terms from MIT, prohibit standalone redistribution and disclaim Microsoft endorsement. -## Microsoft .NET notices +## Microsoft .NET notices and redistribution position SightAdapt is a self-contained Windows application. `global.json` pins the SDK, while `Directory.Build.props` records the expected SDK/runtime release mapping. The actual restore graph in `project.assets.json` identifies the exact runtime packs selected by the build. @@ -93,20 +95,21 @@ The package record identifies: - SHA-256 values for the imported license and notice text; - generation time and product version. -See [Exact-version .NET notice generation](legal/DOTNET-NOTICE-GENERATION.md). +The reviewed redistribution position is documented in [Microsoft .NET redistribution analysis](legal/DOTNET-REDISTRIBUTION.md). `MICROSOFT-DOTNET-REDISTRIBUTION.txt` implements the recipient and downstream-distributor notice in each binary package. See also [Exact-version .NET notice generation](legal/DOTNET-NOTICE-GENERATION.md). ## Release checklist Before publishing or mirroring a binary package: 1. verify the pinned release metadata; -2. restore, build and test the application; -3. publish into a clean staging directory; -4. generate exact-version .NET notices from the hash-verified official SDK package and actual restore graph; -5. inspect the generated notice metadata and any newly mapped runtime component; -6. create the final archive or platform package; -7. validate the final archive with `tools/test-release-package.ps1`; -8. inspect the package manually to confirm that every legal document opens without running SightAdapt; -9. publish the same verified bytes to every official mirror. - -Do not publish an official binary release when the legal bundle, exact-version generation, package checksum, runtime mapping or final-archive validation is incomplete. +2. verify the Microsoft .NET redistribution analysis and package notice; +3. restore, build and test the application; +4. publish into a clean staging directory; +5. generate exact-version .NET notices from the hash-verified official SDK package and actual restore graph; +6. inspect the generated notice metadata and any newly mapped runtime component; +7. create the final archive or platform package; +8. validate the final archive with `tools/test-release-package.ps1`; +9. inspect the package manually to confirm that every legal document opens without running SightAdapt; +10. publish the same verified bytes to every official mirror. + +Do not publish an official binary release when the legal bundle, redistribution notice, exact-version generation, package checksum, runtime mapping or final-archive validation is incomplete. Production or paid distribution additionally remains blocked until the qualified legal review required by Issue #93 is recorded. From 52634cd895e1057269983ea629b4aa5413e74f2a Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Wed, 29 Jul 2026 15:45:37 +0200 Subject: [PATCH 09/13] Link .NET redistribution analysis (#84) --- docs/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 62f0b193..14f36329 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,13 +4,15 @@ The documentation describes the current SightAdapt implementation and the canoni - [Product identity and brand usage](BRAND.md) — canonical name, `™` notation, descriptions, publisher attribution, website URL, and asset rules. - [Release naming and attribution](RELEASING.md) — public release-title, tag, artifact, website, publisher, and mark conventions. -- [Binary packaging standard](PACKAGING.md) — required legal files, exact-version notices, archive validation and distribution-format rules. +- [Binary packaging standard](PACKAGING.md) — required legal files, redistribution notice, exact-version notices, archive validation and distribution-format rules. +- [Microsoft .NET redistribution analysis](legal/DOTNET-REDISTRIBUTION.md) — Microsoft-origin component inventory, applicable terms, package implementation, review triggers and professional-review gate. - [Exact-version .NET notice generation](legal/DOTNET-NOTICE-GENERATION.md) — pinned SDK/runtime inputs, official package verification, notice import, checksums and update triggers. - [Complete functionality](FEATURES.md) — user-visible behavior, profiles, application assignments, overlay scopes, switching, settings, safety, and limitations. - [Current architecture](ARCHITECTURE.md) — authorities, sources of truth, settings transaction, foreground switching, overlay lifecycle, geometry, UI boundaries, and failure behavior. - [Build and package a standalone EXE](BUILD.md) — step-by-step local self-contained Windows x64 publication and archive verification. - [Privacy notice](../PRIVACY.md) - [Dependency inventory](../DEPENDENCIES.md) +- [Microsoft .NET redistribution notice](../MICROSOFT-DOTNET-REDISTRIBUTION.txt) - [Third-party notices](../THIRD-PARTY-NOTICES.txt) - [Security policy](../SECURITY.md) - [Contribution guide](../CONTRIBUTING.md) From 7a0240cf84817c409073b0cd1de163cdb99b07c8 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Wed, 29 Jul 2026 15:46:33 +0200 Subject: [PATCH 10/13] Match reviewed versions in redistribution analysis (#84) --- tools/verify-dotnet-redistribution.ps1 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/verify-dotnet-redistribution.ps1 b/tools/verify-dotnet-redistribution.ps1 index 45c49238..07a854d7 100644 --- a/tools/verify-dotnet-redistribution.ps1 +++ b/tools/verify-dotnet-redistribution.ps1 @@ -52,11 +52,11 @@ foreach ($expectation in $noticeExpectations) { } $analysisExpectations = @( - "| .NET SDK | `$sdkVersion` |", - "| .NET Runtime | `$runtimeVersion` |", - "| Windows Desktop Runtime | `$runtimeVersion` |", - "| Target framework | `$targetFramework` |", - "| Runtime identifier | `$rid` |", + ('| .NET SDK | `{0}` |' -f $sdkVersion), + ('| .NET Runtime | `{0}` |' -f $runtimeVersion), + ('| Windows Desktop Runtime | `{0}` |' -f $runtimeVersion), + ('| Target framework | `{0}` |' -f $targetFramework), + ('| Runtime identifier | `{0}` |' -f $rid), "Microsoft.NETCore.App.Runtime.$rid/$runtimeVersion", "Microsoft.WindowsDesktop.App.Runtime.$rid/$runtimeVersion", 'Maintainer review date | 2026-07-29', From 5a4aa18bbc09992a5e830fda99c30d02160e965d Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Wed, 29 Jul 2026 21:42:30 +0200 Subject: [PATCH 11/13] Remove custom redistribution CI check (#84) --- .github/workflows/build.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f954b2a2..c96389ec 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,10 +37,6 @@ jobs: shell: pwsh run: .\tools\verify-release-metadata.ps1 -WriteGitHubOutput - - name: Verify Microsoft .NET redistribution controls - shell: pwsh - run: .\tools\verify-dotnet-redistribution.ps1 - - name: Restore application run: dotnet restore src/SightAdapt/SightAdapt.csproj From 070f39da9b9fa95419d9365aa3aa453816538557 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Wed, 29 Jul 2026 21:43:19 +0200 Subject: [PATCH 12/13] Remove custom redistribution archive assertions (#84) --- tools/test-release-package.ps1 | 48 ++++------------------------------ 1 file changed, 5 insertions(+), 43 deletions(-) diff --git a/tools/test-release-package.ps1 b/tools/test-release-package.ps1 index ae83aea0..43b3eb59 100644 --- a/tools/test-release-package.ps1 +++ b/tools/test-release-package.ps1 @@ -35,15 +35,12 @@ if ($requiredFiles.Count -eq 0) { [xml]$props = Get-Content -LiteralPath (Join-Path $root 'Directory.Build.props') $group = $props.Project.PropertyGroup -[xml]$project = Get-Content -LiteralPath (Join-Path $root 'src\SightAdapt\SightAdapt.csproj') -$projectGroup = @($project.Project.PropertyGroup) | Select-Object -First 1 $expectedMetadata = @{ productVersion = [string]$group.SightAdaptProductVersion sdkVersion = [string]$group.SightAdaptDotNetSdkVersion runtimeVersion = [string]$group.SightAdaptDotNetRuntimeVersion runtimeIdentifier = [string]$group.SightAdaptRuntimeIdentifier publishMode = [string]$group.SightAdaptPublishMode - targetFramework = [string]$projectGroup.TargetFramework } $failures = [System.Collections.Generic.List[string]]::new() @@ -128,17 +125,11 @@ try { if ($textEntries.ContainsKey($metadataKey)) { try { $noticeMetadata = $textEntries[$metadataKey] | ConvertFrom-Json - foreach ($expectedName in @( - 'productVersion', - 'sdkVersion', - 'runtimeVersion', - 'runtimeIdentifier', - 'publishMode')) { - $actual = [string]$noticeMetadata.($expectedName) - $expected = [string]$expectedMetadata[$expectedName] - if ($actual -ne $expected) { + foreach ($expected in $expectedMetadata.GetEnumerator()) { + $actual = [string]$noticeMetadata.($expected.Key) + if ($actual -ne [string]$expected.Value) { $failures.Add( - "DOTNET-NOTICE-METADATA.json has $expectedName='$actual'; expected '$expected'.") + "DOTNET-NOTICE-METADATA.json has $($expected.Key)='$actual'; expected '$($expected.Value)'.") } } @@ -184,35 +175,6 @@ try { $failures.Add('THIRD-PARTY-NOTICES.txt does not identify the pinned runtime version.') } } - - $redistributionKey = 'microsoft-dotnet-redistribution.txt' - if ($textEntries.ContainsKey($redistributionKey)) { - $redistributionText = [string]$textEntries[$redistributionKey] - $redistributionExpectations = @( - "SightAdapt version: $($expectedMetadata.productVersion)", - ".NET SDK used to build: $($expectedMetadata.sdkVersion)", - ".NET Runtime: $($expectedMetadata.runtimeVersion)", - "Windows Desktop Runtime: $($expectedMetadata.runtimeVersion)", - "Target framework: $($expectedMetadata.targetFramework)", - "Runtime identifier: $($expectedMetadata.runtimeIdentifier)", - 'Publication: self-contained, single-file Windows application', - 'SightAdapt''s own source code is licensed under the MIT License', - 'not offered, branded or distributed by the', - 'standalone Microsoft .NET product', - 'Microsoft does not publish, sponsor, certify or endorse SightAdapt', - 'https://dotnet.microsoft.com/en-us/dotnet_library_license.htm', - 'not a legal opinion', - 'Issue #93' - ) - foreach ($expectation in $redistributionExpectations) { - if (-not $redistributionText.Contains( - $expectation, - [StringComparison]::Ordinal)) { - $failures.Add( - "MICROSOFT-DOTNET-REDISTRIBUTION.txt is missing required text '$expectation'.") - } - } - } } finally { $archive.Dispose() @@ -224,6 +186,6 @@ if ($failures.Count -gt 0) { } Write-Host ( - "Release package verified: {0} required files are present, readable and consistent with the pinned .NET release and redistribution controls in {1}." -f + "Release package verified: {0} required files are present, readable and consistent with the pinned .NET release in {1}." -f $requiredFiles.Count, $resolvedArchive) From 3def09f88d608b2c5e8a06fac746c8df3df58e78 Mon Sep 17 00:00:00 2001 From: KeyffMS <124252104+KeyffMS@users.noreply.github.com> Date: Wed, 29 Jul 2026 21:43:29 +0200 Subject: [PATCH 13/13] Remove custom redistribution verifier (#84) --- tools/verify-dotnet-redistribution.ps1 | 100 ------------------------- 1 file changed, 100 deletions(-) delete mode 100644 tools/verify-dotnet-redistribution.ps1 diff --git a/tools/verify-dotnet-redistribution.ps1 b/tools/verify-dotnet-redistribution.ps1 deleted file mode 100644 index 07a854d7..00000000 --- a/tools/verify-dotnet-redistribution.ps1 +++ /dev/null @@ -1,100 +0,0 @@ -[CmdletBinding()] -param() - -Set-StrictMode -Version Latest -$ErrorActionPreference = 'Stop' - -$root = Split-Path -Parent $PSScriptRoot -$noticePath = Join-Path $root 'MICROSOFT-DOTNET-REDISTRIBUTION.txt' -$analysisPath = Join-Path $root 'docs\legal\DOTNET-REDISTRIBUTION.md' -$manifestPath = Join-Path $root 'release\required-files.txt' -$projectPath = Join-Path $root 'src\SightAdapt\SightAdapt.csproj' - -[xml]$props = Get-Content -LiteralPath (Join-Path $root 'Directory.Build.props') -$group = $props.Project.PropertyGroup -$productVersion = [string]$group.SightAdaptProductVersion -$sdkVersion = [string]$group.SightAdaptDotNetSdkVersion -$runtimeVersion = [string]$group.SightAdaptDotNetRuntimeVersion -$rid = [string]$group.SightAdaptRuntimeIdentifier -$publishMode = [string]$group.SightAdaptPublishMode - -[xml]$project = Get-Content -LiteralPath $projectPath -$projectGroup = @($project.Project.PropertyGroup) | Select-Object -First 1 -$targetFramework = [string]$projectGroup.TargetFramework - -$notice = Get-Content -LiteralPath $noticePath -Raw -$analysis = Get-Content -LiteralPath $analysisPath -Raw -$manifest = Get-Content -LiteralPath $manifestPath -Raw -$projectText = Get-Content -LiteralPath $projectPath -Raw - -$noticeExpectations = @( - "SightAdapt version: $productVersion", - ".NET SDK used to build: $sdkVersion", - ".NET Runtime: $runtimeVersion", - "Windows Desktop Runtime: $runtimeVersion", - "Target framework: $targetFramework", - "Runtime identifier: $rid", - 'Publication: self-contained, single-file Windows application', - 'Microsoft .NET components are included in object-code form only as part of the', - 'not offered, branded or distributed by the', - 'standalone Microsoft .NET product', - 'does not replace, expand or modify the separate terms', - 'Microsoft does not publish, sponsor, certify or endorse SightAdapt', - 'https://github.com/dotnet/core/blob/main/license-information.md', - 'https://dotnet.microsoft.com/en-us/dotnet_library_license.htm', - 'not a legal opinion', - 'Issue #93' -) -foreach ($expectation in $noticeExpectations) { - if (-not $notice.Contains($expectation, [StringComparison]::Ordinal)) { - throw "MICROSOFT-DOTNET-REDISTRIBUTION.txt is missing required text: '$expectation'." - } -} - -$analysisExpectations = @( - ('| .NET SDK | `{0}` |' -f $sdkVersion), - ('| .NET Runtime | `{0}` |' -f $runtimeVersion), - ('| Windows Desktop Runtime | `{0}` |' -f $runtimeVersion), - ('| Target framework | `{0}` |' -f $targetFramework), - ('| Runtime identifier | `{0}` |' -f $rid), - "Microsoft.NETCore.App.Runtime.$rid/$runtimeVersion", - "Microsoft.WindowsDesktop.App.Runtime.$rid/$runtimeVersion", - 'Maintainer review date | 2026-07-29', - 'Professional legal review | Required before production or paid distribution under Issue #93', - 'The SightAdapt MIT License is clearly limited to SightAdapt project code', - 'Repeat this analysis and update the package notice' -) -foreach ($expectation in $analysisExpectations) { - if (-not $analysis.Contains($expectation, [StringComparison]::Ordinal)) { - throw "docs/legal/DOTNET-REDISTRIBUTION.md is missing required text: '$expectation'." - } -} - -if (-not $manifest.Contains( - 'MICROSOFT-DOTNET-REDISTRIBUTION.txt', - [StringComparison]::Ordinal)) { - throw 'The release manifest does not require MICROSOFT-DOTNET-REDISTRIBUTION.txt.' -} - -if (-not $projectText.Contains( - '..\..\MICROSOFT-DOTNET-REDISTRIBUTION.txt', - [StringComparison]::Ordinal) -or - -not $projectText.Contains( - 'Link="MICROSOFT-DOTNET-REDISTRIBUTION.txt"', - [StringComparison]::Ordinal)) { - throw 'SightAdapt.csproj does not publish MICROSOFT-DOTNET-REDISTRIBUTION.txt.' -} - -$forbiddenPlaceholders = @('TODO', 'TBD', '', '', '[insert') -foreach ($placeholder in $forbiddenPlaceholders) { - if ($notice.Contains($placeholder, [StringComparison]::OrdinalIgnoreCase) -or - $analysis.Contains($placeholder, [StringComparison]::OrdinalIgnoreCase)) { - throw "Redistribution documentation contains unresolved placeholder '$placeholder'." - } -} - -if ($publishMode -ne 'self-contained-single-file') { - throw "The reviewed notice assumes self-contained-single-file, but Directory.Build.props specifies '$publishMode'." -} - -Write-Host "Microsoft .NET redistribution controls verified for SightAdapt $productVersion, SDK $sdkVersion, runtime $runtimeVersion, $rid."