Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
23b3845
Enable NuGet dependency lock files
masarray Jul 12, 2026
05c0a69
Generate and retain NuGet dependency lock files in CI
masarray Jul 12, 2026
4a3c5da
Prevent published GitHub releases from being overwritten
masarray Jul 12, 2026
e1c0ccd
Synchronize public documentation with the current engine and release …
masarray Jul 12, 2026
4ad0822
Update build and release guide for locked dependencies and immutable …
masarray Jul 12, 2026
7eb0cdd
Document locked dependency update workflow for contributors
masarray Jul 12, 2026
fdd9397
Commit generated NuGet lock files
masarray Jul 12, 2026
560a33a
Commit generated engine dependency lock
masarray Jul 12, 2026
31e682a
Commit generated subscriber dependency lock
masarray Jul 12, 2026
b2a1e8d
Commit generated test dependency lock
masarray Jul 12, 2026
7ecccb1
Enforce locked NuGet restore in validated automation
masarray Jul 12, 2026
2c745ca
Restore the solution in locked mode
masarray Jul 12, 2026
2b889c6
Enforce committed NuGet locks in CI
masarray Jul 12, 2026
b3cd559
Restore locked dependencies in CodeQL
masarray Jul 12, 2026
b63f7fa
Publish release artifacts from the locked dependency graph
masarray Jul 12, 2026
cdefafa
Use locked restore for coverage tests
masarray Jul 12, 2026
02e06bd
Record P1 dependency and release hardening
masarray Jul 12, 2026
f335f47
Generate win-x64 runtime dependency locks
masarray Jul 12, 2026
b2bbb01
Lock Publisher win-x64 runtime dependencies
masarray Jul 12, 2026
812c95f
Lock Subscriber win-x64 runtime dependencies
masarray Jul 12, 2026
2fbe68c
Finalize locked NuGet restore in CI
masarray Jul 12, 2026
4a12753
Declare supported win-x64 runtime for Publisher
masarray Jul 12, 2026
e87568a
Declare supported win-x64 runtime for Subscriber
masarray Jul 12, 2026
63ea95f
Declare win-x64 runtime graph for the shared engine
masarray Jul 12, 2026
51204bd
Lock shared engine win-x64 runtime dependencies
masarray Jul 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ jobs:
uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5
with:
dotnet-version: 8.0.4xx
cache: true
cache-dependency-path: |
Directory.Packages.props
src/**/packages.lock.json
tests/**/packages.lock.json

- name: Build public site and HTML documentation
run: python scripts/build-public-site.py --output artifacts/public-site
Expand All @@ -30,14 +35,18 @@ jobs:
shell: pwsh
run: .\scripts\validate-public-site.ps1 -SiteRoot artifacts/public-site

- name: Restore Publisher
run: dotnet restore src/ARSVIN/ARSVIN.csproj
- name: Restore locked NuGet dependency graph
run: dotnet restore ARSVIN.sln --locked-mode

- name: Restore Subscriber
run: dotnet restore src/ARSVIN.Subscriber/ARSVIN.Subscriber.csproj

- name: Restore tests
run: dotnet restore tests/ARSVIN.Tests/ARSVIN.Tests.csproj
- name: Upload committed NuGet lock evidence
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: arsvin-nuget-lockfiles
path: |
src/**/packages.lock.json
tests/**/packages.lock.json
if-no-files-found: error
retention-days: 7

- name: Build Publisher with warnings as errors
run: dotnet build src/ARSVIN/ARSVIN.csproj -c Release --no-restore -warnaserror
Expand Down
9 changes: 7 additions & 2 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,20 @@ jobs:
uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5
with:
dotnet-version: 8.0.4xx
cache: true
cache-dependency-path: |
Directory.Packages.props
src/**/packages.lock.json
tests/**/packages.lock.json

- name: Initialize CodeQL
uses: github/codeql-action/init@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4
with:
languages: csharp
build-mode: manual

- name: Restore solution
run: dotnet restore ARSVIN.sln
- name: Restore locked solution dependency graph
run: dotnet restore ARSVIN.sln --locked-mode

- name: Build solution with warnings as errors
run: dotnet build ARSVIN.sln -c Release --no-restore -warnaserror
Expand Down
22 changes: 22 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,28 @@ jobs:
name: ${{ needs.package.outputs.artifact_name }}
path: artifacts/release

- name: Refuse to overwrite an existing GitHub Release
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ needs.package.outputs.tag_name }}
shell: bash
run: |
set -euo pipefail
endpoint="repos/${GITHUB_REPOSITORY}/releases/tags/${RELEASE_TAG}"

