docs(secrets): reconcile 0.2.1 adoption - what was proven vs merely built
- All 4 apps on 0.2.1 (local branches, unpushed). - Records the corrected security story: the version bump closed NO advisory (all four repos already resolved patched 2.1.12); the real live vulnerability was in ScadaBridge, masked by a NuGetAuditSuppress, and was fixed by separate work. - Records the upstream 0.2.0 inert-Akka-replicator defect, its root cause (DI extensions with no container-building test - third instance of that class), and the 0.2.1 fix. - Marks clustered topology WIRED-but-default-OFF and explicitly NOT live-validated; Task 9 remains open and the topology is not 'adopted' until it passes.
This commit is contained in:
@@ -49,11 +49,64 @@ construction).
|
||||
|
||||
### Open
|
||||
|
||||
- ⬜ Bump the four apps `0.1.2` → `0.1.3`/`0.2.0` to pick up KEK rotation + the SQLitePCLRaw security fix.
|
||||
- ✅ **All four apps bumped `0.1.2` → `0.2.1`** (2026-07-18), each on a local `feat/secrets-0.2.0`
|
||||
branch, **not pushed**. HistorianGateway `bb9d923`, MxAccessGateway `b021e29`, OtOpcUa `1ccc237c`,
|
||||
ScadaBridge `0083ce35`.
|
||||
- **Correction:** the bump was originally justified as closing GHSA-2m69-gcr7-jv3q in all four
|
||||
apps. Measured against the `0.1.2` baseline in every repo, **all four already resolved the
|
||||
patched `SQLitePCLRaw.lib.e_sqlite3 2.1.12`** — two via their own pins, two transitively via
|
||||
`Auth.ApiKeys 0.1.5`. The bump delivers **no security change**; its real value is version
|
||||
currency, `secret rewrap-all` access, and being the precondition for the replicator packages.
|
||||
- ✅ **A real SQLite vulnerability WAS found and fixed — but by separate work, not the bump.**
|
||||
ScadaBridge's `NuGetAuditSuppress` was masking a **live** high-severity finding: only the Host
|
||||
project resolved a patched `2.1.12`; `AuditLog`, `SiteRuntime`, `StoreAndForward`,
|
||||
`SiteEventLogging` and 11 test projects still resolved the vulnerable **`2.1.11`**. Fixed with an
|
||||
explicit `2.1.12` pin per SQLite-consuming project and the suppression deleted (`2a0faeab`).
|
||||
MxAccessGateway's obsolete suppression removed likewise (`2f0cfe3`). Both suppressions rested on
|
||||
false premises (*"no patched release exists"* / *"only the 3.x line is patched"*) — `2.1.12`
|
||||
patches it within 2.1.x, verified by forced restore. HistorianGateway and OtOpcUa needed nothing.
|
||||
- Rejected `CentralPackageTransitivePinningEnabled`: it clears the advisory in one line but makes
|
||||
every central version a transitive ceiling, demanding `Google.Protobuf`, `Grpc.Net.Client`,
|
||||
`Microsoft.Data.SqlClient` and `Newtonsoft.Json` bumps. That is a gRPC/data-access change to a
|
||||
production SCADA platform and deserves its own reviewed commit. **Still open as a follow-up** —
|
||||
it is the better long-term posture.
|
||||
- ✅ `0.2.0` **PUBLISHED to the Gitea feed 2026-07-18** (all 5 packages; restore-verified from a
|
||||
scratch consumer — resolves `SQLitePCLRaw.lib.e_sqlite3 2.1.12`, `Microsoft.Data.SqlClient 6.0.2`,
|
||||
`Akka.Cluster.Tools 1.5.62`, and scans clean). Merged to `main` @ `15ef1f3`.
|
||||
- ⬜ Adopt a topology in ScadaBridge / OtOpcUa (config + shared KEK; no code change needed).
|
||||
- 🟡 **Topology WIRED in both clustered apps, default-OFF, NOT live-validated.**
|
||||
**OtOpcUa → Akka peer-to-peer** (one cluster; `DistributedPubSub` already in product use;
|
||||
`ActorSystem` in DI via `Akka.Hosting`; Akka 1.5.62 matches the package exactly).
|
||||
**ScadaBridge → SQL-Server hub mode**, because central and each site are *separate* Akka clusters
|
||||
— `DistributedPubSub` cannot cross that boundary, so an Akka replicator there would produce
|
||||
**secret islands that never reconcile while every node reports healthy**.
|
||||
- Both gate on `Secrets:Replication:Enabled`, **default false**, so current behaviour is
|
||||
unchanged. ScadaBridge additionally requires a non-blank hub connection string — its options
|
||||
`Validate()` eagerly, so unconditional wiring would have broken startup on every node.
|
||||
- Bootstrap constraint recorded: the hub connstr **cannot come from the hub**; it must be seeded
|
||||
in each node's local store or supplied via env.
|
||||
- ⬜ **Task 9, the G-2-class live gate, is NOT done** — write→resolve across nodes, tombstone
|
||||
propagation (no resurrection), partition survival, and the negative-KEK fail-closed control.
|
||||
Needs a 2-node OtOpcUa rig and a ScadaBridge central-pair + site + SQL hub. **The topology is
|
||||
not "adopted" until this passes.** Do not enable `Secrets:Replication:Enabled` anywhere first.
|
||||
|
||||
### Upstream defect found during adoption — `0.2.0` Akka replication was inert
|
||||
|
||||
- ✅ **Fixed in `0.2.1`, published to the feed 2026-07-18** (all 5 packages; all four apps consume it).
|
||||
`AddZbSecretsAkkaReplication` called `AddZbSecrets` **first**, which does
|
||||
`TryAddSingleton<ISecretReplicator, NoOpSecretReplicator>()`, so the package's own `TryAdd` was
|
||||
silently discarded. Replication published into a no-op sink and **no actor was ever spawned** —
|
||||
no exception, no log line. The SQL-Server replicator always had the correct order.
|
||||
- **Why it escaped:** the SQL-Server package had a DI test asserting its replicator type; the Akka
|
||||
package had none. Every Akka test exercised the actor, serializer and reconciler in isolation —
|
||||
**nothing built a container**. This is the **third** instance of this defect class in this library
|
||||
(inert `ISecretReplicator` seam → unregistered concrete `SqliteSecretStore` → this), all with one
|
||||
cause: DI extensions with no test that constructs the graph. `0.2.1` adds 5 such tests, verified
|
||||
to discriminate (2 fail on the old order).
|
||||
- **Testing note:** `Akka.TestKit` is the family convention for non-end-to-end Akka tests, but
|
||||
`Akka.TestKit.Xunit2` is **xunit-v2-only** and OtOpcUa's `Host.IntegrationTests` is on xunit.v3
|
||||
(`CS0433` if added). OtOpcUa's guards therefore assert on `ServiceCollection` descriptors — which
|
||||
is exactly where this defect lives — while actor creation and convergence stay covered by the
|
||||
library's own 2-node cluster suite.
|
||||
- ⬜ Per-app live wonder gates for the G-8 rotation path.
|
||||
- ⬜ Akka self-echo forwarding is only observable with **three** nodes; the 2-node rig covers the
|
||||
drift symptom, not the forwarding filter itself (noted in the test).
|
||||
|
||||
Reference in New Issue
Block a user