// Copyright (c) StellaOps. Licensed under the AGPL-3.0-or-later. using System.ComponentModel.DataAnnotations; using System.Reflection; using System.Text.Json.Serialization; using StellaOps.HybridLogicalClock; namespace StellaOps.Eventing.Models; /// /// Canonical event envelope for unified timeline. /// public sealed record TimelineEvent { /// /// Deterministic event ID: SHA-256(correlation_id || t_hlc || service || kind)[0:32] as hex. /// [JsonPropertyName("event_id")] public required string EventId { get; init; } /// /// HLC timestamp from StellaOps.HybridLogicalClock. /// [JsonPropertyName("t_hlc")] public required HlcTimestamp THlc { get; init; } /// /// Wall-clock time (informational only). /// [JsonPropertyName("ts_wall")] public required DateTimeOffset TsWall { get; init; } /// /// Service name (e.g., "Scheduler", "AirGap", "Attestor"). /// [JsonPropertyName("service")] public required string Service { get; init; } /// /// W3C Trace Context traceparent. /// [JsonPropertyName("trace_parent")] public string? TraceParent { get; init; } /// /// Correlation ID linking related events. /// [JsonPropertyName("correlation_id")] public required string CorrelationId { get; init; } /// /// Event kind (ENQUEUE, EXECUTE, EMIT, etc.). /// [JsonPropertyName("kind")] public required string Kind { get; init; } /// /// RFC 8785 canonicalized JSON payload. /// [JsonPropertyName("payload")] public required string Payload { get; init; } /// /// SHA-256 digest of Payload. /// [JsonPropertyName("payload_digest")] public required byte[] PayloadDigest { get; init; } /// /// Engine version for reproducibility. /// [JsonPropertyName("engine_version")] public required EngineVersionRef EngineVersion { get; init; } /// /// Optional DSSE signature. /// [JsonPropertyName("dsse_sig")] public string? DsseSig { get; init; } /// /// Schema version (current: 1). /// [JsonPropertyName("schema_version")] public int SchemaVersion { get; init; } = 1; } /// /// Engine version reference for reproducibility tracking. /// /// The name of the engine/service. /// The version string. /// SHA-256 digest of the source or assembly. public sealed record EngineVersionRef( [property: JsonPropertyName("engine_name")] string EngineName, [property: JsonPropertyName("version")] string Version, [property: JsonPropertyName("source_digest")] string SourceDigest) { /// /// Creates an EngineVersionRef from the specified assembly metadata. /// public static EngineVersionRef FromAssembly(Assembly assembly) { ArgumentNullException.ThrowIfNull(assembly); var name = assembly.GetName(); var version = name.Version?.ToString() ?? "0.0.0"; // Try to get source digest from assembly metadata var sourceDigest = assembly .GetCustomAttributes() .FirstOrDefault(a => a.Key == "SourceDigest")?.Value ?? "unknown"; return new EngineVersionRef(name.Name ?? "Unknown", version, sourceDigest); } /// /// Creates an EngineVersionRef from the entry assembly. /// public static EngineVersionRef FromEntryAssembly() { var assembly = Assembly.GetEntryAssembly() ?? throw new InvalidOperationException("No entry assembly found"); return FromAssembly(assembly); } } /// /// Pending event for batch emission. /// /// Correlation ID linking related events. /// Event kind (ENQUEUE, EXECUTE, etc.). /// Event payload object. public sealed record PendingEvent( string CorrelationId, string Kind, object Payload); /// /// Standard event kinds used across StellaOps services. /// public static class EventKinds { // Scheduler events public const string Enqueue = "ENQUEUE"; public const string Dequeue = "DEQUEUE"; public const string Execute = "EXECUTE"; public const string Complete = "COMPLETE"; public const string Fail = "FAIL"; // AirGap events public const string Import = "IMPORT"; public const string Export = "EXPORT"; public const string Merge = "MERGE"; public const string Conflict = "CONFLICT"; // Attestor events public const string Attest = "ATTEST"; public const string Verify = "VERIFY"; // Policy events public const string Evaluate = "EVALUATE"; public const string GatePass = "GATE_PASS"; public const string GateFail = "GATE_FAIL"; // VexLens events public const string Consensus = "CONSENSUS"; public const string Override = "OVERRIDE"; // Generic events public const string Emit = "EMIT"; public const string Ack = "ACK"; public const string Error = "ERR"; }