Condition-expression model and triple-array serialization for the policy
builder's condition editor (e.g. if/branch nodes and fault-injection
vars).
This is the TypeScript counterpart of the Rust condition parser in
src/vars/mod.rs (Expr::parse): the triple-array dialect where a rule is
[subject, op, value], the negated [subject, "!", op, value], or a unary
[subject, "present"|"absent"|"is_null"]; groups are ["AND"|"OR", ...]
or ["NOT", child] (heads case-insensitive). Subjects are either flat var
names (http_*, arg_*, cookie_*, or a bare var name) or JSONPath
queries over a request/response JSON body ($..., request_body:$...,
response_body:$...).
ConditionNode is the builder-friendly model the UI edits;
toExpr/fromExpr convert it to/from the triple-array form
used in policy YAML. toVarsList/fromVarsList handle the
fault-injection-style vars list, which is an OR-of-ANDed-expressions
rather than a single top-level AND.
Round-trip fidelity: fromExpr(toExpr(m)) deep-equals m for any model
built by this module's own constructors, and toExpr(fromExpr(e)) equals
e for any expression this module can represent. Anything the builder
model cannot represent (non-scalar operands, malformed groups, ...) makes
fromExpr/fromVarsList return null rather than a mangled model. Two
narrow, deliberate exceptions to byte-identical round-tripping: != is
normalized to its ~= alias at parse time (identical Rust-side semantics),
and a var-subject name typed with a legacy $/${...} wrapper (the
VarInput catalog-suggestion convention) has that wrapper stripped at
serialize time (see stripLegacyDollar) -- neither changes what the
expression means.
Condition-expression model and triple-array serialization for the policy builder's condition editor (e.g.
if/branch nodes and fault-injectionvars).This is the TypeScript counterpart of the Rust condition parser in
src/vars/mod.rs(Expr::parse): the triple-array dialect where a rule is[subject, op, value], the negated[subject, "!", op, value], or a unary[subject, "present"|"absent"|"is_null"]; groups are["AND"|"OR", ...]or["NOT", child](heads case-insensitive). Subjects are either flat var names (http_*,arg_*,cookie_*, or a bare var name) or JSONPath queries over a request/response JSON body ($...,request_body:$...,response_body:$...).ConditionNode is the builder-friendly model the UI edits; toExpr/fromExpr convert it to/from the triple-array form used in policy YAML. toVarsList/fromVarsList handle the fault-injection-style
varslist, which is an OR-of-ANDed-expressions rather than a single top-level AND.Round-trip fidelity:
fromExpr(toExpr(m))deep-equalsmfor any model built by this module's own constructors, andtoExpr(fromExpr(e))equalsefor any expression this module can represent. Anything the builder model cannot represent (non-scalar operands, malformed groups, ...) makesfromExpr/fromVarsListreturnnullrather than a mangled model. Two narrow, deliberate exceptions to byte-identical round-tripping:!=is normalized to its~=alias at parse time (identical Rust-side semantics), and avar-subject name typed with a legacy$/${...}wrapper (theVarInputcatalog-suggestion convention) has that wrapper stripped at serialize time (see stripLegacyDollar) -- neither changes what the expression means.Pure module: no React imports, no side effects.