The zamburak-monty crate provides a governed execution path around the
vendored full-monty interpreter. A GovernedRunner wraps a compiled
MontyRun with a Zamburak observer and mediates every external-function call
through a deterministic ExternalCallMediator hook.
Constructing a `GovernedRunner`
use std::sync::{Arc, Mutex};
use zamburak_monty::{
AllowAllMediator, ExternalCallMediator, GovernedRunner,
};
let monty_run = monty::MontyRun::new(
"x = 1 + 2\nx".to_owned(), "test.py", vec![],
).expect("parse failed");
let mediator: Arc<Mutex<dyn ExternalCallMediator>> =
Arc::new(Mutex::new(AllowAllMediator));
let runner = GovernedRunner::new(monty_run, mediator);
Selecting an `ExternalCallMediator`
The mediator trait defines the deterministic hook invoked at each external-call
boundary. Implementations receive a CallContext and return a
MediationDecision:
MediationDecision::Allow— proceed with the external call,MediationDecision::Deny { reason }— block the call with an explanation,MediationDecision::RequireConfirmation { request }— yield to the host for interactive approval.
Built-in mediators:
AllowAllMediator— unconditionally allows every call (testing and permissive mode),DenyAllMediator— unconditionally denies every call (deny-path testing),PolicyMediator— evaluates calls against loaded policy rules (production use; see Policy-backed mediation below).
Each CallContext now includes an ifc payload describing the observer-driven
information-flow state at that boundary:
propagation_mode—NormalorStrict,aggregate_summary— dependency summary for the whole call,control_context— the active program-counter summary,arg_summaries— per-positional-argument provenance,kwarg_summaries— per-keyword(key, value)provenance in the same order asCallContext::kwarg_names,kwarg_names— resolved keyword identifiers used to align policy rules with the corresponding keyword value summary.
For tests or embedder-controlled execution, GovernedRunner::with_ifc_config
can override the default IFC configuration before execution starts. This is
useful when strict mode must be forced or value seed labels must be customized.
GovernedIfcConfig::strict_with_boundary_seeds and
IfcValueSeedConfig::boundary_defaults provide the shared strict/boundary
defaults used by the governed IFC tests.
`GovernedRunProgress` yield states
After execution, the governed runner returns a GovernedRunProgress enum:
Complete(MontyObject)— execution finished with a final value,ExternalCallPending { context, suspended }— an external call was allowed and execution paused so the host can provide the actual result via theSuspendedCall,Denied { reason, function_name, call_id }— an external call was denied by the mediator,AwaitConfirmation { context, suspended }— execution paused pending host confirmation; theSuspendedCallcan be resumed after approval,NameLookup { name, inner }— execution paused for an unresolved name lookup,ResolveFutures(...)— execution paused waiting for async futures.
Minimal governed run example
use std::sync::{Arc, Mutex};
use monty::{MontyObject, MontyRun, NoLimitTracker, PrintWriter};
use zamburak_monty::{
AllowAllMediator, ExternalCallMediator, GovernedRunProgress,
GovernedRunner,
};
let monty_run = MontyRun::new(
"x = 1 + 2\nx".to_owned(), "test.py", vec![],
).expect("parse failed");
let mediator: Arc<Mutex<dyn ExternalCallMediator>> =
Arc::new(Mutex::new(AllowAllMediator));
let runner = GovernedRunner::new(monty_run, mediator);
match runner.run_no_limits(vec![]) {
Ok(GovernedRunProgress::Complete(value)) => {
assert_eq!(value, MontyObject::Int(3));
}
other => panic!("unexpected result: {other:?}"),
}
Inspecting IFC at an external-call boundary
use std::sync::{Arc, Mutex};
use monty::{MontyRun, NoLimitTracker, PrintWriter};
use zamburak_monty::{
AllowAllMediator, ExternalCallMediator, GovernedRunProgress,
GovernedRunner,
};
let monty_run = MontyRun::new("effect(\"x\")".to_owned(), "test.py", vec![])
.expect("parse failed");
let mediator: Arc<Mutex<dyn ExternalCallMediator>> =
Arc::new(Mutex::new(AllowAllMediator));
let runner = GovernedRunner::new(monty_run, mediator);
match runner.run_no_limits(vec![]) {
Ok(GovernedRunProgress::ExternalCallPending { context, .. }) => {
assert_eq!(context.function_name, "effect");
assert!(!context.ifc.arg_summaries.is_empty());
}
other => panic!("unexpected result: {other:?}"),
}