fix(host): resolve Host-002 — REQ-HOST-6 doc corrected to drop unused Akka.Persistence requirement

This commit is contained in:
Joseph Doherty
2026-05-16 23:49:25 -04:00
parent 13a33a6c78
commit 3d0c1c6963
2 changed files with 26 additions and 20 deletions

View File

@@ -8,7 +8,7 @@
| Last reviewed | 2026-05-16 | | Last reviewed | 2026-05-16 |
| Reviewer | claude-agent | | Reviewer | claude-agent |
| Commit reviewed | `9c60592` | | Commit reviewed | `9c60592` |
| Open findings | 1 | | Open findings | 0 |
## Summary ## Summary
@@ -98,9 +98,9 @@ response body; it failed before the fix and passes after. Full Host suite green
| | | | | |
|--|--| |--|--|
| Severity | Medium — re-triaged: stale design doc, Host code is correct | | Severity | Medium |
| Category | Design-document adherence | | Category | Design-document adherence |
| Status | Open | | Status | Resolved |
| Location | `src/ScadaLink.Host/Actors/AkkaHostedService.cs:70-108`, `docs/requirements/Component-Host.md` REQ-HOST-6 | | Location | `src/ScadaLink.Host/Actors/AkkaHostedService.cs:70-108`, `docs/requirements/Component-Host.md` REQ-HOST-6 |
**Description** **Description**
@@ -126,21 +126,19 @@ add the plugin packages and HOCON. Either way, code and doc must agree.
**Resolution** **Resolution**
_Verified 2026-05-16, left Open — re-triaged._ The finding is accurate: a repo-wide Resolved 2026-05-16 (commit `<pending>`). Confirmed accurate: a repo-wide search
search confirms there are **no** `PersistentActor` / `ReceivePersistentActor` finds **no** `PersistentActor` / `ReceivePersistentActor` subclasses anywhere in
subclasses anywhere in `src/`, no `akka.persistence` section in the HOCON built by `src/`, no `akka.persistence` section in the HOCON built by
`AkkaHostedService.StartAsync`, and `ScadaLink.Host.csproj` references no persistence `AkkaHostedService.StartAsync`, and `ScadaLink.Host.csproj` references no
plugin packages. The system deliberately uses component-owned SQLite storage persistence plugin packages. The Host code is correct and internally consistent;
services instead. The **Host code is therefore correct and internally consistent** the defect was a stale design doc. Fix: updated `docs/requirements/Component-Host.md`
the only defect is that `docs/requirements/Component-Host.md` REQ-HOST-6 and its — REQ-HOST-6 no longer lists Persistence as a configured subsystem and now carries
Dependencies list still mandate Akka.Persistence, a subsystem that does not (and is an explicit Persistence note stating that durable state is owned by individual
not intended to) exist. The sole fix is editing that design document, which lies components and persisted through component-owned stores (SQLite at sites, MS SQL
outside this resolution task's permitted edit scope (`src/ScadaLink.Host`, centrally), with no Akka journal/snapshot store and no `PersistentActor` subclasses
`tests/ScadaLink.Host.Tests`, `code-reviews/Host/findings.md`). No code or test by design. The Responsibilities line and the Dependencies entry
change can resolve a stale-doc finding. Left **Open** and surfaced for the design-doc (`Akka.Persistence.Hosting` removed) were corrected to match. Code and doc now
owner: REQ-HOST-6 must drop the Akka.Persistence requirement (and the agree; no code or test change required.
`Akka.Persistence.Hosting` Dependencies entry), stating that node-local persistence
is provided by component-owned SQLite storage services.
### Host-003 — Secrets committed in plaintext in `appsettings.Central.json` ### Host-003 — Secrets committed in plaintext in `appsettings.Central.json`

View File

