SboxSuperuser/Api/AuditIntent.cs

Represents a recorded audit intent for a host action. It stores immutable IDs, serializes a snapshot of caller-safe fields (actor kind/subject, origin, command, safe arguments, targets, createdUtc) into a JSON string, and validates that JSON against the package TransactionFormat before construction completes.

File Access
using System.Globalization;
using System.Text.Json;
using SboxSuperuser.Core.Contracts;

namespace SboxSuperuser;

/// <summary>Host-recorded action intent data, never an identity credential or a successful action outcome.</summary>
public sealed class AuditIntent
{
	/// <summary>Gets the unique action ID.</summary>
	public Guid Id { get; }

	/// <summary>Gets the correlated command request ID.</summary>
	public Guid RequestId { get; }

	private readonly string _json;

	/// <summary>Snapshots caller-safe audit fields supplied by trusted host code; outcome is always Unknown.</summary>
	public AuditIntent( Guid id, Guid requestId, ActorKind actorKind, string actorSubject,
		CommandOrigin origin, string command, DateTimeOffset createdUtc,
		IReadOnlyDictionary<string, string> safeArguments = null, IEnumerable<string> targets = null )
	{
		Id = id;
		RequestId = requestId;
		var arguments = safeArguments is null ? new Dictionary<string, string>()
			: safeArguments.ToDictionary( pair => pair.Key, pair => pair.Value, StringComparer.Ordinal );
		var targetCopy = ContractGuard.Copy( targets ?? Array.Empty<string>(), nameof( targets ) );
		_json = JsonSerializer.Serialize( new
		{
			id, requestId, actorKind = actorKind.ToString(), actorSubject, origin = origin.ToString(), command,
			safeArguments = arguments, targets = targetCopy,
			createdUtc = createdUtc.ToString( "O", CultureInfo.InvariantCulture ), outcome = "Unknown"
		} );
		try
		{
			Core.Storage.TransactionFormat.Validate( "{\"state\":{},\"auditIntents\":[" + _json + "]}" );
		}
		catch ( Exception error ) when ( error is FormatException or JsonException or InvalidOperationException )
		{
			throw new ArgumentException( "Audit intent fields are invalid.", nameof( id ), error );
		}
	}

	internal string ToJson() => _json;
}