Skip to content

M2.17-M P0: reconcile #618/#620; canonical Data Model focused hydration + Explorer read SSOT #1340

M2.17-M P0: reconcile #618/#620; canonical Data Model focused hydration + Explorer read SSOT

M2.17-M P0: reconcile #618/#620; canonical Data Model focused hydration + Explorer read SSOT #1340

name: Smart Discovery Golden Provenance
on:
pull_request:
paths:
- "*.cs"
- "**/*.cs"
- "*.csproj"
- "**/*.csproj"
- "*.sln"
- "**/*.sln"
- "*.props"
- "**/*.props"
- "*.targets"
- "**/*.targets"
- "global.json"
- "*.xaml"
- "**/*.xaml"
- "app.manifest"
- "VERSION"
- ".release/**"
- ".github/workflows/**"
- "Assets/**"
- "Resources/**"
- "installer/**"
- "engine-patches/**"
- "landing/release-notes*.json"
- "landing/latest.json"
- "engines/**"
- "scripts/**"
- "tests/**"
- "evidence/**"
- "docs/INTEROPERABILITY_REFERENCE_CONTRACT.md"
- ".github/workflows/smart-discovery-*.yml"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
verify-provenance:
name: Verify P0-5e capture build and target provenance
runs-on: windows-latest
steps:
- name: Checkout exact ARSAS candidate
uses: actions/checkout@v7
with:
path: ArIED61850Tester
fetch-depth: 1
persist-credentials: false
- name: Verify exact candidate revision
shell: powershell
run: |
$actual = (git -C .\ArIED61850Tester rev-parse HEAD).Trim().ToLowerInvariant()
$expected = $env:GITHUB_SHA.Trim().ToLowerInvariant()
if ($actual -ne $expected) {
throw "ARSAS source revision mismatch. Expected $expected, checked out $actual."
}
- name: Execute P0-5e provenance fixtures
shell: powershell
run: |
$writer = '.\ArIED61850Tester\scripts\new-smart-discovery-golden-lock.ps1'
$verifier = '.\ArIED61850Tester\scripts\verify-smart-discovery-golden-lock.ps1'
$target = '.\ArIED61850Tester\evidence\smart-discovery-golden-target.json'
foreach ($required in @($writer, $verifier, $target)) {
if (-not (Test-Path $required -PathType Leaf)) { throw "Missing P0-5e provenance source: $required" }
}
foreach ($script in @($writer, $verifier)) {
$tokens = $null
$errors = $null
[System.Management.Automation.Language.Parser]::ParseFile($script, [ref]$tokens, [ref]$errors) | Out-Null
if ($errors.Count -ne 0) { throw "PowerShell parse failure in $script" }
}
$results = '.\ArIED61850Tester\TestResults'
New-Item -ItemType Directory -Force $results | Out-Null
$capture = Join-Path $results 'p0-5e-provenance-fixture.pcapng'
[IO.File]::WriteAllBytes($capture, [Text.Encoding]::UTF8.GetBytes('CI fixture only - never physical authority'))
$arsasCommit = (git -C .\ArIED61850Tester rev-parse HEAD).Trim().ToLowerInvariant()
$engineCommit = '4467124775d8d9d76f3db194f9fbfd97144767a8'
$manifest = Join-Path $results 'SMART-CAPTURE-BUILD.txt'
@(
'ARSAS smart discovery field-capture build',
"ARSAS commit: $arsasCommit",
"ARIEC61850 commit: $engineCommit",
'Engine PR: 134'
) | Set-Content $manifest -Encoding utf8
$proofPath = Join-Path $results 'P0-5D-provenance-source.json'
$proof = [ordered]@{
SchemaVersion = 1
Phase = 'P0-5d'
Verdict = 'PASS'
AcceptanceFailures = @()
ArsasCapture = [ordered]@{
Capture = 'fixture'
ClientIp = '192.0.2.10'
ServerIp = '192.0.2.20'
RequestTcpStreams = @('0')
ConfirmedRequests = 4
ConfirmedResponsesOrErrors = 4
ServiceCounts = [ordered]@{
GetNameList = 2
GetVariableAccessAttributes = 2
}
DuplicateSemanticRequests = 0
DuplicateGetNameListRequests = 0
DuplicateGvaRequests = 0
DuplicateDetails = @()
SecondGetNameListSweepDetected = $false
PeakOutstandingRequests = 3
NegotiatedMaxOutstandingCalling = 10
InvokeIdReuseWhileOutstanding = 0
OrphanResponses = 0
UnansweredRequestsAtCaptureEnd = 0
}
}
$proof | ConvertTo-Json -Depth 12 | Set-Content $proofPath -Encoding utf8
$lockPath = Join-Path $results 'P0-5E-provenance.lock.json'
& $writer `
-ProofJson $proofPath `
-CapturePath $capture `
-DeviceIdentity 'AA1E1F06R4' `
-ArsasCommit $arsasCommit `
-EngineCommit $engineCommit `
-TargetPath $target `
-BuildManifestPath $manifest `
-OutputPath $lockPath `
-AllowFixtureEvidence
$lock = Get-Content $lockPath -Raw | ConvertFrom-Json
if ($lock.SchemaVersion -ne 2 -or
$lock.GoldenSource.BuildManifestSha256 -notmatch '^[0-9a-f]{64}$' -or
$lock.GoldenSource.SemanticTargetSha256 -notmatch '^[0-9a-f]{64}$' -or
$lock.GoldenSource.RawCaptureReverified) {
throw 'Fixture lock did not carry expected P0-5e provenance metadata.'
}
$acceptPath = Join-Path $results 'P0-5E-provenance-pass.json'
& $verifier `
-LockPath $lockPath `
-ProofJson $proofPath `
-DeviceIdentity 'AA1E1F06R4' `
-CandidateArsasCommit $arsasCommit `
-CandidateEngineCommit $engineCommit `
-TargetPath $target `
-OutputJson $acceptPath
$accept = Get-Content $acceptPath -Raw | ConvertFrom-Json
if ($accept.Verdict -ne 'PASS') { throw 'Exact build/target fixture should pass the golden provenance lock.' }
$wrongArsas = '1111111111111111111111111111111111111111'
$mismatchPath = Join-Path $results 'P0-5E-provenance-arsas-mismatch.json'
& $verifier `
-LockPath $lockPath `
-ProofJson $proofPath `
-DeviceIdentity 'AA1E1F06R4' `
-CandidateArsasCommit $wrongArsas `
-CandidateEngineCommit $engineCommit `
-TargetPath $target `
-OutputJson $mismatchPath `
-NoFailExit
$mismatch = Get-Content $mismatchPath -Raw | ConvertFrom-Json
if ($mismatch.Verdict -ne 'FAIL' -or
-not (@($mismatch.AcceptanceFailures) -match 'Candidate ARSAS commit differs')) {
throw 'P0-5e did not reject ARSAS build identity drift.'
}
$alteredTarget = Join-Path $results 'altered-target.json'
$changed = Get-Content $target -Raw | ConvertFrom-Json
$changed.SemanticTarget.LogicalNodes = 120
$changed | ConvertTo-Json -Depth 12 | Set-Content $alteredTarget -Encoding utf8
$targetMismatchPath = Join-Path $results 'P0-5E-provenance-target-mismatch.json'
& $verifier `
-LockPath $lockPath `
-ProofJson $proofPath `
-DeviceIdentity 'AA1E1F06R4' `
-CandidateArsasCommit $arsasCommit `
-CandidateEngineCommit $engineCommit `
-TargetPath $alteredTarget `
-OutputJson $targetMismatchPath `
-NoFailExit
$targetMismatch = Get-Content $targetMismatchPath -Raw | ConvertFrom-Json
if ($targetMismatch.Verdict -ne 'FAIL' -or
-not (@($targetMismatch.AcceptanceFailures) -match 'Semantic target hash differs')) {
throw 'P0-5e did not reject semantic-target authority drift.'
}
- name: Upload P0-5e provenance evidence
if: always()
uses: actions/upload-artifact@v7
with:
name: ARSAS-p0-5e-golden-provenance-fixtures
path: ArIED61850Tester\TestResults\P0-5E-*.json
if-no-files-found: warn
retention-days: 14