Add comprehensive documentation and GitHub Copilot configuration: - docs/knowledge/: 17 deep-dive knowledge files covering value semantics, RVM architecture, builtins, FFI boundary, feature composition, error handling migration, policy evaluation security, Rego semantics, interpreter/compiler architecture, Azure Policy/RBAC, engine API, time builtins, language extension guide, tooling architecture, causality/partial eval, Rego compiler, Azure Policy aliases, and telemetry/diagnostics - .github/agents/: 16 role-specific AI agent definitions (red-teamer, semantics-expert, architect, performance-engineer, test-engineer, verification-engineer, security-auditor, reliability-engineer, support-engineer, ci-engineer, refactorer, api-steward, program-manager, demo-engineer, dx-engineer, tech-lead) - .github/skills/: 6 workflow skill definitions (thorough-review, design-alternatives, add-builtin, opa-conformance, security-review, verification) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: anakrish <35780660+anakrish@users.noreply.github.com>
5.8 KiB
Knowledge: Engine API
Deep knowledge about the public Engine API (src/engine.rs). Read this
before modifying the engine's public interface or evaluation flow.
Engine Structure
pub struct Engine {
modules: Rc<Vec<Ref<Module>>>, // Loaded policy modules
interpreter: Interpreter, // Execution engine
prepared: bool, // Compilation state flag
rego_v1: bool, // Language version
execution_timer_config: Option<ExecutionTimerConfig>,
policy_length_config: PolicyLengthConfig, // File size limits
}
Primary API Flow
1. Policy Loading
pub fn add_policy(&mut self, path: String, rego: String) -> Result<String>
pub fn add_policy_from_file(&mut self, path: impl AsRef<Path>) -> Result<String>
- Parses Rego source via Lexer → Parser → AST
- Returns the package name (e.g.,
"data.test") - Sets
prepared = falseto trigger recompilation on next eval - Enforces
PolicyLengthConfiglimits
2. Data and Input
pub fn add_data(&mut self, data: Value) -> Result<()> // Merge into data document
pub fn add_data_json(&mut self, data: &str) -> Result<()>
pub fn set_input(&mut self, input: Value)
pub fn set_input_json(&mut self, input: &str) -> Result<()>
pub fn clear_data(&mut self)
add_data() merges into the existing data document. It requires the value
to be an object (checked). Conflict detection on merge.
3. Evaluation
| Method | Returns | Use Case |
|---|---|---|
eval_rule(rule) |
Value |
Direct rule evaluation (fast) |
eval_query(query, tracing) |
QueryResults |
OPA-compatible with bindings |
eval_bool_query(query) |
bool |
Boolean shortcut |
eval_allow_query() |
bool |
Common deny-by-default pattern |
eval_modules(tracing) |
Value |
Evaluate all loaded modules |
4. Compilation (for repeated evaluation)
pub fn compile_for_target(&mut self) -> Result<CompiledPolicy>
pub fn compile_with_entrypoint(&mut self, rule: &Rc<str>) -> Result<CompiledPolicy>
Returns CompiledPolicy — an immutable, precompiled artifact that can be
evaluated many times with different inputs:
let compiled = engine.compile_for_target()?;
// Later, potentially in a different thread:
let result = compiled.eval_with_input(input)?;
5. Configuration
pub fn set_rego_v0(&mut self, enabled: bool) // Language version
pub fn set_execution_timer_config(config) // Timeout limits
pub fn set_policy_length_config(config) // File size limits
pub fn set_strict_builtin_errors(b: bool) // Error vs Undefined for type mismatches
pub fn add_extension(name, arity, func) // Custom functions
CompiledPolicy
pub struct CompiledPolicy {
inner: Rc<CompiledPolicyData>,
}
struct CompiledPolicyData {
modules: Rc<Vec<Ref<Module>>>,
schedule: Option<Rc<Schedule>>, // Pre-computed statement order
rules: Map<String, Vec<Ref<Rule>>>, // Rule path → rules
default_rules: Map<String, Vec<...>>, // Default rules
imports: BTreeMap<String, Ref<Expr>>,
functions: FunctionTable, // User-defined functions
rule_paths: Set<String>,
loop_hoisting_table: HoistedLoopsLookup, // Pre-computed loop info
data: Option<Value>, // Preloaded data
strict_builtin_errors: bool,
extensions: Map<String, (u8, Rc<Box<dyn Extension>>)>,
}
Benefits of CompiledPolicy:
- Schedule, loop hoisting, and function table pre-computed once
- Can be cloned cheaply (Rc internals)
- Supports repeated evaluation with different inputs
- Thread-safe when using
arcfeature
Internal Evaluation Flow
When eval_rule() is called:
-
Preparation (if not
prepared):- Gather all functions from modules →
FunctionTable - Run scheduler on all queries →
Schedule - Run loop hoister →
HoistedLoopsLookup - Build
CompiledPolicyData - Set
prepared = true
- Gather all functions from modules →
-
Interpreter setup:
- Set data and input on interpreter
- Set current module context
-
Evaluation:
- Find rule in
compiled_policy.rules - Call
interpreter.eval_rule() - Return result
- Find rule in
Multiple Module Management
- Modules stored as
Rc<Vec<Ref<Module>>> - Each module declares a package namespace (e.g.,
package auth) - Rules qualified by package path:
data.auth.allow - Imports resolve cross-module references
- Functions tracked globally in
FunctionTable
Extensions API
Custom functions can be registered at runtime:
engine.add_extension(
"custom.check".to_string(),
2, // arity
Rc::new(Box::new(|args| -> Result<Value> {
// implementation
})),
)?;
Extensions are available to Rego policies as builtin functions.
Metadata Access
pub fn get_packages(&self) -> Result<Vec<String>> // Package names
pub fn get_policies(&self) -> Result<Vec<Source>> // Policy sources
pub fn get_policies_as_json(&self) -> Result<String> // JSON representation
pub fn get_coverage_report(&self) -> Result<Report> // Code coverage
Key Design Decisions
-
Lazy compilation — policies aren't compiled until first evaluation.
preparedflag tracks whether compilation is needed. -
Data merging —
add_data()merges, doesn't replace. Multiple data sources accumulate into the data document. -
Input replacement —
set_input()replaces, doesn't merge. Each evaluation gets a fresh input. -
Clone semantics —
Engine::clone()clones all persistent state (policies, data, configuration) but resets runtime state (processed rules, caches). The clone is ready for independent evaluation.