if existing_release="$(gh api "$endpoint" 2>&1)"; then
echo "::error::GitHub Release ${RELEASE_TAG} already exists. Published releases are immutable; create a new semantic-version tag instead."
exit 1
fi

if ! grep -q 'HTTP 404' <<<"$existing_release"; then
echo "$existing_release" >&2
echo "::error::Could not verify whether GitHub Release ${RELEASE_TAG} already exists."
exit 1
fi

echo "No existing GitHub Release found for ${RELEASE_TAG}; publication may continue."

- name: Attest release build provenance
uses: actions/attest@a1948c3f048ba23858d222213b7c278aabede763 # v4
with:
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,20 @@ All notable ARSVIN changes are documented here using a lightweight Keep a Change
- Added unique canonical URLs, descriptions, Open Graph metadata, Twitter Card metadata, and `TechArticle` JSON-LD for engineering documentation pages.
- Added a generated multi-page sitemap containing the product homepage and every published documentation page.
- Added recursive validation for all HTML metadata, structured data, canonical uniqueness, local references, search-index targets, sitemap coverage, web-manifest icons, and robots metadata.
- Added committed NuGet lock files for Publisher, Subscriber, the shared engine, and Tests.
- Added CI evidence upload for the committed dependency lock graph.

### Changed

- GitHub Pages and Windows CI now build and validate the same staged public-site artifact instead of copying raw Markdown into the deployment directory.
- The product landing page now links directly to Quick Start, SV Profile Support, COMTRADE Replay, Subscriber Verification, Safety Boundaries, and the complete documentation index.
- Validated CI, CodeQL, build, test, publish, and release paths now restore NuGet dependencies in locked mode.
- README, build guidance, contributor guidance, repository structure, release examples, and coverage baselines now match the current shared-engine implementation.

### Security

- Published GitHub Releases are now immutable in automation; a release job fails before attestation or upload when the semantic-version tag already has a GitHub Release.
- Artifact corrections require a new semantic-version patch instead of replacing previously published binaries, checksums, or SBOMs.

### Planned

Expand Down
34 changes: 27 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,46 +12,66 @@ ARSVIN is an engineering suite for IEC 61850 Sampled Values laboratory workflows
- Preserve Apache-2.0 compatibility.
- Prefer explicit engineering wording over marketing claims.
- Update documentation when behavior, UI, safety assumptions, or release packaging changes.
- Preserve committed NuGet lock files and immutable public releases.

## Development setup

Recommended environment:

- Windows 10/11 x64
- .NET 8 SDK
- .NET 8 SDK, feature band 8.0.4xx
- PowerShell 7+
- Npcap for live packet capture/publishing tests
- Wireshark for packet inspection

Build:
Build using the committed dependency graph:

```powershell
.\build.ps1
```

Run tests:
Run tests and produce coverage evidence:

```powershell
dotnet test tests/ARSVIN.Tests/ARSVIN.Tests.csproj -c Release
.\scripts\test-with-coverage.ps1 -MinimumLineCoverage 50
```

Create portable release artifacts:
Create portable release artifacts for the current source version:

```powershell
.\scripts\publish-release.ps1 -Version 0.1.0
.\scripts\publish-release.ps1 -Version 0.3.1
```

## Dependency updates

NuGet versions are centrally managed in `Directory.Packages.props`, and each project commits `packages.lock.json`.

Normal builds and automation restore with locked mode. When deliberately changing a dependency:

1. update the version in `Directory.Packages.props`,
2. regenerate lock files from the repository root,
3. review direct and transitive changes,
4. commit package-version and lock-file changes together.

```powershell
dotnet restore ARSVIN.sln --force-evaluate
```

Do not hand-edit `packages.lock.json`. Unrelated lock-file churn should not be included in a pull request.

## Pull request checklist

Before opening a PR, please check:

- The change has a narrow engineering purpose.
- Both affected applications build in Release mode.
- Relevant unit tests were added or updated where practical.
- The protocol-core coverage floor still passes, and broader coverage changes are explained.
- Safety behavior is not weakened.
- Docs are updated for user-visible changes.
- Screenshots or Wireshark notes are included for UI / packet behavior changes.
- New dependencies are necessary, maintained, and license-compatible.
- New dependencies are necessary, maintained, license-compatible, and represented in lock files.
- Release-workflow changes preserve tag-only publication and immutable existing releases.

## Commit and branch style

