// Copyright (c) StellaOps. Licensed under the BUSL-1.1. using StellaOps.HybridLogicalClock; using System.Security.Cryptography; using System.Text; namespace StellaOps.Eventing.Internal; /// /// Generates deterministic event IDs from event content. /// internal static class EventIdGenerator { /// /// Generates a deterministic event ID using SHA-256 hash of inputs. /// /// The correlation ID. /// The HLC timestamp. /// The service name. /// The event kind. /// First 32 hex characters of SHA-256 hash (128 bits). public static string Generate( string correlationId, HlcTimestamp tHlc, string service, string kind) { ArgumentException.ThrowIfNullOrWhiteSpace(correlationId); ArgumentException.ThrowIfNullOrWhiteSpace(service); ArgumentException.ThrowIfNullOrWhiteSpace(kind); using var hasher = IncrementalHash.CreateHash(HashAlgorithmName.SHA256); // Append all inputs in deterministic order hasher.AppendData(Encoding.UTF8.GetBytes(correlationId)); hasher.AppendData(Encoding.UTF8.GetBytes(tHlc.ToSortableString())); hasher.AppendData(Encoding.UTF8.GetBytes(service)); hasher.AppendData(Encoding.UTF8.GetBytes(kind)); var hash = hasher.GetHashAndReset(); // Return first 16 bytes (128 bits) as lowercase hex (32 chars) return Convert.ToHexString(hash.AsSpan(0, 16)).ToLowerInvariant(); } /// /// Computes SHA-256 digest of the payload. /// /// The canonicalized JSON payload. /// SHA-256 digest bytes. public static byte[] ComputePayloadDigest(string payload) { ArgumentNullException.ThrowIfNull(payload); return SHA256.HashData(Encoding.UTF8.GetBytes(payload)); } }