namespace Tiku.IntegrationTests; public sealed class ArchitectureBoundaryTests { [Fact] public void Business_code_does_not_bypass_tenant_query_boundaries() { var root = FindRepositoryRoot(); var sourceRoots = new[] { "Tiku.Api", "Tiku.Application", "Tiku.Infrastructure" }; var forbidden = new[] { "IgnoreQueryFilters(", "FromSql(", "FromSqlRaw(", "FromSqlInterpolated(", "ExecuteSql(", "ExecuteSqlRaw(", "ExecuteSqlInterpolated(", "new NpgsqlCommand(" }; var violations = sourceRoots .SelectMany(directory => Directory.EnumerateFiles( Path.Combine(root, directory), "*.cs", SearchOption.AllDirectories)) .Where(path => !path.Contains( $"{Path.DirectorySeparatorChar}Persistence{Path.DirectorySeparatorChar}Migrations{Path.DirectorySeparatorChar}", StringComparison.Ordinal)) .SelectMany(path => File.ReadLines(path) .Select((line, index) => new { path, line, lineNumber = index + 1 })) .Where(candidate => forbidden.Any(symbol => candidate.line.Contains(symbol, StringComparison.Ordinal))) .Select(candidate => $"{Path.GetRelativePath(root, candidate.path)}:{candidate.lineNumber}") .ToArray(); Assert.True( violations.Length == 0, $"Forbidden tenant-boundary bypasses were found:{Environment.NewLine}{string.Join(Environment.NewLine, violations)}"); } [Fact] public void Business_code_does_not_depend_on_supabase_or_removed_provider_models() { var root = FindRepositoryRoot(); var sourceRoots = new[] { "Tiku.Api", "Tiku.Application", "Tiku.Domain", "Tiku.Infrastructure" }; var forbidden = new[] { "Supabase", "supabase_storage", "SUPABASE_", "TenantAuthProvider", "TenantPaymentAccount", "TenantPaymentMode", "TenantPaymentAccountStatus", "TenantAuthProviderStatus" }; var allowedPathFragments = new[] { $"{Path.DirectorySeparatorChar}Persistence{Path.DirectorySeparatorChar}Migrations{Path.DirectorySeparatorChar}" }; var violations = sourceRoots .SelectMany(directory => Directory.EnumerateFiles( Path.Combine(root, directory), "*.cs", SearchOption.AllDirectories)) .Where(path => !allowedPathFragments.Any(fragment => path.Contains(fragment, StringComparison.Ordinal))) .SelectMany(path => File.ReadLines(path) .Select((line, index) => new { path, line, lineNumber = index + 1 })) .Where(candidate => forbidden.Any(symbol => candidate.line.Contains(symbol, StringComparison.Ordinal))) .Select(candidate => $"{Path.GetRelativePath(root, candidate.path)}:{candidate.lineNumber}") .ToArray(); Assert.True( violations.Length == 0, $"Forbidden external-provider coupling was found:{Environment.NewLine}{string.Join(Environment.NewLine, violations)}"); } [Fact] public void Production_code_does_not_reference_removed_wechat_payment_sdk() { var root = FindRepositoryRoot(); var sourceRoots = new[] { "Tiku.Api", "Tiku.Application", "Tiku.Domain", "Tiku.Infrastructure", "Tiku.Worker" }; var forbidden = new[] { "SKIT.FlurlHttpClient.Wechat" }; var violations = sourceRoots .SelectMany(directory => Directory.EnumerateFiles( Path.Combine(root, directory), "*.cs", SearchOption.AllDirectories)) .Where(path => !path.Contains( $"{Path.DirectorySeparatorChar}Persistence{Path.DirectorySeparatorChar}Migrations{Path.DirectorySeparatorChar}", StringComparison.Ordinal)) .SelectMany(path => File.ReadLines(path) .Select((line, index) => new { path, line, lineNumber = index + 1 })) .Where(candidate => forbidden.Any(symbol => candidate.line.Contains(symbol, StringComparison.Ordinal))) .Select(candidate => $"{Path.GetRelativePath(root, candidate.path)}:{candidate.lineNumber}") .ToArray(); Assert.True( violations.Length == 0, $"Removed WeChat payment SDK references were found:{Environment.NewLine}{string.Join(Environment.NewLine, violations)}"); } [Fact] public void Business_layers_do_not_reference_third_party_provider_sdks() { var root = FindRepositoryRoot(); var sourceRoots = new[] { "Tiku.Api", "Tiku.Application", "Tiku.Domain" }; var forbidden = new[] { "AlibabaCloud.", "Aliyun.OSS", "Senparc.Weixin", "AlipaySDKNet", "Aop.Api" }; var violations = sourceRoots .SelectMany(directory => Directory.EnumerateFiles( Path.Combine(root, directory), "*.cs", SearchOption.AllDirectories)) .SelectMany(path => File.ReadLines(path) .Select((line, index) => new { path, line, lineNumber = index + 1 })) .Where(candidate => forbidden.Any(symbol => candidate.line.Contains(symbol, StringComparison.Ordinal))) .Select(candidate => $"{Path.GetRelativePath(root, candidate.path)}:{candidate.lineNumber}") .ToArray(); Assert.True( violations.Length == 0, $"Business-layer third-party provider SDK references were found:{Environment.NewLine}{string.Join(Environment.NewLine, violations)}"); } private static string FindRepositoryRoot() { var directory = new DirectoryInfo(AppContext.BaseDirectory); while (directory is not null && !File.Exists(Path.Combine(directory.FullName, "TIKU-BACKEND.slnx"))) { directory = directory.Parent; } return directory?.FullName ?? throw new DirectoryNotFoundException("Repository root was not found."); } }