using System.Reflection; using Omika.Core.Observability; using Omika.Core.Observability.Outbox; namespace Omika.Tests.Observability.Outbox; /// Garde-fous d'architecture (§53, §84) : isolation métier, absence d'infra externe. public class DiagnosticArchitectureTests { [Fact] public void DiagnosticOutbox_HasNoReferenceToBusinessOutboxAssembly() { // Le DiagnosticOutbox vit dans Omika.Core ; l'outbox métier vit dans // Omika.App.Local. Core ne référence pas App.Local (jamais l'inverse). Assembly core = typeof(DiagnosticOutbox).Assembly; Assert.DoesNotContain(core.GetReferencedAssemblies(), a => a.Name == "Omika.App.Local"); } [Fact] public void DiagnosticOutboxStoreInterface_IsProviderAgnostic() { // Les signatures du store ne font référence à aucun type de l'outbox métier // (IOutboxRepository / OutboxOperation) ni à SQLite. foreach (MethodInfo method in typeof(IDiagnosticOutboxStore).GetMethods()) { Assert.DoesNotContain("Business", method.Name, StringComparison.Ordinal); foreach (Type type in method.ReturnType.GetGenericArguments() .Concat(method.GetParameters().SelectMany(p => ParameterTypes(p.ParameterType)))) { Assert.DoesNotContain("OutboxRepository", type.FullName ?? "", StringComparison.Ordinal); Assert.DoesNotContain("Microsoft.Data.Sqlite", type.FullName ?? "", StringComparison.Ordinal); } } } [Fact] public void Core_DoesNotReferenceExternalObservabilityInfrastructure() { Assembly core = typeof(OmikaEvent).Assembly; string[] referenced = core.GetReferencedAssemblies().Select(a => a.Name!).ToArray(); Assert.DoesNotContain(referenced, n => n.Contains("OpenTelemetry")); Assert.DoesNotContain(referenced, n => n.Contains("ClickHouse")); Assert.DoesNotContain(referenced, n => n.Contains("SigNoz")); // Aucun type OTLP / OpenTelemetry dans l'assemblage Core. Assert.DoesNotContain( core.GetTypes(), t => (t.FullName ?? "").Contains("Otlp", StringComparison.OrdinalIgnoreCase) || (t.FullName ?? "").Contains("OpenTelemetry", StringComparison.OrdinalIgnoreCase)); } private static IEnumerable ParameterTypes(Type type) { if (type.IsGenericType) { foreach (Type argument in type.GetGenericArguments()) { foreach (Type inner in ParameterTypes(argument)) { yield return inner; } } } else { yield return type; } } }