Files
lmxopcua/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Services/ILdapGroupRoleMappingService.cs
T
Joseph Doherty 2bae1b4c9f refactor(localdb): delete the dormant LiteDB LocalCache (superseded by ZB.MOM.WW.LocalDb)
Never registered in DI and dead since Phase 6.1. Keeping two unwired cache designs
invites the next reader to wire the wrong one.

Deletes all three test files - LiteDbConfigCacheTests.cs was missing from the plan's
list and would have failed to compile (it calls new LiteDB.LiteDatabase directly).
StaleConfigFlagTests lives inside ResilientConfigReaderTests.cs, so it goes too.

The XML-doc reference in ILdapGroupRoleMappingService is rewritten rather than removed:
it now records that no sign-in fallback exists and that reviving one means an admin-side
cache on LocalDb.
2026-07-20 10:46:07 -04:00

73 lines
4.1 KiB
C#

using ZB.MOM.WW.OtOpcUa.Configuration.Entities;
using ZB.MOM.WW.OtOpcUa.Configuration.Enums;
namespace ZB.MOM.WW.OtOpcUa.Configuration.Services;
/// <summary>
/// CRUD surface for <see cref="LdapGroupRoleMapping"/> — the control-plane mapping from
/// LDAP groups to Admin UI roles. Consumed only by Admin UI code paths; the OPC UA
/// data-path evaluator MUST NOT depend on this interface (see the
/// Phase 6.2 compliance check on control/data-plane separation).
/// </summary>
/// <remarks>
/// <para>
/// This service has no local-cache fallback: a DB outage during sign-in denies logins.
/// </para>
/// <para>
/// The Phase 6.1 <c>ResilientConfigReader</c> pipeline (timeout → retry →
/// fallback-to-sealed-snapshot) this was once expected to run behind was never wired to
/// anything and was deleted along with the rest of the dormant LiteDB local cache, which
/// <c>ZB.MOM.WW.LocalDb</c> supersedes. LocalDb caches the deployed-configuration artifact
/// for driver-role nodes; it does not currently cover admin-plane reads like this one.
/// Reviving the fallback means adding an admin-side cache on LocalDb, not restoring the
/// old pipeline.
/// </para>
/// </remarks>
public interface ILdapGroupRoleMappingService
{
/// <summary>List every mapping whose LDAP group matches one of <paramref name="ldapGroups"/>.</summary>
/// <remarks>
/// Hot path — fires on every sign-in. The default EF implementation relies on the
/// <c>IX_LdapGroupRoleMapping_Group</c> index. The match is a SQL <c>IN (…)</c> whose
/// case-sensitivity is determined by the <c>LdapGroup</c> column collation. Case-insensitive
/// behaviour requires a case-insensitive (CI) server or column collation — this is a
/// deployment requirement. On a case-sensitive-collation server the lookup will silently
/// miss rows that differ only in case.
/// </remarks>
/// <param name="ldapGroups">The LDAP groups to search for.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The mappings whose LDAP group matches one of <paramref name="ldapGroups"/>.</returns>
Task<IReadOnlyList<LdapGroupRoleMapping>> GetByGroupsAsync(
IEnumerable<string> ldapGroups, CancellationToken cancellationToken);
/// <summary>Enumerate every mapping; Admin UI listing only.</summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Every LDAP group role mapping.</returns>
Task<IReadOnlyList<LdapGroupRoleMapping>> ListAllAsync(CancellationToken cancellationToken);
/// <summary>Create a new grant.</summary>
/// <exception cref="InvalidLdapGroupRoleMappingException">
/// Thrown when the proposed row violates an invariant (IsSystemWide inconsistent with
/// ClusterId, duplicate (group, cluster) pair, etc.) — ValidatedLdapGroupRoleMappingService
/// is the write surface that enforces these; the raw service here surfaces DB-level violations.
/// </exception>
/// <param name="row">The LDAP group role mapping to create.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The created mapping row.</returns>
Task<LdapGroupRoleMapping> CreateAsync(LdapGroupRoleMapping row, CancellationToken cancellationToken);
/// <summary>Delete a mapping by its surrogate key.</summary>
/// <param name="id">The unique identifier of the mapping to delete.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
Task DeleteAsync(Guid id, CancellationToken cancellationToken);
}
/// <summary>Thrown when <see cref="LdapGroupRoleMapping"/> authoring violates an invariant.</summary>
public sealed class InvalidLdapGroupRoleMappingException : Exception
{
/// <summary>Initializes a new instance of the InvalidLdapGroupRoleMappingException.</summary>
/// <param name="message">The error message.</param>
public InvalidLdapGroupRoleMappingException(string message) : base(message) { }
}