diff --git a/AppInspector.RulesEngine/Schema/RuleSchemaProvider.cs b/AppInspector.RulesEngine/Schema/RuleSchemaProvider.cs
index c3214d70..d0902414 100644
--- a/AppInspector.RulesEngine/Schema/RuleSchemaProvider.cs
+++ b/AppInspector.RulesEngine/Schema/RuleSchemaProvider.cs
@@ -35,6 +35,34 @@ public RuleSchemaProvider(string? customSchemaPath = null)
}
}
+ ///
+ /// Private constructor for factory methods
+ ///
+ private RuleSchemaProvider(JsonSchema schema)
+ {
+ _schema = schema;
+ }
+
+ ///
+ /// Create a schema provider from schema content string
+ ///
+ /// The JSON schema content as a string
+ /// A new RuleSchemaProvider instance
+ public static RuleSchemaProvider FromSchemaContent(string schemaContent)
+ {
+ if (schemaContent is null)
+ {
+ throw new ArgumentNullException(nameof(schemaContent));
+ }
+ if (string.IsNullOrWhiteSpace(schemaContent))
+ {
+ throw new ArgumentException("Schema content cannot be empty or whitespace.", nameof(schemaContent));
+ }
+
+ var schema = LoadSchemaFromContent(schemaContent);
+ return new RuleSchemaProvider(schema);
+ }
+
private JsonSchema LoadEmbeddedSchema()
{
var assembly = Assembly.GetExecutingAssembly();
@@ -42,13 +70,18 @@ private JsonSchema LoadEmbeddedSchema()
?? throw new InvalidOperationException($"Could not find embedded schema resource: {SCHEMA_RESOURCE_NAME}");
using var reader = new StreamReader(stream);
var schemaJson = reader.ReadToEnd();
- return JsonSchema.FromText(schemaJson);
+ return LoadSchemaFromContent(schemaJson);
}
private JsonSchema LoadSchemaFromFile(string path)
{
var schemaJson = File.ReadAllText(path);
- return JsonSchema.FromText(schemaJson);
+ return LoadSchemaFromContent(schemaJson);
+ }
+
+ private static JsonSchema LoadSchemaFromContent(string schemaContent)
+ {
+ return JsonSchema.FromText(schemaContent);
}
///
diff --git a/AppInspector.Tests/RuleProcessor/SchemaValidationTests.cs b/AppInspector.Tests/RuleProcessor/SchemaValidationTests.cs
index ea7c18b1..03df7e2f 100644
--- a/AppInspector.Tests/RuleProcessor/SchemaValidationTests.cs
+++ b/AppInspector.Tests/RuleProcessor/SchemaValidationTests.cs
@@ -26,6 +26,92 @@ public void SchemaProvider_LoadsEmbeddedSchema()
Assert.NotNull(schema);
}
+ [Fact]
+ public void SchemaProvider_FromSchemaContent_LoadsSchema()
+ {
+ // Load embedded schema content first to use as test data
+ var defaultProvider = new RuleSchemaProvider();
+ var schemaJson = JsonSerializer.Serialize(defaultProvider.GetSchema());
+
+ // Create provider from schema content
+ var provider = RuleSchemaProvider.FromSchemaContent(schemaJson);
+ var schema = provider.GetSchema();
+
+ Assert.NotNull(schema);
+ }
+
+ [Fact]
+ public void SchemaProvider_FromSchemaContent_WithNullContent_ThrowsException()
+ {
+ Assert.Throws(() => RuleSchemaProvider.FromSchemaContent(null));
+ }
+
+ [Fact]
+ public void SchemaProvider_FromSchemaContent_WithEmptyContent_ThrowsException()
+ {
+ Assert.Throws(() => RuleSchemaProvider.FromSchemaContent(string.Empty));
+ }
+
+ [Fact]
+ public void SchemaProvider_FromSchemaContent_ValidatesRules()
+ {
+ // Use a minimal schema that requires id and name
+ var minimalSchema = @"{
+ ""$schema"": ""http://json-schema.org/draft-07/schema#"",
+ ""type"": ""array"",
+ ""items"": {
+ ""type"": ""object"",
+ ""required"": [""id"", ""name"", ""tags"", ""patterns""],
+ ""properties"": {
+ ""id"": { ""type"": ""string"", ""minLength"": 1 },
+ ""name"": { ""type"": ""string"" },
+ ""description"": { ""type"": ""string"" },
+ ""tags"": {
+ ""type"": ""array"",
+ ""minItems"": 1,
+ ""items"": { ""type"": ""string"" }
+ },
+ ""patterns"": {
+ ""type"": ""array"",
+ ""minItems"": 1,
+ ""items"": {
+ ""type"": ""object"",
+ ""required"": [""pattern"", ""type""],
+ ""properties"": {
+ ""pattern"": { ""type"": ""string"" },
+ ""type"": { ""type"": ""string"" }
+ }
+ }
+ }
+ }
+ }
+ }";
+
+ var provider = RuleSchemaProvider.FromSchemaContent(minimalSchema);
+
+ var validRule = new Rule
+ {
+ Id = "TEST001",
+ Name = "Test Rule",
+ Description = "A test rule",
+ Tags = new[] { "Test.Tag" },
+ Patterns = new[]
+ {
+ new SearchPattern
+ {
+ Pattern = "test",
+ PatternType = PatternType.String,
+ Scopes = new[] { PatternScope.Code },
+ Confidence = Confidence.High
+ }
+ }
+ };
+
+ var result = provider.ValidateRule(validRule);
+
+ Assert.True(result.IsValid);
+ }
+
[Fact]
public void ValidRule_PassesSchemaValidation()
{