Native OCaml Rego/OPA policy engine
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

ocaml-rego: add strict_error mode

OPA's [strict_error] mode propagates builtin errors to the caller
instead of treating them as [Undefined]. Useful for catching bugs
that would otherwise silently produce empty results.

[Rego.set_strict engine true] enables it. The flag threads through to
[env.strict] and gates the [try/with Eval_error] around [eval_builtin]
in [eval_call]. The OPA test runner picks up [strict_error] from each
case's JSON so the upstream conformance suite drives it.

+17 -2
+7 -1
lib/eval.ml
··· 31 31 mocks : (string list * mock) list; 32 32 (** [with X as Y] mocks: full path -> mock. Last entry wins so inner 33 33 [with] modifiers shadow outer ones. *) 34 + strict : bool; 35 + (** When [true], builtin errors propagate to the caller instead of being 36 + treated as undefined — OPA's [strict_error] mode. *) 34 37 } 35 38 36 39 type bindings = (string * Value.t) list ··· 1930 1933 match user_function env path vargs with 1931 1934 | Some v -> Some v 1932 1935 | None -> ( 1933 - try Some (eval_builtin name vargs) with Eval_error _ -> None)) 1936 + if env.strict then Some (eval_builtin name vargs) 1937 + else 1938 + try Some (eval_builtin name vargs) 1939 + with Eval_error _ -> None)) 1934 1940 in 1935 1941 eval_seq env bnds args 1936 1942 |> List.concat_map (fun (vargs, b) ->
+6 -1
lib/rego.ml
··· 95 95 type engine = { 96 96 mutable modules : (string * Ast.rego_module) list; 97 97 mutable data : Value.t; 98 + mutable strict : bool; 99 + (** When [true], builtin errors propagate instead of producing [Undefined] 100 + — matches OPA's [strict_error] mode. *) 98 101 } 99 102 100 - let engine () = { modules = []; data = Value.Object [] } 103 + let engine () = { modules = []; data = Value.Object []; strict = false } 104 + let set_strict e b = e.strict <- b 101 105 let add_data e data = e.data <- data 102 106 103 107 let add_data_json e json = ··· 125 129 imports = []; 126 130 evaluating = []; 127 131 mocks = []; 132 + strict = e.strict; 128 133 } 129 134 130 135 let eval e ~input query =
+4
test/test_opa_runner.ml
··· 86 86 want_error : string option; 87 87 want_error_code : string option; 88 88 sort_bindings : bool; 89 + strict_error : bool; 89 90 } 90 91 91 92 let case_of_json j = ··· 118 119 let want_error = json_string_opt (field "want_error") in 119 120 let want_error_code = json_string_opt (field "want_error_code") in 120 121 let sort_bindings = json_bool_default false (field "sort_bindings") in 122 + let strict_error = json_bool_default false (field "strict_error") in 121 123 { 122 124 note; 123 125 modules; ··· 128 130 want_error; 129 131 want_error_code; 130 132 sort_bindings; 133 + strict_error; 131 134 } 132 135 133 136 let cases_of_file path = ··· 200 203 201 204 let run_case case = 202 205 let engine = Rego.engine () in 206 + Rego.set_strict engine case.strict_error; 203 207 (match case.data with Some v -> Rego.add_data engine v | None -> ()); 204 208 let load_ok = ref true in 205 209 List.iteri