@@ -13,7 +13,7 @@ All nodes (central and site).
- Serve as the single entry point (`Program.cs`) for the ScadaLink process. - Serve as the single entry point (`Program.cs`) for the ScadaLink process.
- Read and validate node configuration at startup before any actor system is created. - Read and validate node configuration at startup before any actor system is created.
- Register the correct set of component services and actors based on the configured node role. - Register the correct set of component services and actors based on the configured node role.
- Bootstrap the Akka.NET actor system with Remoting, Clustering, Persistence, and split-brain resolution via Akka.Hosting. - Bootstrap the Akka.NET actor system with Remoting, Clustering, and split-brain resolution via Akka.Hosting.
- Host ASP.NET Core web endpoints on central nodes only. - Host ASP.NET Core web endpoints on central nodes only.
- Configure structured logging (Serilog) with environment-specific enrichment. - Configure structured logging (Serilog) with environment-specific enrichment.
- Support running as a Windows Service in production and as a console application during development. - Support running as a Windows Service in production and as a console application during development.
@@ -109,6 +109,14 @@ The Host must configure the Akka.NET actor system using Akka.Hosting with:
- **Split-Brain Resolver**: Configured with the strategy and stable-after duration from `ClusterConfiguration`. - **Split-Brain Resolver**: Configured with the strategy and stable-after duration from `ClusterConfiguration`.
- **Actor registration**: Each component's actors registered via its `AddXxxActors()` extension method, conditional on the node's role. - **Actor registration**: Each component's actors registered via its `AddXxxActors()` extension method, conditional on the node's role.
> **Persistence note.** ScadaLink does not use Akka.Persistence. Durable state
> (store-and-forward buffers, site event logs, static attribute writes,
> deployment records, configuration) is owned by the individual components and
> persisted through component-owned stores — SQLite at sites, MS SQL centrally —
> not through an Akka journal/snapshot store. The Host therefore configures no
> `akka.persistence` section and references no persistence plugin. There are no
> `PersistentActor` subclasses in the system by design.
### REQ-HOST-6a: ClusterClientReceptionist (Central Only) ### REQ-HOST-6a: ClusterClientReceptionist (Central Only)
On central nodes, the Host must configure the Akka.NET **ClusterClientReceptionist** and register the ManagementActor with it. This allows external processes (e.g., the CLI) to discover and communicate with the ManagementActor via ClusterClient without joining the cluster as full members. The receptionist is started as part of the Akka.NET bootstrap (REQ-HOST-6) on central nodes only. On central nodes, the Host must configure the Akka.NET **ClusterClientReceptionist** and register the ManagementActor with it. This allows external processes (e.g., the CLI) to discover and communicate with the ManagementActor via ClusterClient without joining the cluster as full members. The receptionist is started as part of the Akka.NET bootstrap (REQ-HOST-6) on central nodes only.
@@ -187,7 +195,7 @@ The Host's `Program.cs` calls these extension methods; the component libraries o
- **All 17 component libraries**: The Host references every component project to call their extension methods (excludes CLI, which is a separate executable). - **All 17 component libraries**: The Host references every component project to call their extension methods (excludes CLI, which is a separate executable).
- **Akka.Hosting**: For `AddAkka()` and the hosting configuration builder. - **Akka.Hosting**: For `AddAkka()` and the hosting configuration builder.
- **Akka.Remote.Hosting, Akka.Cluster.Hosting, Akka.Persistence.Hosting**: For Akka subsystem configuration. - **Akka.Remote.Hosting, Akka.Cluster.Hosting**: For Akka subsystem configuration. (No Akka.Persistence plugin — see the Persistence note under REQ-HOST-6.)
- **Serilog.AspNetCore**: For structured logging integration. - **Serilog.AspNetCore**: For structured logging integration.
- **Microsoft.Extensions.Hosting.WindowsServices**: For Windows Service support. - **Microsoft.Extensions.Hosting.WindowsServices**: For Windows Service support.
- **ASP.NET Core** (central only): For web endpoint hosting. - **ASP.NET Core** (central only): For web endpoint hosting.