This commit is contained in:
2026-07-15 02:42:16 +03:00
parent be2a24bfd9
commit 3a1b95dbc5
27 changed files with 1767 additions and 197 deletions
@@ -5,7 +5,8 @@ namespace Esiur.Security.Management;
/// <summary>
/// Evaluates whether a resource operation is admitted by rate-control policy.
/// A manager may assign <see cref="ResourceManagerContext.Delay"/> when allowing
/// an operation that should be queued.
/// an operation that should be queued and
/// <see cref="ResourceManagerContext.SupportsDelay"/> is true.
/// </summary>
public interface IRateControlManager : IResourceManager
{
@@ -10,9 +10,9 @@ using System.Linq;
namespace Esiur.Security.Management;
/// <summary>
/// Immutable metadata describing a resource operation being evaluated by managers.
/// <see cref="Delay"/> is the sole mutable value and allows rate-control managers to
/// request deferred execution.
/// Metadata describing a resource operation being evaluated by managers. Operation
/// identity is immutable; <see cref="Delay"/> and <see cref="DenialReason"/> let a
/// manager return admission details.
/// </summary>
public sealed class ResourceManagerContext
{
@@ -23,9 +23,16 @@ public sealed class ResourceManagerContext
public Session? Session { get; }
public IResource? Resource { get; }
public MemberDef? Member { get; }
public TypeDef? TypeDefinition { get; }
public ActionType Action { get; }
public object? Inquirer { get; }
/// <summary>
/// Indicates whether the protocol operation can honor an allowed delayed ruling.
/// Rate managers should inspect this before reserving queued capacity.
/// </summary>
public bool SupportsDelay { get; }
/// <summary>
/// Gets the local attributes that configure manager policy for the target member.
/// The collection is a defensive, read-only snapshot.
@@ -33,10 +40,17 @@ public sealed class ResourceManagerContext
public IReadOnlyList<Attribute> MemberPolicyAttributes => _memberPolicyAttributes;
/// <summary>
/// Gets or sets an optional delay requested by a rate-control manager.
/// Gets or sets an optional delay requested by a rate-control manager. Execute,
/// property-set, and pull-stream operations honor delayed rulings; operations
/// that cannot be delayed fail closed.
/// </summary>
public TimeSpan Delay { get; set; }
/// <summary>
/// Optional public-safe reason supplied by a manager when it denies an operation.
/// </summary>
public string? DenialReason { get; set; }
public ResourceManagerContext(
Warehouse warehouse,
EpConnection? connection,
@@ -45,15 +59,19 @@ public sealed class ResourceManagerContext
MemberDef? member,
ActionType action,
object? inquirer = null,
IEnumerable<Attribute>? memberPolicyAttributes = null)
IEnumerable<Attribute>? memberPolicyAttributes = null,
TypeDef? typeDefinition = null,
bool supportsDelay = false)
{
Warehouse = warehouse ?? throw new ArgumentNullException(nameof(warehouse));
Connection = connection;
Session = session;
Resource = resource;
Member = member;
TypeDefinition = typeDefinition ?? resource?.Instance?.Definition ?? member?.Definition;
Action = action;
Inquirer = inquirer;
SupportsDelay = supportsDelay;
var policies = memberPolicyAttributes?.ToArray() ?? Array.Empty<Attribute>();
if (policies.Any(attribute => attribute == null))
@@ -0,0 +1,43 @@
using Esiur.Security.Permissions;
using System;
namespace Esiur.Security.Management;
/// <summary>
/// Aggregated decisions from each independent manager category.
/// An allow in one category never grants admission in another category.
/// </summary>
public sealed class ResourceManagerEvaluation
{
public Ruling Permissions { get; }
public Ruling RateControl { get; }
public Ruling Auditing { get; }
public TimeSpan Delay { get; }
public string? PermissionsDenialReason { get; }
public string? RateControlDenialReason { get; }
public string? AuditingDenialReason { get; }
public bool IsAllowed =>
Permissions == Ruling.Allowed &&
RateControl != Ruling.Denied &&
Auditing != Ruling.Denied;
internal ResourceManagerEvaluation(
Ruling permissions,
Ruling rateControl,
Ruling auditing,
TimeSpan delay,
string? permissionsDenialReason,
string? rateControlDenialReason,
string? auditingDenialReason)
{
Permissions = permissions;
RateControl = rateControl;
Auditing = auditing;
Delay = delay > TimeSpan.Zero ? delay : TimeSpan.Zero;
PermissionsDenialReason = permissionsDenialReason;
RateControlDenialReason = rateControlDenialReason;
AuditingDenialReason = auditingDenialReason;
}
}