using System.Text.Json.Nodes; using StellaOps.Findings.Ledger.Domain; using StellaOps.Findings.Ledger.WebService.Contracts; namespace StellaOps.Findings.Ledger.WebService.Mappings; public static class LedgerEventMapping { public static LedgerEventDraft ToDraft(this LedgerEventRequest request, TimeProvider? timeProvider = null) { ArgumentNullException.ThrowIfNull(request); timeProvider ??= TimeProvider.System; var recordedAt = (request.RecordedAt ?? timeProvider.GetUtcNow()).ToUniversalTime(); var payload = request.Payload is null ? new JsonObject() : (JsonObject)request.Payload.DeepClone(); var eventObject = new JsonObject { ["id"] = request.EventId.ToString(), ["type"] = request.EventType, ["tenant"] = request.TenantId, ["chainId"] = request.ChainId.ToString(), ["sequence"] = request.Sequence, ["policyVersion"] = request.PolicyVersion, ["artifactId"] = request.ArtifactId, ["finding"] = new JsonObject { ["id"] = request.Finding.Id, ["artifactId"] = request.Finding.ArtifactId ?? request.ArtifactId, ["vulnId"] = request.Finding.VulnId }, ["actor"] = new JsonObject { ["id"] = request.Actor.Id, ["type"] = request.Actor.Type }, ["occurredAt"] = FormatTimestamp(request.OccurredAt), ["recordedAt"] = FormatTimestamp(recordedAt), ["payload"] = payload }; if (request.SourceRunId is Guid sourceRunId && sourceRunId != Guid.Empty) { eventObject["sourceRunId"] = sourceRunId.ToString(); } var envelope = new JsonObject { ["event"] = eventObject }; return new LedgerEventDraft( request.TenantId, request.ChainId, request.Sequence, request.EventId, request.EventType, request.PolicyVersion, request.Finding.Id, request.ArtifactId, request.SourceRunId, request.Actor.Id, request.Actor.Type, request.OccurredAt.ToUniversalTime(), recordedAt, payload, envelope, request.PreviousHash); } private static string FormatTimestamp(DateTimeOffset value) => value.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss.fff'Z'"); }