From f1e409618924bc27d0aae530cc78a9811c253a8e Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Thu, 24 Sep 2026 12:52:02 +0700 Subject: [PATCH 1/7] refactor(sntp): use neutral commissioning profile terminology --- Services/SntpPacket.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Services/SntpPacket.cs b/Services/SntpPacket.cs index 0aae4c6fb..2ea0d5df0 100644 --- a/Services/SntpPacket.cs +++ b/Services/SntpPacket.cs @@ -170,15 +170,15 @@ public readonly record struct SntpClientRequest( public sealed record SntpServerProfile { /// - /// SIPROTEC compatibility advertisement used by ARSAS commissioning Clock Sync. - /// Field experience with SIPROTEC requires a trusted-looking low stratum; stratum 2 + /// commissioning compatibility advertisement used by ARSAS commissioning Clock Sync. + /// Field experience with IED requires a trusted-looking low stratum; stratum 2 /// is deliberately used instead of stratum 1 so ARSAS does not claim to be a primary /// GPS/PTP/atomic reference. ReferenceId remains LOCL and diagnostics state that the /// laptop clock is a local commissioning source, not a traceable grandmaster. /// - public const byte SiprotecCompatibilityStratum = 2; + public const byte CommissioningCompatibilityStratum = 2; - public byte Stratum { get; init; } = SiprotecCompatibilityStratum; + public byte Stratum { get; init; } = CommissioningCompatibilityStratum; public byte LeapIndicator { get; init; } public sbyte PollExponent { get; init; } = 6; public sbyte PrecisionExponent { get; init; } = -10; From 9cdaa928ed92ddcee6442c77eb74805a9bcf3084 Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Thu, 24 Sep 2026 12:52:05 +0700 Subject: [PATCH 2/7] refactor(sntp): use neutral commissioning profile terminology --- Services/SntpClockService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Services/SntpClockService.cs b/Services/SntpClockService.cs index 834146f5d..763b1ce8d 100644 --- a/Services/SntpClockService.cs +++ b/Services/SntpClockService.cs @@ -228,8 +228,8 @@ private async Task StartCoreAsync(SntpNetworkBinding binding, CancellationToken SetState( SntpClockServiceState.Serving, binding.DirectedBroadcast == null - ? $"SNTP UDP server active on {binding.LocalAddress}:123 with SIPROTEC compatibility stratum {_profile.Stratum}. No usable directed broadcast is available." - : $"SNTP UDP server active on {binding.LocalAddress}:123 with SIPROTEC compatibility stratum {_profile.Stratum}; Mode 5 broadcast targets {binding.DirectedBroadcast}:123."); + ? $"SNTP UDP server active on {binding.LocalAddress}:123 with commissioning compatibility stratum {_profile.Stratum}. No usable directed broadcast is available." + : $"SNTP UDP server active on {binding.LocalAddress}:123 with commissioning compatibility stratum {_profile.Stratum}; Mode 5 broadcast targets {binding.DirectedBroadcast}:123."); _receiveTask = ReceiveLoopAsync(udp, serviceCancellation.Token); _broadcastTask = BroadcastLoopAsync(binding, serviceCancellation.Token); From 39a369e29adfcc22645d8b925569fdc905240d9e Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Thu, 24 Sep 2026 12:52:07 +0700 Subject: [PATCH 3/7] refactor(sntp): use neutral commissioning profile terminology --- tests/ARSAS.Tests/SntpPacketTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ARSAS.Tests/SntpPacketTests.cs b/tests/ARSAS.Tests/SntpPacketTests.cs index e9d8e2ca4..67347af91 100644 --- a/tests/ARSAS.Tests/SntpPacketTests.cs +++ b/tests/ARSAS.Tests/SntpPacketTests.cs @@ -24,7 +24,7 @@ public void ClientRequest_IsRecognized_AndReplyCopiesVersionPollAndOriginateTime Assert.Equal(4, reply[0] & 0x07); Assert.Equal(4, (reply[0] >> 3) & 0x07); - Assert.Equal(SntpServerProfile.SiprotecCompatibilityStratum, reply[1]); + Assert.Equal(SntpServerProfile.CommissioningCompatibilityStratum, reply[1]); Assert.Equal(9, unchecked((sbyte)reply[2])); Assert.Equal(request.AsSpan(40, 8).ToArray(), reply.AsSpan(24, 8).ToArray()); Assert.InRange((SntpPacket.ReadTimestamp(reply.AsSpan(32, 8), receive) - receive).Duration(), TimeSpan.Zero, TimeSpan.FromTicks(2)); @@ -32,7 +32,7 @@ public void ClientRequest_IsRecognized_AndReplyCopiesVersionPollAndOriginateTime } [Fact] - public void Broadcast_IsMode5_AndUsesSiprotecCompatibilityStratum() + public void Broadcast_IsMode5_AndUsesCommissioningCompatibilityStratum() { var now = new DateTimeOffset(2026, 8, 13, 2, 3, 4, TimeSpan.Zero); var packet = SntpPacket.BuildBroadcast(now, new SntpServerProfile()); @@ -40,8 +40,8 @@ public void Broadcast_IsMode5_AndUsesSiprotecCompatibilityStratum() Assert.Equal(SntpPacket.MinimumLength, packet.Length); Assert.Equal(5, packet[0] & 0x07); Assert.Equal(4, (packet[0] >> 3) & 0x07); - Assert.Equal((byte)2, SntpServerProfile.SiprotecCompatibilityStratum); - Assert.Equal(SntpServerProfile.SiprotecCompatibilityStratum, packet[1]); + Assert.Equal((byte)2, SntpServerProfile.CommissioningCompatibilityStratum); + Assert.Equal(SntpServerProfile.CommissioningCompatibilityStratum, packet[1]); Assert.Equal(6, unchecked((sbyte)packet[2])); Assert.Equal("LOCL", System.Text.Encoding.ASCII.GetString(packet, 12, 4)); Assert.InRange((SntpPacket.ReadTimestamp(packet.AsSpan(40, 8), now) - now).Duration(), TimeSpan.Zero, TimeSpan.FromTicks(2)); From 7332916fdc8353f91b946021e60dc2bf3eb51a3a Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Thu, 24 Sep 2026 12:52:10 +0700 Subject: [PATCH 4/7] refactor(sntp): use neutral commissioning profile terminology --- tests/ARSAS.Tests/SntpEthernetFrameCodecTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ARSAS.Tests/SntpEthernetFrameCodecTests.cs b/tests/ARSAS.Tests/SntpEthernetFrameCodecTests.cs index 497026435..7738aeb51 100644 --- a/tests/ARSAS.Tests/SntpEthernetFrameCodecTests.cs +++ b/tests/ARSAS.Tests/SntpEthernetFrameCodecTests.cs @@ -46,7 +46,7 @@ public void Mode3RawFrame_IsParsed_AndMode4ReplySwapsEndpointsWithValidChecksums var payload = reply.AsSpan(udpOffset + 8, SntpPacket.MinimumLength); Assert.Equal(4, payload[0] & 0x07); - Assert.Equal(SntpServerProfile.SiprotecCompatibilityStratum, payload[1]); + Assert.Equal(SntpServerProfile.CommissioningCompatibilityStratum, payload[1]); Assert.Equal(requestPayload.AsSpan(40, 8).ToArray(), payload.Slice(24, 8).ToArray()); } From 888a2fec2e2fb4419d391f0e718d06b344d5cd6d Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Thu, 24 Sep 2026 12:52:13 +0700 Subject: [PATCH 5/7] refactor(sntp): use neutral commissioning profile terminology --- docs/SNTP_CLOCK_SYNC.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/SNTP_CLOCK_SYNC.md b/docs/SNTP_CLOCK_SYNC.md index 4ad3d263f..b5bad2c2f 100644 --- a/docs/SNTP_CLOCK_SYNC.md +++ b/docs/SNTP_CLOCK_SYNC.md @@ -14,7 +14,7 @@ ARSAS includes a small clean-room SNTPv4 commissioning service for station-bus w - Sends an immediate SNTPv4 Mode 5 directed broadcast, then repeats every 64 seconds by default when a usable directed-broadcast address exists. - Sends another immediate broadcast when a newly connected IED is observed. - Separately records `broadcast sent`, `client request seen`, and `Mode 4 reply sent` evidence. -- Advertises synchronized commissioning packets with SIPROTEC compatibility `stratum 2` and reference ID `LOCL`. +- Advertises synchronized commissioning packets with commissioning compatibility `stratum 2` and reference ID `LOCL`. - Performs a wall-clock sanity/step check. A large time step suppresses broadcast and makes that instant's unicast reply RFC-style unsynchronized (`LI=3`, `stratum=0`, `INIT`, server timestamps zero). - Never fails an IEC 61850 association when SNTP cannot start. @@ -29,11 +29,11 @@ FAT Clock Sync telemetry intentionally distinguishes packet activity from actual A broadcast without a client request may still be valid when the relay is explicitly configured for broadcast NTP, but ARSAS does not treat it as an acknowledgement. For unicast SNTP, the strongest wire-level evidence is a Mode 3 request followed by a Mode 4 reply. Device-side time-quality or clock evidence is still required before declaring the relay synchronized. -## SIPROTEC compatibility stratum +## commissioning compatibility stratum -Field commissioning has shown that a conservative high-stratum local source can be rejected or remain marked unsynchronized on some SIPROTEC installations. ARSAS therefore uses `stratum 2` for both Mode 4 replies and Mode 5 broadcasts. +Field commissioning has shown that a conservative high-stratum local source can be rejected or remain marked unsynchronized on some tested IED installations. ARSAS therefore uses `stratum 2` for both Mode 4 replies and Mode 5 broadcasts. -The value is named in code as `SntpServerProfile.SiprotecCompatibilityStratum` and is protected by regression tests. It does not claim that the Windows laptop is physically traceable to a stratum-1 GNSS/PTP/atomic source. `LOCL` remains the reference ID and ARSAS diagnostics describe the laptop as a local commissioning source. +The value is named in code as `SntpServerProfile.CommissioningCompatibilityStratum` and is protected by regression tests. It does not claim that the Windows laptop is physically traceable to a stratum-1 GNSS/PTP/atomic source. `LOCL` remains the reference ID and ARSAS diagnostics describe the laptop as a local commissioning source. If the Windows clock fails the ARSAS clock-health guard, synchronized stratum is not advertised: the affected unicast response becomes unsynchronized (`LI=3`, `stratum=0`, `INIT`) and broadcast is suppressed. @@ -75,7 +75,7 @@ If another connected IED routes through a different local IPv4 interface, ARSAS - version/poll field copy behavior; - Mode 4 reply semantics; - originate timestamp echo; -- SIPROTEC compatibility stratum 2 on unicast and broadcast packets; +- commissioning compatibility stratum 2 on unicast and broadcast packets; - Mode 5 broadcast semantics; - RFC-style unsynchronized response fields; - directed-broadcast calculation; From 463e0ecf0fc121eab91089bbf186f02d03d12bf1 Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Thu, 24 Sep 2026 12:52:55 +0700 Subject: [PATCH 6/7] docs(sntp): preserve bounded field-source provenance without vendor-specific product naming --- Services/SntpPacket.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Services/SntpPacket.cs b/Services/SntpPacket.cs index 2ea0d5df0..f7ee09f0d 100644 --- a/Services/SntpPacket.cs +++ b/Services/SntpPacket.cs @@ -170,7 +170,7 @@ public readonly record struct SntpClientRequest( public sealed record SntpServerProfile { /// - /// commissioning compatibility advertisement used by ARSAS commissioning Clock Sync. + /// Commissioning compatibility advertisement used by ARSAS Clock Sync. /// Field experience with IED requires a trusted-looking low stratum; stratum 2 /// is deliberately used instead of stratum 1 so ARSAS does not claim to be a primary /// GPS/PTP/atomic reference. ReferenceId remains LOCL and diagnostics state that the From 1019d49ce628db9690dc787f334d74bc359a3edc Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Thu, 24 Sep 2026 12:52:59 +0700 Subject: [PATCH 7/7] docs(sntp): preserve bounded field-source provenance without vendor-specific product naming --- docs/SNTP_CLOCK_SYNC.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/SNTP_CLOCK_SYNC.md b/docs/SNTP_CLOCK_SYNC.md index b5bad2c2f..530418f88 100644 --- a/docs/SNTP_CLOCK_SYNC.md +++ b/docs/SNTP_CLOCK_SYNC.md @@ -29,9 +29,9 @@ FAT Clock Sync telemetry intentionally distinguishes packet activity from actual A broadcast without a client request may still be valid when the relay is explicitly configured for broadcast NTP, but ARSAS does not treat it as an acknowledgement. For unicast SNTP, the strongest wire-level evidence is a Mode 3 request followed by a Mode 4 reply. Device-side time-quality or clock evidence is still required before declaring the relay synchronized. -## commissioning compatibility stratum +## Commissioning compatibility stratum -Field commissioning has shown that a conservative high-stratum local source can be rejected or remain marked unsynchronized on some tested IED installations. ARSAS therefore uses `stratum 2` for both Mode 4 replies and Mode 5 broadcasts. +Authorized field observations on the historical reference configuration showed that a conservative high-stratum local source could be rejected or remain marked unsynchronized. ARSAS therefore uses the same `stratum 2` advertisement for Mode 4 replies and Mode 5 broadcasts. This is a bounded commissioning default, not a claim about all IEDs. The original device-specific naming and observation context remain traceable in the [pre-migration source revision](https://github.com/masarray/arsas/commit/e03ff1caa7d83902ef106f0c4aafdc3fb24143e5). The value is named in code as `SntpServerProfile.CommissioningCompatibilityStratum` and is protected by regression tests. It does not claim that the Windows laptop is physically traceable to a stratum-1 GNSS/PTP/atomic source. `LOCL` remains the reference ID and ARSAS diagnostics describe the laptop as a local commissioning source.