feat: Complete target system with C# bindings and resource inference (#458)

* feat: Add Schema Registry and Validation Framework

This commit introduces a comprehensive schema registry and validation framework, providing schema-based validation of resources and policy effects.

- Thread-safe, in-memory registry for schema storage and management
- Global registry patterns for effects and resources
- Concurrent access with proper error handling
- Unicode schema names support

- JSON Schema-compliant validation for all primitive types
- Advanced constraint validation (patterns, ranges, length limits)
- Discriminated union support with anyOf schemas
- Detailed error reporting with nested validation paths
- Discriminated subobject validation for polymorphic schemas

- **Registry Tests**: All registry operations
- **Effect Tests**: Policy effect validation
- **Resource Tests**: Resource validation
- **Validation Tests**: Core validation engine
- Thread-safety, error handling, integration scenarios, edge cases

- **Dependencies**: dashmap, once_cell, regex
- **Thread Safety**: Minimal locking with Rc<Schema> sharing
- **Error Types**: TypeMismatch, OutOfRange, PatternMismatch, etc.

- Complete schema registry and validation subsystem
- Comprehensive test coverage
- Foundation for policy validation in Regorus

Benchmarks:

- Criterion benchmarks for basic types, effects and Azure resources
- Performance range: 3.22ns (string) to 34.74µs (Azure VM resource schema validation)
- String withs patterns validation: 30.2µs. Need to explore whether regex caching helps
  bring this down.
- Azure policy effects: 188ns-1.4µs

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>

* feat: Complete target system with C# bindings and resource inference

- Add comprehensive target system with TargetRegistry and target-aware compilation
- Implement resource type inference from policy equality expressions
- Create modular C# bindings with separate wrapper classes for each concept
- Add thread-safe CompiledPolicy with reference counting for safe disposal
- Enhance FFI with detailed error propagation and target functionality
- Create TargetExampleApp demonstrating Azure Policy integration
- Add CI/CD pipeline testing for all C# applications
- Support target definitions with schema validation and resource selectors
- Implement PolicyModule struct and target-aware compilation methods
- Add comprehensive test coverage for target functionality

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>

---------

Signed-off-by: Anand Krishnamoorthi <anakrish@microsoft.com>
This commit is contained in:
Anand Krishnamoorthi
2025-08-19 20:23:43 -05:00
committed by GitHub
parent 3c33d31d08
commit cc917ea75d
71 changed files with 10278 additions and 1000 deletions

View File

@@ -1881,18 +1881,75 @@ impl<'source> Parser<'source> {
Ok(imports)
}
fn parse_string_literal(&mut self) -> Result<String> {
if self.tok.0 != TokenKind::String {
bail!(self.tok.1.error("expected string literal"));
}
let string_span = self.tok.1.clone();
let target_value =
match serde_json::from_str::<Value>(format!("\"{}\"", string_span.text()).as_str()) {
Ok(v) => v,
Err(e) => {
bail!(string_span.error(&format!("invalid string literal: {}", e)));
}
};
self.next_token()?;
match target_value.as_string() {
Ok(s) => Ok(s.as_ref().to_string()),
Err(_) => {
bail!(string_span.error("invalid string value"));
}
}
}
fn parse_target_rule(&mut self) -> Result<Option<String>> {
// Check if the current token starts a target rule: __target__
if self.tok.0 == TokenKind::Ident && self.token_text() == "__target__" {
// Parse __target__
self.next_token()?;
// Expect := operator
if self.token_text() != ":=" {
bail!(self.tok.1.error("expected ':=' after __target__"));
}
self.next_token()?;
// Parse the target name string using the helper function
let target_string = self.parse_string_literal()?;
Ok(Some(target_string))
} else {
Ok(None)
}
}
pub fn parse(&mut self) -> Result<Module> {
let package = self.parse_package()?;
let imports = self.parse_imports()?;
let target = self.parse_target_rule()?;
if target.is_some() {
self.rego_v1 = true;
}
let mut policy = vec![];
while self.tok.0 != TokenKind::Eof {
policy.push(Ref::new(self.parse_rule()?));
if self.token_text() == "__target__" {
bail!(self
.tok
.1
.error("__target__ must be defined before any rules"));
}
}
let m = Module {
package,
imports,
target,
policy,
rego_v1: self.rego_v1,
num_expressions: self.eidx,