Compare commits

..

3 Commits

5 changed files with 137 additions and 12 deletions

View File

@ -636,5 +636,110 @@
}
}
]
},
{
"description": "STI Projections (Lacking Kind Discriminator Definitions)",
"database": {
"types": [
{
"name": "widget",
"variations": [
"widget"
],
"schemas": {
"widget": {
"type": "object",
"properties": {
"type": {
"type": "string"
}
}
},
"stock.widget": {
"type": "widget",
"properties": {
"kind": {
"type": "string"
},
"amount": {
"type": "integer"
}
}
},
"projected.widget": {
"type": "widget",
"properties": {
"alias": {
"type": "string"
}
}
}
}
}
],
"schemas": {
"stock_widget_validation": {
"type": "stock.widget"
},
"projected_widget_validation": {
"type": "projected.widget"
}
}
},
"tests": [
{
"description": "stock.widget securely expects kind when configured",
"schema_id": "stock_widget_validation",
"data": {
"type": "widget",
"amount": 5
},
"action": "validate",
"expect": {
"success": false,
"errors": [
{
"code": "MISSING_KIND",
"details": {
"path": ""
}
}
]
}
},
{
"description": "projected.widget seamlessly bypasses kind expectation when excluded from schema",
"schema_id": "projected_widget_validation",
"data": {
"type": "widget",
"alias": "Test Projection"
},
"action": "validate",
"expect": {
"success": true
}
},
{
"description": "projected.widget securely fails if user erroneously provides extra kind property",
"schema_id": "projected_widget_validation",
"data": {
"type": "widget",
"alias": "Test Projection",
"kind": "projected"
},
"action": "validate",
"expect": {
"success": false,
"errors": [
{
"code": "STRICT_PROPERTY_VIOLATION",
"details": {
"path": "kind"
}
}
]
}
}
]
}
]

View File

@ -1559,6 +1559,24 @@ fn test_polymorphism_4_1() {
crate::tests::runner::run_test_case(&path, 4, 1).unwrap();
}
#[test]
fn test_polymorphism_5_0() {
let path = format!("{}/fixtures/polymorphism.json", env!("CARGO_MANIFEST_DIR"));
crate::tests::runner::run_test_case(&path, 5, 0).unwrap();
}
#[test]
fn test_polymorphism_5_1() {
let path = format!("{}/fixtures/polymorphism.json", env!("CARGO_MANIFEST_DIR"));
crate::tests::runner::run_test_case(&path, 5, 1).unwrap();
}
#[test]
fn test_polymorphism_5_2() {
let path = format!("{}/fixtures/polymorphism.json", env!("CARGO_MANIFEST_DIR"));
crate::tests::runner::run_test_case(&path, 5, 2).unwrap();
}
#[test]
fn test_not_0_0() {
let path = format!("{}/fixtures/not.json", env!("CARGO_MANIFEST_DIR"));

View File

@ -24,9 +24,6 @@ impl<'a> ValidationContext<'a> {
if let Some(obj) = self.instance.as_object() {
for key in obj.keys() {
if key == "type" || key == "kind" {
continue; // Reserved keywords implicitly allowed
}
if !result.evaluated_keys.contains(key) && !self.overrides.contains(key) {
result.errors.push(ValidationError {
code: "STRICT_PROPERTY_VIOLATION".to_string(),

View File

@ -54,14 +54,19 @@ impl<'a> ValidationContext<'a> {
// If the target mathematically declares a horizontal structural STI variation natively
if schema_identifier_str.contains('.') {
if obj.get("kind").is_none() {
result.errors.push(ValidationError {
code: "MISSING_KIND".to_string(),
message: "Schema mechanically requires horizontal kind discrimination".to_string(),
path: self.path.clone(),
});
} else {
result.evaluated_keys.insert("kind".to_string());
let requires_kind = self.schema.compiled_properties.get()
.map_or(false, |p| p.contains_key("kind"));
if requires_kind {
if obj.get("kind").is_none() {
result.errors.push(ValidationError {
code: "MISSING_KIND".to_string(),
message: "Schema mechanically requires horizontal kind discrimination".to_string(),
path: self.path.clone(),
});
} else {
result.evaluated_keys.insert("kind".to_string());
}
}
}
} else {

View File

@ -1 +1 @@
1.0.118
1.0.120