refactor: rename ScadaLink → ZB.MOM.WW.ScadaBridge (code + projects + namespaces)

Solution + 23 src projects + 26 test projects renamed; folders, csproj,
namespaces, and ScadaLinkDbContext/ScadaBridgeDbContext class updated.
ActorSystem "scadalink" → "scadabridge", Akka seed-node URLs migrated.
SQL roles/logins, LDAP domains, CLI command name, and CLI config dir
(~/.scadalink → ~/.scadabridge) also renamed.

Build green; 5 Host.Tests fail awaiting SQL login rename in next commit.
Pre-existing StaleTagMonitor timing flakes unchanged.

Rename script committed at tools/rename-to-scadabridge.sh.
This commit is contained in:
Joseph Doherty
2026-05-28 09:37:45 -04:00
parent 6d87ee3c3b
commit 7b0b9c7365
1531 changed files with 11180 additions and 11054 deletions
+84 -84
View File
@@ -15,17 +15,17 @@
### Task 0: Proto Definition & Stub Generation
**Files:**
- Create: `src/ScadaLink.Communication/Protos/sitestream.proto`
- Create: `src/ScadaLink.Communication/SiteStreamGrpc/` (generated stubs)
- Modify: `src/ScadaLink.Communication/ScadaLink.Communication.csproj`
- Create: `src/ZB.MOM.WW.ScadaBridge.Communication/Protos/sitestream.proto`
- Create: `src/ZB.MOM.WW.ScadaBridge.Communication/SiteStreamGrpc/` (generated stubs)
- Modify: `src/ZB.MOM.WW.ScadaBridge.Communication/ZB.MOM.WW.ScadaBridge.Communication.csproj`
**Step 1: Create the proto file**
Create `src/ScadaLink.Communication/Protos/sitestream.proto` with the proto definition from `docs/plans/grpc_streams.md` "Proto Improvements" section (V1 review notes version with enums and `google.protobuf.Timestamp`):
Create `src/ZB.MOM.WW.ScadaBridge.Communication/Protos/sitestream.proto` with the proto definition from `docs/plans/grpc_streams.md` "Proto Improvements" section (V1 review notes version with enums and `google.protobuf.Timestamp`):
```protobuf
syntax = "proto3";
option csharp_namespace = "ScadaLink.Communication.Grpc";
option csharp_namespace = "ZB.MOM.WW.ScadaBridge.Communication.Grpc";
package sitestream;
import "google/protobuf/timestamp.proto";
@@ -80,7 +80,7 @@ message AlarmStateUpdate {
**Step 2: Add gRPC NuGet packages**
Add to `src/ScadaLink.Communication/ScadaLink.Communication.csproj`:
Add to `src/ZB.MOM.WW.ScadaBridge.Communication/ZB.MOM.WW.ScadaBridge.Communication.csproj`:
```xml
<PackageReference Include="Grpc.AspNetCore" Version="2.71.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.71.0" />
@@ -92,16 +92,16 @@ Also add `<FrameworkReference Include="Microsoft.AspNetCore.App" />` if not alre
**Step 3: Generate C# stubs**
Run `protoc` locally to generate stubs. Check generated files into `src/ScadaLink.Communication/SiteStreamGrpc/` — pre-generated and checked in, no `protoc` at build time.
Run `protoc` locally to generate stubs. Check generated files into `src/ZB.MOM.WW.ScadaBridge.Communication/SiteStreamGrpc/` — pre-generated and checked in, no `protoc` at build time.
**Step 4: Verify build**
Run: `dotnet build src/ScadaLink.Communication/`
Run: `dotnet build src/ZB.MOM.WW.ScadaBridge.Communication/`
Expected: Build succeeded, 0 errors
**Step 5: Write proto roundtrip tests**
Create `tests/ScadaLink.Communication.Tests/Grpc/ProtoRoundtripTests.cs`:
Create `tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/Grpc/ProtoRoundtripTests.cs`:
- Test `AttributeValueUpdate` serialization/deserialization with all Quality enum values
- Test `AlarmStateUpdate` serialization/deserialization with all AlarmStateEnum values
- Test `SiteStreamEvent` oneof discrimination (attribute vs alarm)
@@ -109,13 +109,13 @@ Create `tests/ScadaLink.Communication.Tests/Grpc/ProtoRoundtripTests.cs`:
**Step 6: Run tests**
Run: `dotnet test tests/ScadaLink.Communication.Tests/`
Run: `dotnet test tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/`
Expected: All pass including new proto tests
**Step 7: Commit**
```bash
git add src/ScadaLink.Communication/Protos/ src/ScadaLink.Communication/SiteStreamGrpc/ src/ScadaLink.Communication/ScadaLink.Communication.csproj tests/ScadaLink.Communication.Tests/
git add src/ZB.MOM.WW.ScadaBridge.Communication/Protos/ src/ZB.MOM.WW.ScadaBridge.Communication/SiteStreamGrpc/ src/ZB.MOM.WW.ScadaBridge.Communication/ZB.MOM.WW.ScadaBridge.Communication.csproj tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/
git commit -m "feat: add sitestream.proto definition and generated gRPC stubs"
```
@@ -124,10 +124,10 @@ git commit -m "feat: add sitestream.proto definition and generated gRPC stubs"
### Task 1: Site Config — GrpcPort in NodeOptions
**Files:**
- Modify: `src/ScadaLink.Host/NodeOptions.cs:8`
- Modify: `src/ScadaLink.Host/StartupValidator.cs:43-48`
- Modify: `src/ScadaLink.Host/appsettings.Site.json:7`
- Test: `tests/ScadaLink.Host.Tests/`
- Modify: `src/ZB.MOM.WW.ScadaBridge.Host/NodeOptions.cs:8`
- Modify: `src/ZB.MOM.WW.ScadaBridge.Host/StartupValidator.cs:43-48`
- Modify: `src/ZB.MOM.WW.ScadaBridge.Host/appsettings.Site.json:7`
- Test: `tests/ZB.MOM.WW.ScadaBridge.Host.Tests/`
**Step 1: Write failing test for GrpcPort validation**
@@ -135,44 +135,44 @@ Add to existing startup validator tests: test that a site node with `GrpcPort` o
**Step 2: Run test to verify it fails**
Run: `dotnet test tests/ScadaLink.Host.Tests/`
Run: `dotnet test tests/ZB.MOM.WW.ScadaBridge.Host.Tests/`
Expected: New test FAILS (GrpcPort not validated yet)
**Step 3: Add GrpcPort to NodeOptions**
In `src/ScadaLink.Host/NodeOptions.cs`, add:
In `src/ZB.MOM.WW.ScadaBridge.Host/NodeOptions.cs`, add:
```csharp
public int GrpcPort { get; set; } = 8083;
```
**Step 4: Add validation in StartupValidator**
In `src/ScadaLink.Host/StartupValidator.cs`, after the existing site validation block (line ~43):
In `src/ZB.MOM.WW.ScadaBridge.Host/StartupValidator.cs`, after the existing site validation block (line ~43):
```csharp
if (role == "Site")
{
var grpcPortStr = nodeSection["GrpcPort"];
if (grpcPortStr != null && (!int.TryParse(grpcPortStr, out var gp) || gp < 1 || gp > 65535))
errors.Add("ScadaLink:Node:GrpcPort must be 1-65535");
errors.Add("ScadaBridge:Node:GrpcPort must be 1-65535");
}
```
**Step 5: Add GrpcPort to appsettings.Site.json**
In `src/ScadaLink.Host/appsettings.Site.json`, add after `"RemotingPort": 8082`:
In `src/ZB.MOM.WW.ScadaBridge.Host/appsettings.Site.json`, add after `"RemotingPort": 8082`:
```json
"GrpcPort": 8083
```
**Step 6: Run tests**
Run: `dotnet test tests/ScadaLink.Host.Tests/`
Run: `dotnet test tests/ZB.MOM.WW.ScadaBridge.Host.Tests/`
Expected: All pass
**Step 7: Commit**
```bash
git add src/ScadaLink.Host/ tests/ScadaLink.Host.Tests/
git add src/ZB.MOM.WW.ScadaBridge.Host/ tests/ZB.MOM.WW.ScadaBridge.Host.Tests/
git commit -m "feat: add GrpcPort config to NodeOptions with startup validation"
```
@@ -181,17 +181,17 @@ git commit -m "feat: add GrpcPort config to NodeOptions with startup validation"
### Task 2: Site Entity — gRPC Address Fields
**Files:**
- Modify: `src/ScadaLink.Commons/Entities/Sites/Site.cs:9-10`
- Modify: `src/ScadaLink.Commons/Messages/Management/SiteCommands.cs:5-6`
- Modify: `src/ScadaLink.ConfigurationDatabase/` (migration)
- Modify: `src/ScadaLink.ManagementService/ManagementActor.cs` (handlers)
- Modify: `src/ScadaLink.CLI/Commands/SiteCommands.cs`
- Modify: `src/ScadaLink.CentralUI/Components/Pages/Admin/Sites.razor`
- Test: `tests/ScadaLink.Commons.Tests/`
- Modify: `src/ZB.MOM.WW.ScadaBridge.Commons/Entities/Sites/Site.cs:9-10`
- Modify: `src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Management/SiteCommands.cs:5-6`
- Modify: `src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/` (migration)
- Modify: `src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs` (handlers)
- Modify: `src/ZB.MOM.WW.ScadaBridge.CLI/Commands/SiteCommands.cs`
- Modify: `src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/Sites.razor`
- Test: `tests/ZB.MOM.WW.ScadaBridge.Commons.Tests/`
**Step 1: Add fields to Site entity**
In `src/ScadaLink.Commons/Entities/Sites/Site.cs`, add after `NodeBAddress`:
In `src/ZB.MOM.WW.ScadaBridge.Commons/Entities/Sites/Site.cs`, add after `NodeBAddress`:
```csharp
public string? GrpcNodeAAddress { get; set; }
public string? GrpcNodeBAddress { get; set; }
@@ -199,38 +199,38 @@ public string? GrpcNodeBAddress { get; set; }
**Step 2: Update management commands**
In `src/ScadaLink.Commons/Messages/Management/SiteCommands.cs`, add `GrpcNodeAAddress` and `GrpcNodeBAddress` optional params to `CreateSiteCommand` and `UpdateSiteCommand`.
In `src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Management/SiteCommands.cs`, add `GrpcNodeAAddress` and `GrpcNodeBAddress` optional params to `CreateSiteCommand` and `UpdateSiteCommand`.
**Step 3: Add EF Core migration**
Run: `dotnet ef migrations add AddGrpcNodeAddresses --project src/ScadaLink.ConfigurationDatabase/ --startup-project src/ScadaLink.Host/`
Run: `dotnet ef migrations add AddGrpcNodeAddresses --project src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/ --startup-project src/ZB.MOM.WW.ScadaBridge.Host/`
Or create manual migration adding nullable `GrpcNodeAAddress` and `GrpcNodeBAddress` string columns to Sites table.
**Step 4: Update ManagementActor handlers**
In `src/ScadaLink.ManagementService/ManagementActor.cs`, update `HandleCreateSite` and `HandleUpdateSite` to pass gRPC addresses to the repository.
In `src/ZB.MOM.WW.ScadaBridge.ManagementService/ManagementActor.cs`, update `HandleCreateSite` and `HandleUpdateSite` to pass gRPC addresses to the repository.
**Step 5: Update CLI SiteCommands**
In `src/ScadaLink.CLI/Commands/SiteCommands.cs`, add `--grpc-node-a-address` and `--grpc-node-b-address` options to `site create` and `site update` commands.
In `src/ZB.MOM.WW.ScadaBridge.CLI/Commands/SiteCommands.cs`, add `--grpc-node-a-address` and `--grpc-node-b-address` options to `site create` and `site update` commands.
**Step 6: Update Central UI Sites.razor**
In `src/ScadaLink.CentralUI/Components/Pages/Admin/Sites.razor`:
In `src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Admin/Sites.razor`:
- Add `_formGrpcNodeAAddress` and `_formGrpcNodeBAddress` form fields
- Add table columns for gRPC addresses
- Wire into create/update handlers
**Step 7: Run tests**
Run: `dotnet test tests/ScadaLink.Commons.Tests/ && dotnet test tests/ScadaLink.CLI.Tests/ && dotnet test tests/ScadaLink.Host.Tests/`
Run: `dotnet test tests/ZB.MOM.WW.ScadaBridge.Commons.Tests/ && dotnet test tests/ZB.MOM.WW.ScadaBridge.CLI.Tests/ && dotnet test tests/ZB.MOM.WW.ScadaBridge.Host.Tests/`
Expected: All pass
**Step 8: Commit**
```bash
git add src/ScadaLink.Commons/ src/ScadaLink.ConfigurationDatabase/ src/ScadaLink.ManagementService/ src/ScadaLink.CLI/ src/ScadaLink.CentralUI/
git add src/ZB.MOM.WW.ScadaBridge.Commons/ src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/ src/ZB.MOM.WW.ScadaBridge.ManagementService/ src/ZB.MOM.WW.ScadaBridge.CLI/ src/ZB.MOM.WW.ScadaBridge.CentralUI/
git commit -m "feat: add GrpcNodeAAddress/GrpcNodeBAddress to Site entity, CLI, and UI"
```
@@ -239,8 +239,8 @@ git commit -m "feat: add GrpcNodeAAddress/GrpcNodeBAddress to Site entity, CLI,
### Task 3: Site-Side gRPC Server — StreamRelayActor
**Files:**
- Create: `src/ScadaLink.Communication/Grpc/StreamRelayActor.cs`
- Test: `tests/ScadaLink.Communication.Tests/Grpc/StreamRelayActorTests.cs`
- Create: `src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/StreamRelayActor.cs`
- Test: `tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/Grpc/StreamRelayActorTests.cs`
**Step 1: Write failing test**
@@ -248,12 +248,12 @@ Test that `StreamRelayActor` receives `AttributeValueChanged` and writes a corre
**Step 2: Run test to verify it fails**
Run: `dotnet test tests/ScadaLink.Communication.Tests/`
Run: `dotnet test tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/`
Expected: FAIL (class doesn't exist)
**Step 3: Implement StreamRelayActor**
Create `src/ScadaLink.Communication/Grpc/StreamRelayActor.cs`:
Create `src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/StreamRelayActor.cs`:
- `ReceiveActor` that receives `AttributeValueChanged` and `AlarmStateChanged`
- Converts each to the proto `SiteStreamEvent` with correct enum mappings and `Timestamp` conversion
- Writes to `ChannelWriter<SiteStreamEvent>` via `TryWrite`
@@ -261,13 +261,13 @@ Create `src/ScadaLink.Communication/Grpc/StreamRelayActor.cs`:
**Step 4: Run tests**
Run: `dotnet test tests/ScadaLink.Communication.Tests/`
Run: `dotnet test tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/`
Expected: All pass
**Step 5: Commit**
```bash
git add src/ScadaLink.Communication/Grpc/ tests/ScadaLink.Communication.Tests/
git add src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/ tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/
git commit -m "feat: add StreamRelayActor bridging Akka events to gRPC proto channel"
```
@@ -276,8 +276,8 @@ git commit -m "feat: add StreamRelayActor bridging Akka events to gRPC proto cha
### Task 4: Site-Side gRPC Server — SiteStreamGrpcServer
**Files:**
- Create: `src/ScadaLink.Communication/Grpc/SiteStreamGrpcServer.cs`
- Test: `tests/ScadaLink.Communication.Tests/Grpc/SiteStreamGrpcServerTests.cs`
- Create: `src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcServer.cs`
- Test: `tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/Grpc/SiteStreamGrpcServerTests.cs`
**Step 1: Write failing tests**
@@ -289,12 +289,12 @@ git commit -m "feat: add StreamRelayActor bridging Akka events to gRPC proto cha
**Step 2: Run tests to verify they fail**
Run: `dotnet test tests/ScadaLink.Communication.Tests/`
Run: `dotnet test tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/`
Expected: FAIL
**Step 3: Implement SiteStreamGrpcServer**
Create `src/ScadaLink.Communication/Grpc/SiteStreamGrpcServer.cs`:
Create `src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcServer.cs`:
- Inherits `SiteStreamService.SiteStreamServiceBase`
- Injects `SiteStreamManager` (or interface), `ActorSystem`
- Tracks active streams in `ConcurrentDictionary<string, CancellationTokenSource>`
@@ -304,13 +304,13 @@ Create `src/ScadaLink.Communication/Grpc/SiteStreamGrpcServer.cs`:
**Step 4: Run tests**
Run: `dotnet test tests/ScadaLink.Communication.Tests/`
Run: `dotnet test tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/`
Expected: All pass
**Step 5: Commit**
```bash
git add src/ScadaLink.Communication/Grpc/ tests/ScadaLink.Communication.Tests/
git add src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/ tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/
git commit -m "feat: add SiteStreamGrpcServer with Channel<T> bridge and stream limits"
```
@@ -319,10 +319,10 @@ git commit -m "feat: add SiteStreamGrpcServer with Channel<T> bridge and stream
### Task 5: Switch Site Host to WebApplicationBuilder + gRPC
**Files:**
- Modify: `src/ScadaLink.Host/Program.cs:157-174`
- Modify: `src/ScadaLink.Host/appsettings.Site.json`
- Modify: `src/ZB.MOM.WW.ScadaBridge.Host/Program.cs:157-174`
- Modify: `src/ZB.MOM.WW.ScadaBridge.Host/appsettings.Site.json`
- Modify: `docker/docker-compose.yml`
- Test: `tests/ScadaLink.Host.Tests/`
- Test: `tests/ZB.MOM.WW.ScadaBridge.Host.Tests/`
**Step 1: Write failing test**
@@ -330,7 +330,7 @@ Site host startup test: verify `WebApplicationBuilder` starts, gRPC port is conf
**Step 2: Switch site host from generic Host to WebApplicationBuilder**
In `src/ScadaLink.Host/Program.cs`, replace the `Host.CreateDefaultBuilder()` site section with `WebApplication.CreateBuilder()` + Kestrel HTTP/2 on `GrpcPort` + `AddGrpc()` + `MapGrpcService<SiteStreamGrpcServer>()`. Keep all existing service registrations via `SiteServiceRegistration.Configure()`.
In `src/ZB.MOM.WW.ScadaBridge.Host/Program.cs`, replace the `Host.CreateDefaultBuilder()` site section with `WebApplication.CreateBuilder()` + Kestrel HTTP/2 on `GrpcPort` + `AddGrpc()` + `MapGrpcService<SiteStreamGrpcServer>()`. Keep all existing service registrations via `SiteServiceRegistration.Configure()`.
Add gRPC keepalive settings from `CommunicationOptions`:
- `KeepAlivePingDelay = 15s`
@@ -345,7 +345,7 @@ Expose gRPC port 8083 for each site node:
**Step 4: Add gRPC keepalive config to CommunicationOptions**
Add to `src/ScadaLink.Communication/CommunicationOptions.cs`:
Add to `src/ZB.MOM.WW.ScadaBridge.Communication/CommunicationOptions.cs`:
```csharp
public TimeSpan GrpcKeepAlivePingDelay { get; set; } = TimeSpan.FromSeconds(15);
public TimeSpan GrpcKeepAlivePingTimeout { get; set; } = TimeSpan.FromSeconds(10);
@@ -355,13 +355,13 @@ public int GrpcMaxConcurrentStreams { get; set; } = 100;
**Step 5: Run tests and build**
Run: `dotnet build src/ScadaLink.Host/ && dotnet test tests/ScadaLink.Host.Tests/`
Run: `dotnet build src/ZB.MOM.WW.ScadaBridge.Host/ && dotnet test tests/ZB.MOM.WW.ScadaBridge.Host.Tests/`
Expected: All pass
**Step 6: Commit**
```bash
git add src/ScadaLink.Host/ src/ScadaLink.Communication/ docker/
git add src/ZB.MOM.WW.ScadaBridge.Host/ src/ZB.MOM.WW.ScadaBridge.Communication/ docker/
git commit -m "feat: switch site host to WebApplicationBuilder with Kestrel gRPC server"
```
@@ -370,10 +370,10 @@ git commit -m "feat: switch site host to WebApplicationBuilder with Kestrel gRPC
### Task 6: Central-Side gRPC Client
**Files:**
- Create: `src/ScadaLink.Communication/Grpc/SiteStreamGrpcClient.cs`
- Create: `src/ScadaLink.Communication/Grpc/SiteStreamGrpcClientFactory.cs`
- Test: `tests/ScadaLink.Communication.Tests/Grpc/SiteStreamGrpcClientTests.cs`
- Test: `tests/ScadaLink.Communication.Tests/Grpc/SiteStreamGrpcClientFactoryTests.cs`
- Create: `src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcClient.cs`
- Create: `src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcClientFactory.cs`
- Test: `tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/Grpc/SiteStreamGrpcClientTests.cs`
- Test: `tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/Grpc/SiteStreamGrpcClientFactoryTests.cs`
**Step 1: Write failing tests for SiteStreamGrpcClient**
@@ -402,13 +402,13 @@ git commit -m "feat: switch site host to WebApplicationBuilder with Kestrel gRPC
**Step 5: Run tests**
Run: `dotnet test tests/ScadaLink.Communication.Tests/`
Run: `dotnet test tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/`
Expected: All pass
**Step 6: Commit**
```bash
git add src/ScadaLink.Communication/Grpc/ tests/ScadaLink.Communication.Tests/
git add src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/ tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/
git commit -m "feat: add SiteStreamGrpcClient and SiteStreamGrpcClientFactory"
```
@@ -417,10 +417,10 @@ git commit -m "feat: add SiteStreamGrpcClient and SiteStreamGrpcClientFactory"
### Task 7: Update DebugStreamBridgeActor to Use gRPC
**Files:**
- Modify: `src/ScadaLink.Communication/Actors/DebugStreamBridgeActor.cs`
- Modify: `src/ScadaLink.Communication/DebugStreamService.cs`
- Modify: `src/ScadaLink.Communication/ServiceCollectionExtensions.cs`
- Test: `tests/ScadaLink.Communication.Tests/`
- Modify: `src/ZB.MOM.WW.ScadaBridge.Communication/Actors/DebugStreamBridgeActor.cs`
- Modify: `src/ZB.MOM.WW.ScadaBridge.Communication/DebugStreamService.cs`
- Modify: `src/ZB.MOM.WW.ScadaBridge.Communication/ServiceCollectionExtensions.cs`
- Test: `tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/`
**Step 1: Write failing tests for updated bridge actor**
@@ -446,20 +446,20 @@ Inject `SiteStreamGrpcClientFactory`. Resolve `GrpcNodeAAddress`/`GrpcNodeBAddre
**Step 4: Register factory in DI**
In `src/ScadaLink.Communication/ServiceCollectionExtensions.cs`:
In `src/ZB.MOM.WW.ScadaBridge.Communication/ServiceCollectionExtensions.cs`:
```csharp
services.AddSingleton<SiteStreamGrpcClientFactory>();
```
**Step 5: Run tests**
Run: `dotnet test tests/ScadaLink.Communication.Tests/`
Run: `dotnet test tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/`
Expected: All pass
**Step 6: Commit**
```bash
git add src/ScadaLink.Communication/ tests/ScadaLink.Communication.Tests/
git add src/ZB.MOM.WW.ScadaBridge.Communication/ tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/
git commit -m "feat: update DebugStreamBridgeActor to use gRPC for streaming events"
```
@@ -468,12 +468,12 @@ git commit -m "feat: update DebugStreamBridgeActor to use gRPC for streaming eve
### Task 8: Remove ClusterClient Streaming Path
**Files:**
- Modify: `src/ScadaLink.SiteRuntime/Actors/InstanceActor.cs`
- Modify: `src/ScadaLink.Communication/Actors/SiteCommunicationActor.cs`
- Modify: `src/ScadaLink.Communication/Actors/CentralCommunicationActor.cs`
- Delete: `src/ScadaLink.Commons/Messages/DebugView/DebugStreamEvent.cs`
- Test: `tests/ScadaLink.SiteRuntime.Tests/Actors/InstanceActorIntegrationTests.cs`
- Test: `tests/ScadaLink.Commons.Tests/ArchitecturalConstraintTests.cs`
- Modify: `src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Actors/InstanceActor.cs`
- Modify: `src/ZB.MOM.WW.ScadaBridge.Communication/Actors/SiteCommunicationActor.cs`
- Modify: `src/ZB.MOM.WW.ScadaBridge.Communication/Actors/CentralCommunicationActor.cs`
- Delete: `src/ZB.MOM.WW.ScadaBridge.Commons/Messages/DebugView/DebugStreamEvent.cs`
- Test: `tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/InstanceActorIntegrationTests.cs`
- Test: `tests/ZB.MOM.WW.ScadaBridge.Commons.Tests/ArchitecturalConstraintTests.cs`
**Step 1: Remove DebugStreamEvent from InstanceActor**
@@ -491,7 +491,7 @@ Remove `Receive<DebugStreamEvent>` handler and `HandleDebugStreamEvent` method.
**Step 4: Delete DebugStreamEvent.cs**
Delete `src/ScadaLink.Commons/Messages/DebugView/DebugStreamEvent.cs`.
Delete `src/ZB.MOM.WW.ScadaBridge.Commons/Messages/DebugView/DebugStreamEvent.cs`.
**Step 5: Update InstanceActorIntegrationTests**
@@ -499,11 +499,11 @@ Remove `DebugStreamEventForwarder` test helper. Update debug subscriber tests to
**Step 6: Add architectural constraint test**
In `tests/ScadaLink.Commons.Tests/ArchitecturalConstraintTests.cs`, add test verifying `DebugStreamEvent` type no longer exists in the Commons assembly.
In `tests/ZB.MOM.WW.ScadaBridge.Commons.Tests/ArchitecturalConstraintTests.cs`, add test verifying `DebugStreamEvent` type no longer exists in the Commons assembly.
**Step 7: Run full test suite**
Run: `dotnet test tests/ScadaLink.SiteRuntime.Tests/ && dotnet test tests/ScadaLink.Communication.Tests/ && dotnet test tests/ScadaLink.Commons.Tests/ && dotnet test tests/ScadaLink.Host.Tests/`
Run: `dotnet test tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/ && dotnet test tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/ && dotnet test tests/ZB.MOM.WW.ScadaBridge.Commons.Tests/ && dotnet test tests/ZB.MOM.WW.ScadaBridge.Host.Tests/`
Expected: All pass
**Step 8: Commit**
@@ -520,7 +520,7 @@ git commit -m "refactor: remove ClusterClient streaming path (DebugStreamEvent),
**Files:**
- Modify: `docker/docker-compose.yml`
- Modify: `docker/deploy.sh` (if needed)
- Create: `tests/ScadaLink.IntegrationTests/Grpc/GrpcStreamIntegrationTests.cs`
- Create: `tests/ZB.MOM.WW.ScadaBridge.IntegrationTests/Grpc/GrpcStreamIntegrationTests.cs`
**Step 1: Update docker-compose site appsettings**
@@ -537,7 +537,7 @@ Expected: All containers start, gRPC ports exposed
**Step 4: Manual end-to-end verification**
Run: `timeout 35 dotnet run --project src/ScadaLink.CLI -- --url http://localhost:9000 --username multi-role --password password debug stream --id 1 --format table`
Run: `timeout 35 dotnet run --project src/ZB.MOM.WW.ScadaBridge.CLI -- --url http://localhost:9000 --username multi-role --password password debug stream --id 1 --format table`
Expected: Initial snapshot + streaming ATTR/ALARM rows via gRPC (not ClusterClient).
@@ -549,7 +549,7 @@ python3 infra/tools/opcua_tool.py write --node "ns=3;s=JoeAppEngine.BTCS" --valu
**Step 5: Commit**
```bash
git add tests/ScadaLink.IntegrationTests/ docker/
git add tests/ZB.MOM.WW.ScadaBridge.IntegrationTests/ docker/
git commit -m "test: add gRPC stream integration test and docker config"
```
@@ -606,8 +606,8 @@ git commit -m "docs: update requirements and architecture for gRPC streaming cha
### Task 11: Final Guardrail Tests
**Files:**
- Test: `tests/ScadaLink.Communication.Tests/Grpc/ProtoContractTests.cs`
- Test: `tests/ScadaLink.Communication.Tests/Grpc/CleanupVerificationTests.cs`
- Test: `tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/Grpc/ProtoContractTests.cs`
- Test: `tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/Grpc/CleanupVerificationTests.cs`
**Step 1: Proto contract test**
@@ -623,7 +623,7 @@ Integration test that subscribes via gRPC, triggers changes, and verifies events
**Step 4: Run full test suite**
Run: `dotnet test tests/ScadaLink.Host.Tests/ && dotnet test tests/ScadaLink.Communication.Tests/ && dotnet test tests/ScadaLink.SiteRuntime.Tests/ && dotnet test tests/ScadaLink.Commons.Tests/ && dotnet test tests/ScadaLink.CLI.Tests/ && dotnet test tests/ScadaLink.ManagementService.Tests/`
Run: `dotnet test tests/ZB.MOM.WW.ScadaBridge.Host.Tests/ && dotnet test tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/ && dotnet test tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/ && dotnet test tests/ZB.MOM.WW.ScadaBridge.Commons.Tests/ && dotnet test tests/ZB.MOM.WW.ScadaBridge.CLI.Tests/ && dotnet test tests/ZB.MOM.WW.ScadaBridge.ManagementService.Tests/`
Expected: All pass, zero warnings
**Step 5: Commit**