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:
@@ -4,7 +4,7 @@
|
||||
|
||||
**Goal:** Capture the cluster node of origin (`node-a` / `node-b` for site rows, `central-a` / `central-b` for central direct-write rows) on every `AuditLog`, `Notifications`, and `SiteCalls` row, end-to-end from the writing node through telemetry / reconciliation to the Central UI.
|
||||
|
||||
**Architecture:** Introduce a single `INodeIdentityProvider` exposing the local node name from `NodeOptions.NodeName` (new config key, bound from `ScadaLink:Node:NodeName`). Stamp `SourceNode` at the *writing node* — site `SqliteAuditWriter` for site rows, `CentralAuditWriter` for central direct-writes — and carry it verbatim through the existing gRPC `AuditEventDto` / `SiteCallOperationalDto` envelopes (additive new field), the `NotificationSubmit` S&F payload, and the `CachedCallTelemetry` packet. EF Core migrations add the column to all three central tables; site-side SQLite schemas use the existing idempotent `PRAGMA table_info` + `ALTER TABLE ADD COLUMN` pattern. UI gets a new "Node" column + filter on the three grids.
|
||||
**Architecture:** Introduce a single `INodeIdentityProvider` exposing the local node name from `NodeOptions.NodeName` (new config key, bound from `ScadaBridge:Node:NodeName`). Stamp `SourceNode` at the *writing node* — site `SqliteAuditWriter` for site rows, `CentralAuditWriter` for central direct-writes — and carry it verbatim through the existing gRPC `AuditEventDto` / `SiteCallOperationalDto` envelopes (additive new field), the `NotificationSubmit` S&F payload, and the `CachedCallTelemetry` packet. EF Core migrations add the column to all three central tables; site-side SQLite schemas use the existing idempotent `PRAGMA table_info` + `ALTER TABLE ADD COLUMN` pattern. UI gets a new "Node" column + filter on the three grids.
|
||||
|
||||
**Tech Stack:** .NET 8 / C# 12 sealed records, EF Core 8 (MS SQL on central, SQLite at sites), Akka.NET, Grpc.AspNetCore, Blazor Server, xUnit + Akka.TestKit + NSubstitute + Playwright. Migration naming: `YYYYMMDDHHmmss_DescriptiveTitle`.
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
|
||||
## Conventions
|
||||
|
||||
- All file paths are relative to repo root (`/Users/dohertj2/Desktop/scadalink-design`).
|
||||
- All file paths are relative to repo root (`/Users/dohertj2/Desktop/scadabridge-design`).
|
||||
- TDD: red → green → commit. Failing test first, then implementation, then verify, then commit.
|
||||
- One coherent change per commit. Commit messages prefix with the affected slice: `feat(audit):`, `feat(notif-outbox):`, `feat(sitecall-audit):`, `chore(docker):`, etc.
|
||||
- After each task, run the targeted test set (`dotnet test <project> --filter <name>`) and the full solution build (`dotnet build ScadaLink.slnx`) before the commit.
|
||||
- After each task, run the targeted test set (`dotnet test <project> --filter <name>`) and the full solution build (`dotnet build ZB.MOM.WW.ScadaBridge.slnx`) before the commit.
|
||||
- For tasks whose migration name needs a timestamp, use `date -u +%Y%m%d%H%M%S` at the moment of execution. The exact name doesn't matter for correctness; just keep them monotonically ordered.
|
||||
|
||||
---
|
||||
@@ -40,11 +40,11 @@ Expected: branch created, working tree shows only the prior design-doc edits + t
|
||||
|
||||
**Step 2: Stash unrelated dirty files**
|
||||
|
||||
`docker/central-node-{a,b}/appsettings.Central.json` and `src/ScadaLink.CentralUI/Components/Pages/Login.razor` are dirty from prior unrelated work — do **NOT** include them in this feature's commits. Verify with `git diff --stat` what's already modified, and either revert or stash:
|
||||
`docker/central-node-{a,b}/appsettings.Central.json` and `src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Login.razor` are dirty from prior unrelated work — do **NOT** include them in this feature's commits. Verify with `git diff --stat` what's already modified, and either revert or stash:
|
||||
|
||||
```bash
|
||||
git diff --stat
|
||||
git stash push -- docker/central-node-a/appsettings.Central.json docker/central-node-b/appsettings.Central.json src/ScadaLink.CentralUI/Components/Pages/Login.razor
|
||||
git stash push -- docker/central-node-a/appsettings.Central.json docker/central-node-b/appsettings.Central.json src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Login.razor
|
||||
```
|
||||
|
||||
Expected: clean diff against the prior commit + the design-doc edits from this session.
|
||||
@@ -52,10 +52,10 @@ Expected: clean diff against the prior commit + the design-doc edits from this s
|
||||
**Step 3: Baseline build + tests**
|
||||
|
||||
```bash
|
||||
dotnet build ScadaLink.slnx
|
||||
dotnet test tests/ScadaLink.AuditLog.Tests/ScadaLink.AuditLog.Tests.csproj
|
||||
dotnet test tests/ScadaLink.NotificationOutbox.Tests/ScadaLink.NotificationOutbox.Tests.csproj
|
||||
dotnet test tests/ScadaLink.SiteCallAudit.Tests/ScadaLink.SiteCallAudit.Tests.csproj
|
||||
dotnet build ZB.MOM.WW.ScadaBridge.slnx
|
||||
dotnet test tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests.csproj
|
||||
dotnet test tests/ZB.MOM.WW.ScadaBridge.NotificationOutbox.Tests/ZB.MOM.WW.ScadaBridge.NotificationOutbox.Tests.csproj
|
||||
dotnet test tests/ZB.MOM.WW.ScadaBridge.SiteCallAudit.Tests/ZB.MOM.WW.ScadaBridge.SiteCallAudit.Tests.csproj
|
||||
```
|
||||
|
||||
Expected: green. If any are red on `main`, **STOP** and surface that to the user — the plan assumes a green starting point.
|
||||
@@ -72,11 +72,11 @@ git commit -m "docs(audit): add SourceNode column to AuditLog/Notifications/Site
|
||||
## Task 1: NodeOptions + INodeIdentityProvider
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/ScadaLink.Host/NodeOptions.cs`
|
||||
- Create: `src/ScadaLink.Commons/Interfaces/Services/INodeIdentityProvider.cs`
|
||||
- Create: `src/ScadaLink.Host/NodeIdentityProvider.cs`
|
||||
- Modify: `src/ScadaLink.Host/SiteServiceRegistration.cs` (and central registration if separate — check `CentralServiceRegistration.cs` if it exists)
|
||||
- Create test: `tests/ScadaLink.Host.Tests/NodeIdentityProviderTests.cs` (if Host.Tests doesn't exist, place under `tests/ScadaLink.AuditLog.Tests/Configuration/NodeIdentityProviderTests.cs` instead)
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.Host/NodeOptions.cs`
|
||||
- Create: `src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/INodeIdentityProvider.cs`
|
||||
- Create: `src/ZB.MOM.WW.ScadaBridge.Host/NodeIdentityProvider.cs`
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.Host/SiteServiceRegistration.cs` (and central registration if separate — check `CentralServiceRegistration.cs` if it exists)
|
||||
- Create test: `tests/ZB.MOM.WW.ScadaBridge.Host.Tests/NodeIdentityProviderTests.cs` (if Host.Tests doesn't exist, place under `tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Configuration/NodeIdentityProviderTests.cs` instead)
|
||||
|
||||
**Step 1: Failing test — provider returns configured NodeName**
|
||||
|
||||
@@ -117,8 +117,8 @@ public class NodeOptions
|
||||
**Step 3: Create `INodeIdentityProvider` + implementation**
|
||||
|
||||
```csharp
|
||||
// src/ScadaLink.Commons/Interfaces/Services/INodeIdentityProvider.cs
|
||||
namespace ScadaLink.Commons.Interfaces.Services;
|
||||
// src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/INodeIdentityProvider.cs
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Services;
|
||||
|
||||
public interface INodeIdentityProvider
|
||||
{
|
||||
@@ -132,7 +132,7 @@ public interface INodeIdentityProvider
|
||||
```
|
||||
|
||||
```csharp
|
||||
// src/ScadaLink.Host/NodeIdentityProvider.cs
|
||||
// src/ZB.MOM.WW.ScadaBridge.Host/NodeIdentityProvider.cs
|
||||
internal sealed class NodeIdentityProvider : INodeIdentityProvider
|
||||
{
|
||||
public NodeIdentityProvider(IOptions<NodeOptions> options)
|
||||
@@ -157,7 +157,7 @@ services.AddSingleton<INodeIdentityProvider, NodeIdentityProvider>();
|
||||
|
||||
```bash
|
||||
dotnet test tests/<project> --filter NodeIdentityProvider -v n
|
||||
dotnet build ScadaLink.slnx
|
||||
dotnet build ZB.MOM.WW.ScadaBridge.slnx
|
||||
```
|
||||
|
||||
Expected: PASS, solution builds.
|
||||
@@ -165,10 +165,10 @@ Expected: PASS, solution builds.
|
||||
**Step 6: Commit**
|
||||
|
||||
```bash
|
||||
git add src/ScadaLink.Host/NodeOptions.cs \
|
||||
src/ScadaLink.Commons/Interfaces/Services/INodeIdentityProvider.cs \
|
||||
src/ScadaLink.Host/NodeIdentityProvider.cs \
|
||||
src/ScadaLink.Host/SiteServiceRegistration.cs \
|
||||
git add src/ZB.MOM.WW.ScadaBridge.Host/NodeOptions.cs \
|
||||
src/ZB.MOM.WW.ScadaBridge.Commons/Interfaces/Services/INodeIdentityProvider.cs \
|
||||
src/ZB.MOM.WW.ScadaBridge.Host/NodeIdentityProvider.cs \
|
||||
src/ZB.MOM.WW.ScadaBridge.Host/SiteServiceRegistration.cs \
|
||||
tests/<project>/NodeIdentityProviderTests.cs
|
||||
git commit -m "feat(host): add NodeName to NodeOptions + INodeIdentityProvider"
|
||||
```
|
||||
@@ -178,9 +178,9 @@ git commit -m "feat(host): add NodeName to NodeOptions + INodeIdentityProvider"
|
||||
## Task 2: Add `SourceNode` to `AuditEvent` record
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/ScadaLink.Commons/Entities/Audit/AuditEvent.cs`
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.Commons/Entities/Audit/AuditEvent.cs`
|
||||
- Modify: any direct constructors of `AuditEvent` (compile errors will surface them)
|
||||
- Modify: `tests/ScadaLink.AuditLog.Tests/AddAuditLogTests.cs` (or the closest equivalent) — add a SourceNode round-trip assertion.
|
||||
- Modify: `tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/AddAuditLogTests.cs` (or the closest equivalent) — add a SourceNode round-trip assertion.
|
||||
|
||||
**Step 1: Failing test**
|
||||
|
||||
@@ -220,9 +220,9 @@ The record is `sealed` and used widely. Most usages will be init-only and won't
|
||||
**Step 4: Run + commit**
|
||||
|
||||
```bash
|
||||
dotnet test tests/ScadaLink.AuditLog.Tests --filter SourceNode -v n
|
||||
dotnet build ScadaLink.slnx
|
||||
git add src/ScadaLink.Commons/Entities/Audit/AuditEvent.cs tests/ScadaLink.AuditLog.Tests/AddAuditLogTests.cs
|
||||
dotnet test tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests --filter SourceNode -v n
|
||||
dotnet build ZB.MOM.WW.ScadaBridge.slnx
|
||||
git add src/ZB.MOM.WW.ScadaBridge.Commons/Entities/Audit/AuditEvent.cs tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/AddAuditLogTests.cs
|
||||
git commit -m "feat(audit): add SourceNode property to AuditEvent record"
|
||||
```
|
||||
|
||||
@@ -231,9 +231,9 @@ git commit -m "feat(audit): add SourceNode property to AuditEvent record"
|
||||
## Task 3: Add `SourceNode` to `SiteCallOperational` + `SiteCall` entity
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/ScadaLink.Commons/Types/SiteCallOperational.cs`
|
||||
- Modify: `src/ScadaLink.Commons/Entities/Audit/SiteCall.cs`
|
||||
- Modify: tests in `tests/ScadaLink.SiteCallAudit.Tests/` that build a `SiteCall` — extend at least one to assert SourceNode is carried.
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.Commons/Types/SiteCallOperational.cs`
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.Commons/Entities/Audit/SiteCall.cs`
|
||||
- Modify: tests in `tests/ZB.MOM.WW.ScadaBridge.SiteCallAudit.Tests/` that build a `SiteCall` — extend at least one to assert SourceNode is carried.
|
||||
|
||||
**Step 1: Failing test — `SiteCallOperational` constructed with SourceNode**
|
||||
|
||||
@@ -264,25 +264,25 @@ Run: expected FAIL.
|
||||
**Step 2: Add `SourceNode` to `SiteCallOperational`**
|
||||
|
||||
Insert `string? SourceNode` between `SourceSite` and `Status`. **Update all callers** — the C# compiler will list every site that constructs the record. Most are in:
|
||||
- `src/ScadaLink.ExternalSystemGateway/ExternalSystemClient.cs`
|
||||
- `src/ScadaLink.DataConnectionLayer/...` (cached DB write site)
|
||||
- `src/ScadaLink.Communication/...` (mappers)
|
||||
- `src/ScadaLink.SiteCallAudit/SiteCallAuditActor.cs`
|
||||
- All `tests/ScadaLink.SiteCallAudit.Tests/*` and `tests/ScadaLink.ConfigurationDatabase.Tests/Repositories/SiteCallAuditRepositoryTests.cs`
|
||||
- `src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/ExternalSystemClient.cs`
|
||||
- `src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/...` (cached DB write site)
|
||||
- `src/ZB.MOM.WW.ScadaBridge.Communication/...` (mappers)
|
||||
- `src/ZB.MOM.WW.ScadaBridge.SiteCallAudit/SiteCallAuditActor.cs`
|
||||
- All `tests/ZB.MOM.WW.ScadaBridge.SiteCallAudit.Tests/*` and `tests/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests/Repositories/SiteCallAuditRepositoryTests.cs`
|
||||
|
||||
For now, pass `SourceNode: null` at every existing call site — actual stamping comes in Task 11.
|
||||
|
||||
**Step 3: Add `SourceNode` to `SiteCall` entity**
|
||||
|
||||
Mirror in `src/ScadaLink.Commons/Entities/Audit/SiteCall.cs` as `public string? SourceNode { get; init; }`.
|
||||
Mirror in `src/ZB.MOM.WW.ScadaBridge.Commons/Entities/Audit/SiteCall.cs` as `public string? SourceNode { get; init; }`.
|
||||
|
||||
**Step 4: Run + commit**
|
||||
|
||||
```bash
|
||||
dotnet build ScadaLink.slnx
|
||||
dotnet test tests/ScadaLink.SiteCallAudit.Tests --filter SourceNode -v n
|
||||
git add src/ScadaLink.Commons/Types/SiteCallOperational.cs \
|
||||
src/ScadaLink.Commons/Entities/Audit/SiteCall.cs \
|
||||
dotnet build ZB.MOM.WW.ScadaBridge.slnx
|
||||
dotnet test tests/ZB.MOM.WW.ScadaBridge.SiteCallAudit.Tests --filter SourceNode -v n
|
||||
git add src/ZB.MOM.WW.ScadaBridge.Commons/Types/SiteCallOperational.cs \
|
||||
src/ZB.MOM.WW.ScadaBridge.Commons/Entities/Audit/SiteCall.cs \
|
||||
<updated callers>
|
||||
git commit -m "feat(sitecall-audit): add SourceNode to SiteCallOperational + SiteCall entity"
|
||||
```
|
||||
@@ -292,9 +292,9 @@ git commit -m "feat(sitecall-audit): add SourceNode to SiteCallOperational + Sit
|
||||
## Task 4: Add `SourceNode` to `Notification` entity + `NotificationSubmit` message
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/ScadaLink.Commons/Entities/Notifications/Notification.cs`
|
||||
- Modify: `src/ScadaLink.Commons/Messages/Notification/NotificationMessages.cs`
|
||||
- Modify: tests in `tests/ScadaLink.NotificationOutbox.Tests/`
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.Commons/Entities/Notifications/Notification.cs`
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Notification/NotificationMessages.cs`
|
||||
- Modify: tests in `tests/ZB.MOM.WW.ScadaBridge.NotificationOutbox.Tests/`
|
||||
|
||||
**Step 1: Failing test**
|
||||
|
||||
@@ -343,11 +343,11 @@ public record NotificationSubmit(
|
||||
**Step 3: Run + commit**
|
||||
|
||||
```bash
|
||||
dotnet build ScadaLink.slnx
|
||||
dotnet test tests/ScadaLink.NotificationOutbox.Tests --filter SourceNode -v n
|
||||
git add src/ScadaLink.Commons/Entities/Notifications/Notification.cs \
|
||||
src/ScadaLink.Commons/Messages/Notification/NotificationMessages.cs \
|
||||
tests/ScadaLink.NotificationOutbox.Tests/<modified>.cs
|
||||
dotnet build ZB.MOM.WW.ScadaBridge.slnx
|
||||
dotnet test tests/ZB.MOM.WW.ScadaBridge.NotificationOutbox.Tests --filter SourceNode -v n
|
||||
git add src/ZB.MOM.WW.ScadaBridge.Commons/Entities/Notifications/Notification.cs \
|
||||
src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Notification/NotificationMessages.cs \
|
||||
tests/ZB.MOM.WW.ScadaBridge.NotificationOutbox.Tests/<modified>.cs
|
||||
git commit -m "feat(notif-outbox): add SourceNode to Notification entity + NotificationSubmit"
|
||||
```
|
||||
|
||||
@@ -356,10 +356,10 @@ git commit -m "feat(notif-outbox): add SourceNode to Notification entity + Notif
|
||||
## Task 5: Add `source_node` to proto + update DTO mappers
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/ScadaLink.Communication/Protos/sitestream.proto`
|
||||
- Modify: `src/ScadaLink.Communication/AuditEventDtoMapper.cs` (or wherever `ToDto` / `FromDto` live)
|
||||
- Modify: `src/ScadaLink.Communication/SiteCallOperationalDtoMapper.cs` (likewise)
|
||||
- Modify: `tests/ScadaLink.Communication.Tests/Protos/AuditEventProtoTests.cs`
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.Communication/Protos/sitestream.proto`
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.Communication/AuditEventDtoMapper.cs` (or wherever `ToDto` / `FromDto` live)
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.Communication/SiteCallOperationalDtoMapper.cs` (likewise)
|
||||
- Modify: `tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/Protos/AuditEventProtoTests.cs`
|
||||
- Modify: equivalent SiteCallOperational proto round-trip tests
|
||||
|
||||
**Step 1: Failing test — proto round-trip preserves SourceNode**
|
||||
@@ -421,13 +421,13 @@ Same pattern for `SiteCallOperationalDtoMapper`.
|
||||
**Step 4: Run + commit**
|
||||
|
||||
```bash
|
||||
dotnet build ScadaLink.slnx
|
||||
dotnet test tests/ScadaLink.Communication.Tests --filter SourceNode -v n
|
||||
git add src/ScadaLink.Communication/Protos/sitestream.proto \
|
||||
src/ScadaLink.Communication/AuditEventDtoMapper.cs \
|
||||
src/ScadaLink.Communication/SiteCallOperationalDtoMapper.cs \
|
||||
tests/ScadaLink.Communication.Tests/Protos/AuditEventProtoTests.cs \
|
||||
tests/ScadaLink.Communication.Tests/<sitecall mapper tests>.cs
|
||||
dotnet build ZB.MOM.WW.ScadaBridge.slnx
|
||||
dotnet test tests/ZB.MOM.WW.ScadaBridge.Communication.Tests --filter SourceNode -v n
|
||||
git add src/ZB.MOM.WW.ScadaBridge.Communication/Protos/sitestream.proto \
|
||||
src/ZB.MOM.WW.ScadaBridge.Communication/AuditEventDtoMapper.cs \
|
||||
src/ZB.MOM.WW.ScadaBridge.Communication/SiteCallOperationalDtoMapper.cs \
|
||||
tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/Protos/AuditEventProtoTests.cs \
|
||||
tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/<sitecall mapper tests>.cs
|
||||
git commit -m "feat(comm): add source_node field to AuditEventDto + SiteCallOperationalDto proto"
|
||||
```
|
||||
|
||||
@@ -436,10 +436,10 @@ git commit -m "feat(comm): add source_node field to AuditEventDto + SiteCallOper
|
||||
## Task 6: EF migration — add `SourceNode` to `AuditLog` + index
|
||||
|
||||
**Files:**
|
||||
- Create: `src/ScadaLink.ConfigurationDatabase/Migrations/<ts>_AddAuditLogSourceNode.cs` + `.Designer.cs`
|
||||
- Modify: `src/ScadaLink.ConfigurationDatabase/Migrations/ScadaLinkDbContextModelSnapshot.cs`
|
||||
- Modify: `src/ScadaLink.ConfigurationDatabase/Configurations/AuditLogEntityTypeConfiguration.cs`
|
||||
- Create test: `tests/ScadaLink.ConfigurationDatabase.Tests/Migrations/AddAuditLogSourceNodeMigrationTests.cs`
|
||||
- Create: `src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Migrations/<ts>_AddAuditLogSourceNode.cs` + `.Designer.cs`
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Migrations/ScadaBridgeDbContextModelSnapshot.cs`
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Configurations/AuditLogEntityTypeConfiguration.cs`
|
||||
- Create test: `tests/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests/Migrations/AddAuditLogSourceNodeMigrationTests.cs`
|
||||
|
||||
**Step 1: Failing test (migration apply produces `SourceNode` column + index)**
|
||||
|
||||
@@ -453,9 +453,9 @@ From repo root:
|
||||
|
||||
```bash
|
||||
dotnet ef migrations add AddAuditLogSourceNode \
|
||||
--project src/ScadaLink.ConfigurationDatabase \
|
||||
--startup-project src/ScadaLink.Host \
|
||||
--context ScadaLinkDbContext
|
||||
--project src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase \
|
||||
--startup-project src/ZB.MOM.WW.ScadaBridge.Host \
|
||||
--context ScadaBridgeDbContext
|
||||
```
|
||||
|
||||
Hand-edit the generated `Up()` / `Down()` to verify shape:
|
||||
@@ -499,13 +499,13 @@ builder.HasIndex(e => new { e.SourceNode, e.OccurredAtUtc })
|
||||
**Step 4: Run + commit**
|
||||
|
||||
```bash
|
||||
dotnet build ScadaLink.slnx
|
||||
dotnet test tests/ScadaLink.ConfigurationDatabase.Tests --filter AuditLogSourceNode -v n
|
||||
git add src/ScadaLink.ConfigurationDatabase/Migrations/<ts>_AddAuditLogSourceNode.cs \
|
||||
src/ScadaLink.ConfigurationDatabase/Migrations/<ts>_AddAuditLogSourceNode.Designer.cs \
|
||||
src/ScadaLink.ConfigurationDatabase/Migrations/ScadaLinkDbContextModelSnapshot.cs \
|
||||
src/ScadaLink.ConfigurationDatabase/Configurations/AuditLogEntityTypeConfiguration.cs \
|
||||
tests/ScadaLink.ConfigurationDatabase.Tests/Migrations/AddAuditLogSourceNodeMigrationTests.cs
|
||||
dotnet build ZB.MOM.WW.ScadaBridge.slnx
|
||||
dotnet test tests/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests --filter AuditLogSourceNode -v n
|
||||
git add src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Migrations/<ts>_AddAuditLogSourceNode.cs \
|
||||
src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Migrations/<ts>_AddAuditLogSourceNode.Designer.cs \
|
||||
src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Migrations/ScadaBridgeDbContextModelSnapshot.cs \
|
||||
src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Configurations/AuditLogEntityTypeConfiguration.cs \
|
||||
tests/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests/Migrations/AddAuditLogSourceNodeMigrationTests.cs
|
||||
git commit -m "feat(db): add SourceNode column + IX_AuditLog_Node_Occurred index to AuditLog"
|
||||
```
|
||||
|
||||
@@ -514,10 +514,10 @@ git commit -m "feat(db): add SourceNode column + IX_AuditLog_Node_Occurred index
|
||||
## Task 7: EF migration — add `SourceNode` to `Notifications`
|
||||
|
||||
**Files:**
|
||||
- Create: `src/ScadaLink.ConfigurationDatabase/Migrations/<ts>_AddNotificationSourceNode.cs` + `.Designer.cs`
|
||||
- Modify: `src/ScadaLink.ConfigurationDatabase/Migrations/ScadaLinkDbContextModelSnapshot.cs`
|
||||
- Modify: `src/ScadaLink.ConfigurationDatabase/Configurations/NotificationOutboxConfiguration.cs`
|
||||
- Create test: `tests/ScadaLink.ConfigurationDatabase.Tests/Migrations/AddNotificationSourceNodeMigrationTests.cs`
|
||||
- Create: `src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Migrations/<ts>_AddNotificationSourceNode.cs` + `.Designer.cs`
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Migrations/ScadaBridgeDbContextModelSnapshot.cs`
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Configurations/NotificationOutboxConfiguration.cs`
|
||||
- Create test: `tests/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests/Migrations/AddNotificationSourceNodeMigrationTests.cs`
|
||||
|
||||
**Step 1–4:** Mirror Task 6 for the `Notifications` table. No new index (the spec says index only on `AuditLog`).
|
||||
|
||||
@@ -542,9 +542,9 @@ git commit -m "feat(db): add SourceNode column to SiteCalls"
|
||||
## Task 9: Site SQLite `AuditLog` — add `SourceNode` column (idempotent upgrade)
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/ScadaLink.AuditLog/Site/SqliteAuditWriter.cs`
|
||||
- Modify: `tests/ScadaLink.AuditLog.Tests/Site/SqliteAuditWriterSchemaTests.cs`
|
||||
- Modify: `tests/ScadaLink.AuditLog.Tests/Site/SqliteAuditWriterWriteTests.cs`
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SqliteAuditWriter.cs`
|
||||
- Modify: `tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Site/SqliteAuditWriterSchemaTests.cs`
|
||||
- Modify: `tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Site/SqliteAuditWriterWriteTests.cs`
|
||||
|
||||
**Step 1: Failing test — schema includes SourceNode AND old DBs are upgraded**
|
||||
|
||||
@@ -588,11 +588,11 @@ In the parameterized batch insert SQL (lines ~270-284), add the column + paramet
|
||||
**Step 4: Run + commit**
|
||||
|
||||
```bash
|
||||
dotnet test tests/ScadaLink.AuditLog.Tests/Site/SqliteAuditWriterSchemaTests.cs --filter SourceNode -v n
|
||||
dotnet build ScadaLink.slnx
|
||||
git add src/ScadaLink.AuditLog/Site/SqliteAuditWriter.cs \
|
||||
tests/ScadaLink.AuditLog.Tests/Site/SqliteAuditWriterSchemaTests.cs \
|
||||
tests/ScadaLink.AuditLog.Tests/Site/SqliteAuditWriterWriteTests.cs
|
||||
dotnet test tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Site/SqliteAuditWriterSchemaTests.cs --filter SourceNode -v n
|
||||
dotnet build ZB.MOM.WW.ScadaBridge.slnx
|
||||
git add src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SqliteAuditWriter.cs \
|
||||
tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Site/SqliteAuditWriterSchemaTests.cs \
|
||||
tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Site/SqliteAuditWriterWriteTests.cs
|
||||
git commit -m "feat(audit): add SourceNode column to site SQLite AuditLog (idempotent upgrade)"
|
||||
```
|
||||
|
||||
@@ -601,8 +601,8 @@ git commit -m "feat(audit): add SourceNode column to site SQLite AuditLog (idemp
|
||||
## Task 10: Site SQLite `OperationTracking` — add `SourceNode` column
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/ScadaLink.SiteRuntime/Tracking/OperationTrackingStore.cs`
|
||||
- Modify: tests under `tests/ScadaLink.SiteRuntime.Tests/Tracking/` (or closest)
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Tracking/OperationTrackingStore.cs`
|
||||
- Modify: tests under `tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Tracking/` (or closest)
|
||||
|
||||
**Step 1: Failing test** — same pattern as Task 9, asserting the `OperationTracking` table grows a `SourceNode TEXT NULL` column on both fresh and pre-existing DBs.
|
||||
|
||||
@@ -632,9 +632,9 @@ git commit -m "feat(site-runtime): add SourceNode column to OperationTracking +
|
||||
## Task 11: Stamp `SourceNode` at the site `SqliteAuditWriter`
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/ScadaLink.AuditLog/Site/SqliteAuditWriter.cs`
|
||||
- Modify: DI registration that wires `SqliteAuditWriter` (likely `src/ScadaLink.AuditLog/AuditLogServiceCollectionExtensions.cs` or equivalent)
|
||||
- Modify: `tests/ScadaLink.AuditLog.Tests/Site/SqliteAuditWriterWriteTests.cs`
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.AuditLog/Site/SqliteAuditWriter.cs`
|
||||
- Modify: DI registration that wires `SqliteAuditWriter` (likely `src/ZB.MOM.WW.ScadaBridge.AuditLog/AuditLogServiceCollectionExtensions.cs` or equivalent)
|
||||
- Modify: `tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Site/SqliteAuditWriterWriteTests.cs`
|
||||
|
||||
**Step 1: Failing test**
|
||||
|
||||
@@ -683,8 +683,8 @@ git commit -m "feat(audit): stamp SourceNode at site SqliteAuditWriter from INod
|
||||
## Task 12: Stamp `SourceNode` at central `CentralAuditWriter`
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/ScadaLink.AuditLog/Central/CentralAuditWriter.cs`
|
||||
- Modify: `tests/ScadaLink.AuditLog.Tests/Central/CentralAuditWriterTests.cs`
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.AuditLog/Central/CentralAuditWriter.cs`
|
||||
- Modify: `tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/Central/CentralAuditWriterTests.cs`
|
||||
|
||||
**Step 1: Failing test** — mirror Task 11 but for the central writer (Inbound API / Notification Outbox dispatcher path).
|
||||
|
||||
@@ -692,7 +692,7 @@ git commit -m "feat(audit): stamp SourceNode at site SqliteAuditWriter from INod
|
||||
|
||||
**Step 3: Update `AuditLogRepository.InsertIfNotExistsAsync` to persist `SourceNode`**
|
||||
|
||||
This is in `src/ScadaLink.ConfigurationDatabase/Repositories/AuditLogRepository.cs` — extend the parameterized INSERT.
|
||||
This is in `src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Repositories/AuditLogRepository.cs` — extend the parameterized INSERT.
|
||||
|
||||
**Step 4: Run + commit**
|
||||
|
||||
@@ -705,11 +705,11 @@ git commit -m "feat(audit): stamp SourceNode at CentralAuditWriter + persist via
|
||||
## Task 13: Site → central — carry `SourceNode` on `NotificationSubmit`
|
||||
|
||||
**Files:**
|
||||
- Modify: site code that constructs `NotificationSubmit` (likely under `src/ScadaLink.SiteRuntime/Scripts/` or `src/ScadaLink.NotificationService/Site/...`)
|
||||
- Modify: S&F buffer schema if NotificationSubmit is serialized to SQLite (check `src/ScadaLink.StoreAndForward/StoreAndForwardStorage.cs` for a notification-specific column — likely the whole DTO is serialized as a blob, no schema change needed)
|
||||
- Modify: `src/ScadaLink.NotificationOutbox/NotificationOutboxActor.cs` `HandleSubmit` to copy `SourceNode` into the `Notification` row
|
||||
- Modify: `src/ScadaLink.ConfigurationDatabase/Repositories/NotificationOutboxRepository.cs` (or wherever) `InsertIfNotExistsAsync` SQL
|
||||
- Modify: tests in `tests/ScadaLink.NotificationOutbox.Tests/NotificationOutboxActorIngestTests.cs`
|
||||
- Modify: site code that constructs `NotificationSubmit` (likely under `src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/` or `src/ZB.MOM.WW.ScadaBridge.NotificationService/Site/...`)
|
||||
- Modify: S&F buffer schema if NotificationSubmit is serialized to SQLite (check `src/ZB.MOM.WW.ScadaBridge.StoreAndForward/StoreAndForwardStorage.cs` for a notification-specific column — likely the whole DTO is serialized as a blob, no schema change needed)
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.NotificationOutbox/NotificationOutboxActor.cs` `HandleSubmit` to copy `SourceNode` into the `Notification` row
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Repositories/NotificationOutboxRepository.cs` (or wherever) `InsertIfNotExistsAsync` SQL
|
||||
- Modify: tests in `tests/ZB.MOM.WW.ScadaBridge.NotificationOutbox.Tests/NotificationOutboxActorIngestTests.cs`
|
||||
|
||||
**Step 1: Failing test — central persists SourceNode from NotificationSubmit**
|
||||
|
||||
@@ -741,10 +741,10 @@ git commit -m "feat(notif-outbox): carry + persist SourceNode end-to-end via Not
|
||||
## Task 14: Site → central — carry `SourceNode` on `SiteCallOperational` + cached telemetry
|
||||
|
||||
**Files:**
|
||||
- Modify: site emitters of `SiteCallOperational` — `src/ScadaLink.ExternalSystemGateway/ExternalSystemClient.cs`, `src/ScadaLink.DataConnectionLayer/...` (cached DB write), and the S&F retry path that emits `Attempted` packets
|
||||
- Modify: `src/ScadaLink.SiteCallAudit/SiteCallAuditActor.cs` (and any `SiteCallAuditIngestActor` that maps `SiteCallOperational` → `SiteCall`)
|
||||
- Modify: `src/ScadaLink.ConfigurationDatabase/Repositories/SiteCallAuditRepository.cs` — extend monotonic upsert SQL to include `SourceNode`
|
||||
- Modify: tests in `tests/ScadaLink.SiteCallAudit.Tests/SiteCallAuditActorTests.cs` and `tests/ScadaLink.ConfigurationDatabase.Tests/Repositories/SiteCallAuditRepositoryTests.cs`
|
||||
- Modify: site emitters of `SiteCallOperational` — `src/ZB.MOM.WW.ScadaBridge.ExternalSystemGateway/ExternalSystemClient.cs`, `src/ZB.MOM.WW.ScadaBridge.DataConnectionLayer/...` (cached DB write), and the S&F retry path that emits `Attempted` packets
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.SiteCallAudit/SiteCallAuditActor.cs` (and any `SiteCallAuditIngestActor` that maps `SiteCallOperational` → `SiteCall`)
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Repositories/SiteCallAuditRepository.cs` — extend monotonic upsert SQL to include `SourceNode`
|
||||
- Modify: tests in `tests/ZB.MOM.WW.ScadaBridge.SiteCallAudit.Tests/SiteCallAuditActorTests.cs` and `tests/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests/Repositories/SiteCallAuditRepositoryTests.cs`
|
||||
|
||||
**Step 1: Failing test — central persists `SourceNode` on upsert; subsequent upsert with same id keeps SourceNode set even if newer packet has it null**
|
||||
|
||||
@@ -777,11 +777,11 @@ git commit -m "feat(sitecall-audit): carry + persist SourceNode end-to-end via c
|
||||
## Task 15: Central UI — add Node column + filter to AuditLog grid
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/ScadaLink.CentralUI/Components/Audit/AuditResultsGrid.razor` + `.razor.cs` (add column entry to `AllColumns`)
|
||||
- Modify: `src/ScadaLink.CentralUI/Components/Audit/AuditFilterBar.razor` (add a text or multi-select Node filter)
|
||||
- Modify: `src/ScadaLink.CentralUI/Services/AuditLogQueryService.cs` (extend the query/filter model)
|
||||
- Modify: tests in `tests/ScadaLink.CentralUI.Tests/Services/AuditLogQueryServiceTests.cs`
|
||||
- Modify: `tests/ScadaLink.CentralUI.PlaywrightTests/Audit/AuditGridColumnTests.cs` — assert the Node column renders
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditResultsGrid.razor` + `.razor.cs` (add column entry to `AllColumns`)
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/AuditFilterBar.razor` (add a text or multi-select Node filter)
|
||||
- Modify: `src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/AuditLogQueryService.cs` (extend the query/filter model)
|
||||
- Modify: tests in `tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Services/AuditLogQueryServiceTests.cs`
|
||||
- Modify: `tests/ZB.MOM.WW.ScadaBridge.CentralUI.PlaywrightTests/Audit/AuditGridColumnTests.cs` — assert the Node column renders
|
||||
|
||||
**Step 1: Failing test — query service supports `SourceNode` filter**
|
||||
|
||||
@@ -812,7 +812,7 @@ git commit -m "feat(ui): add Node column + filter to AuditLog grid"
|
||||
|
||||
## Task 16: Central UI — add Node column + filter to Notifications grid
|
||||
|
||||
**Files:** mirror Task 15 for `src/ScadaLink.CentralUI/Components/Pages/Notifications/NotificationReport.razor` and its query service. No filter populate-from-DB required if scope is per-site already; a free-text Node filter is acceptable for v1.
|
||||
**Files:** mirror Task 15 for `src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationReport.razor` and its query service. No filter populate-from-DB required if scope is per-site already; a free-text Node filter is acceptable for v1.
|
||||
|
||||
```bash
|
||||
git commit -m "feat(ui): add Node column + filter to NotificationOutbox grid"
|
||||
@@ -822,7 +822,7 @@ git commit -m "feat(ui): add Node column + filter to NotificationOutbox grid"
|
||||
|
||||
## Task 17: Central UI — add Node column + filter to SiteCalls grid
|
||||
|
||||
**Files:** mirror Task 15 for `src/ScadaLink.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor`.
|
||||
**Files:** mirror Task 15 for `src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/SiteCalls/SiteCallsReport.razor`.
|
||||
|
||||
```bash
|
||||
git commit -m "feat(ui): add Node column + filter to SiteCalls grid"
|
||||
@@ -856,7 +856,7 @@ git commit -m "chore(docker): set NodeName on all 8 cluster nodes"
|
||||
**Step 1: Build**
|
||||
|
||||
```bash
|
||||
dotnet build ScadaLink.slnx
|
||||
dotnet build ZB.MOM.WW.ScadaBridge.slnx
|
||||
```
|
||||
|
||||
Expected: 0 errors, 0 warnings.
|
||||
@@ -864,12 +864,12 @@ Expected: 0 errors, 0 warnings.
|
||||
**Step 2: Run the touched test projects**
|
||||
|
||||
```bash
|
||||
dotnet test tests/ScadaLink.AuditLog.Tests/ScadaLink.AuditLog.Tests.csproj
|
||||
dotnet test tests/ScadaLink.NotificationOutbox.Tests/ScadaLink.NotificationOutbox.Tests.csproj
|
||||
dotnet test tests/ScadaLink.SiteCallAudit.Tests/ScadaLink.SiteCallAudit.Tests.csproj
|
||||
dotnet test tests/ScadaLink.Communication.Tests/ScadaLink.Communication.Tests.csproj
|
||||
dotnet test tests/ScadaLink.ConfigurationDatabase.Tests/ScadaLink.ConfigurationDatabase.Tests.csproj
|
||||
dotnet test tests/ScadaLink.CentralUI.Tests/ScadaLink.CentralUI.Tests.csproj
|
||||
dotnet test tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests/ZB.MOM.WW.ScadaBridge.AuditLog.Tests.csproj
|
||||
dotnet test tests/ZB.MOM.WW.ScadaBridge.NotificationOutbox.Tests/ZB.MOM.WW.ScadaBridge.NotificationOutbox.Tests.csproj
|
||||
dotnet test tests/ZB.MOM.WW.ScadaBridge.SiteCallAudit.Tests/ZB.MOM.WW.ScadaBridge.SiteCallAudit.Tests.csproj
|
||||
dotnet test tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/ZB.MOM.WW.ScadaBridge.Communication.Tests.csproj
|
||||
dotnet test tests/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests.csproj
|
||||
dotnet test tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests.csproj
|
||||
```
|
||||
|
||||
Expected: all green. If anything fails, fix it before proceeding.
|
||||
@@ -877,7 +877,7 @@ Expected: all green. If anything fails, fix it before proceeding.
|
||||
**Step 3: Full solution test (sanity)**
|
||||
|
||||
```bash
|
||||
dotnet test ScadaLink.slnx --no-build
|
||||
dotnet test ZB.MOM.WW.ScadaBridge.slnx --no-build
|
||||
```
|
||||
|
||||
---
|
||||
@@ -902,7 +902,7 @@ Expected: image rebuilt, all 8 containers up. Watch for migration apply on centr
|
||||
# 3. Run a script that calls ExternalSystem.CachedCall → produces CachedSubmit/Forwarded/Attempted/Delivered
|
||||
|
||||
# Then check SourceNode is populated:
|
||||
docker exec scadalink-mssql /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'YourStrong!Passw0rd' -Q "SELECT TOP 20 Channel, Kind, SourceSiteId, SourceNode, Status FROM scadalink.dbo.AuditLog ORDER BY OccurredAtUtc DESC"
|
||||
docker exec scadabridge-mssql /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'YourStrong!Passw0rd' -Q "SELECT TOP 20 Channel, Kind, SourceSiteId, SourceNode, Status FROM scadabridge.dbo.AuditLog ORDER BY OccurredAtUtc DESC"
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
Reference in New Issue
Block a user