fix(security): wrap the ConfigDb key store on admin nodes + registration guard

This commit is contained in:
Joseph Doherty
2026-08-20 09:45:08 -04:00
parent 6048257dfe
commit 39a10a277a
7 changed files with 100 additions and 9 deletions
@@ -14,8 +14,19 @@ namespace ZB.MOM.WW.OtOpcUa.Host.OpcUa;
/// <b>A driver-only node has no ConfigDb since per-cluster mesh Phase 4</b>, so this store cannot be
/// registered there; that node uses <see cref="ArtifactApiKeyStore"/> instead (#520 stage 4).
/// <para>
/// Reading per request is what makes revocation immediate here, which is why this store is
/// preferred wherever a ConfigDb exists — including on a fused admin+driver node.
/// Reading per activation is what makes revocation prompt here, which is why this store is
/// preferred wherever a ConfigDb exists — including on a fused admin+driver node. ⚠️ It reaches a
/// <b>new session activation</b> only: an already-open session re-checks its key against the
/// in-memory artifact snapshot on every operation, not against this store, so clearing
/// <c>Enabled</c> here does not stop an open session until the next deployment. See
/// <c>docs/security.md</c>.
/// </para>
/// <para>
/// ⚠️ <b>In production this store is WRAPPED by <see cref="BoundedApiKeyStore"/></b> (arch-review
/// 03/S18), because these queries run inline in the SDK's impersonation callback under a
/// SessionManager-wide lock. A call may therefore be cancelled by the wrapper's deadline even
/// though the caller passed <see cref="CancellationToken.None"/> — the resulting
/// <see cref="OperationCanceledException"/> is a denial, not a bug.
/// </para>
/// <para>
/// ⚠️ <b>The ConfigDb holds the WHOLE fleet's ACL rows, not just this node's cluster's.</b> That is