using ZB.MOM.WW.OtOpcUa.Core.Authorization;
namespace ZB.MOM.WW.OtOpcUa.Server.Security;
///
/// Maps a driver-side full reference (e.g. "TestMachine_001/Oven/SetPoint") to the
/// the Phase 6.2 evaluator walks. Today a simplified resolver that
/// returns a cluster-scoped + tag-only scope — the deeper UnsArea / UnsLine / Equipment
/// path lookup from the live Configuration DB is a Stream C.12 follow-up.
///
///
/// The flat cluster-level scope is sufficient for v2 GA because Phase 6.2 ACL grants
/// at the Cluster scope cascade to every tag below (decision #129 — additive grants). The
/// finer hierarchy only matters when operators want per-area or per-equipment grants;
/// those still work for Cluster-level grants, and landing the finer resolution in a
/// follow-up doesn't regress the base security model.
///
/// Thread-safety: the resolver is stateless once constructed. Callers may cache a
/// single instance per DriverNodeManager without locks.
///
public sealed class NodeScopeResolver
{
private readonly string _clusterId;
public NodeScopeResolver(string clusterId)
{
ArgumentException.ThrowIfNullOrWhiteSpace(clusterId);
_clusterId = clusterId;
}
///
/// Resolve a node scope for the given driver-side .
/// Phase 1 shape: returns ClusterId + TagId = fullReference only;
/// NamespaceId / UnsArea / UnsLine / Equipment stay null. A future resolver will
/// join against the Configuration DB to populate the full path.
///
public NodeScope Resolve(string fullReference)
{
ArgumentException.ThrowIfNullOrWhiteSpace(fullReference);
return new NodeScope
{
ClusterId = _clusterId,
TagId = fullReference,
Kind = NodeHierarchyKind.Equipment,
};
}
}