Expand Down
2 changes: 2 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<ContinuousIntegrationBuild Condition="'$(CI)' == 'true'">true</ContinuousIntegrationBuild>
<Deterministic>true</Deterministic>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<RestoreLockedMode Condition="'$(CI)' == 'true'">true</RestoreLockedMode>
<VersionPrefix>0.3.1</VersionPrefix>
<RepositoryUrl>https://github.com/masarray/arsvin</RepositoryUrl>
<RepositoryType>git</RepositoryType>
Expand Down
19 changes: 13 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ Stable and prerelease tag builds publish signed GitHub artifact attestations for
gh attestation verify .\ARSVIN-Suite-Setup-win-x64.exe --repo masarray/arsvin
```

Published GitHub Releases are immutable in the automated workflow. Corrections use a new semantic-version tag instead of replacing existing assets.

The binaries are currently **unsigned**. Windows SmartScreen may show an unknown-publisher warning. Releases do not silently install Npcap; download Npcap from its official website when live capture or transmission is required.

## Quick start
Expand Down Expand Up @@ -125,7 +127,7 @@ For users:

For developers:

- .NET 8 SDK.
- .NET 8 SDK, feature band 8.0.4xx.
- PowerShell 7+ recommended.
- Visual Studio 2022, JetBrains Rider, or VS Code with C# tooling.
- Inno Setup 6.7.1 when reproducing the automated installer build locally.
Expand All @@ -138,16 +140,18 @@ cd arsvin
.\build.ps1
```

NuGet versions are centrally managed and committed `packages.lock.json` files lock the resolved dependency graph. Validated CI and release paths restore with `--locked-mode`.

Build all release artifacts except the installer:

```powershell
.\scripts\publish-release.ps1 -Version 0.3.0
.\scripts\publish-release.ps1 -Version 0.3.1
```

Compatibility wrapper:

```powershell
.\publish-win-x64.ps1 -Version 0.3.0
.\publish-win-x64.ps1 -Version 0.3.1
```

Run tests with the repository coverage gate and retain TRX/Cobertura evidence:
Expand All @@ -156,18 +160,19 @@ Run tests with the repository coverage gate and retain TRX/Cobertura evidence:
.\scripts\test-with-coverage.ps1 -MinimumLineCoverage 50
```

The current linked engine surface measures 57.85% line coverage across 1,535 instrumented production lines. CI enforces a 50% regression floor while the shared engine project and broader protocol tests are developed.
The complete shared `ARSVIN.Engine` baseline currently measures 5.64% line coverage across 15,726 instrumented production lines. The established protocol-core regression surface measures 57.89% across 1,534 lines, with 888 covered lines; CI enforces a 50% floor on that tested protocol-core surface while broader engine tests are added.

Generate a CycloneDX SBOM after restoring the solution:

```powershell
.\scripts\generate-sbom.ps1 -Version 0.3.0
.\scripts\generate-sbom.ps1 -Version 0.3.1
```

## Repository structure

```text
src/ARSVIN/ Publisher application and SV generation engine
src/ARSVIN.Engine/ Shared IEC 61850 protocol, SCL, capture, transport, and SV engine project
src/ARSVIN/ Publisher application
src/ARSVIN.Subscriber/ ArSubsv subscriber and visualization companion
tests/ARSVIN.Tests/ Protocol and publisher helper tests
installer/ Inno Setup definition for the Windows suite
Expand All @@ -178,6 +183,8 @@ site/ Static, SEO-ready GitHub Pages product site
.github/workflows/ CI, CodeQL, Pages, and release automation
```

The shared engine is compiled once as `ARSVIN.Engine`; its source files are still physically located under `src/ARSVIN/Engine` during the staged directory migration.

## Documentation

- [Documentation index](docs/index.md)
Expand Down
7 changes: 3 additions & 4 deletions build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ $ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest

$root = $PSScriptRoot
$solution = Join-Path $root 'ARSVIN.sln'
$appProject = Join-Path $root 'src\ARSVIN\ARSVIN.csproj'
$subscriberProject = Join-Path $root 'src\ARSVIN.Subscriber\ARSVIN.Subscriber.csproj'
$testProject = Join-Path $root 'tests\ARSVIN.Tests\ARSVIN.Tests.csproj'
Expand All @@ -18,10 +19,8 @@ function Invoke-DotNet {
}
}

Write-Host '==> Restoring solution projects'
Invoke-DotNet -Arguments @('restore', $appProject)
Invoke-DotNet -Arguments @('restore', $subscriberProject)
Invoke-DotNet -Arguments @('restore', $testProject)
Write-Host '==> Restoring locked solution dependency graph'
Invoke-DotNet -Arguments @('restore', $solution, '--locked-mode')

Write-Host '==> Building ARSVIN Publisher'
Invoke-DotNet -Arguments @('build', $appProject, '-c', 'Release', '--no-restore', '-warnaserror')
Expand Down
Loading
Loading