SboxSuperuser/Api/AdminActionRequest.cs

Represents a bounded admin moderation request. It stores an AdminAction enum, a canonical Steam ID, a printable reason and an optional duration, validates inputs in the constructor and can convert itself to an internal CommandRequest.

Credential Access
using SboxSuperuser.Core.Contracts;
using SboxSuperuser.Core.Identity;

namespace SboxSuperuser;

/// <summary>Exact-target moderation input; contains no actor, permission or console text.</summary>
public sealed class AdminActionRequest
{
	/// <summary>Gets the moderation operation.</summary>
	public AdminAction Action { get; }

	/// <summary>Gets the canonical target Steam ID; names are never used for mutations.</summary>
	public string SteamId { get; }

	/// <summary>Gets the operator's printable reason.</summary>
	public string Reason { get; }

	/// <summary>Gets an explicit duration such as 30m, 7d or permanent for ban/mute.</summary>
	public string Duration { get; }

	/// <summary>Creates bounded input; permission, duration parsing and target protection remain host-side.</summary>
	public AdminActionRequest( AdminAction action, string steamId, string reason, string duration = "" )
	{
		ContractGuard.EnumValue( action, nameof( action ) );
		SteamIdentity.Validate( steamId, nameof( steamId ) );
		if ( string.IsNullOrWhiteSpace( reason ) || reason.Length > 256 || reason.Any( char.IsControl )
			|| duration is null || duration.Length > 32 || duration.Any( char.IsControl )
			|| action is AdminAction.Ban or AdminAction.Mute && string.IsNullOrWhiteSpace( duration )
			|| action is not (AdminAction.Ban or AdminAction.Mute) && duration.Length != 0 )
		{
			throw new ArgumentException( "A printable reason (1–256 characters) and an explicit ban/mute duration are required." );
		}
		Action = action;
		SteamId = steamId;
		Reason = reason;
		Duration = duration;
	}

	internal CommandRequest ToCommand( Guid requestId ) => new( Action.ToString().ToLowerInvariant(),
		Action is AdminAction.Ban or AdminAction.Mute ? new[] { SteamId, Duration, Reason } : new[] { SteamId, Reason }, requestId );
}