feat(expression): ADR-0032 phase 1 — validate-by-default expression layer (no silent failure)#1517
Merged
Merged
Conversation
…ayer, no silent failure Fixes the #1491 class: a malformed predicate (notably the `{record.x}` template-brace-in-CEL mistake) was silently swallowed to `false`, so a flow "fired" with success but did nothing. - service-automation: evaluateCondition throws an attributed/corrective error instead of returning false; registerFlow parse-validates every predicate at registration (loud, located). - formula: shared validator (validateExpression / introspectScope / CEL_STDLIB_FUNCTIONS) with schema-aware field-existence + did-you-mean; the {{ }} template engine gains a formatter whitelist with defined value→string semantics (plain {{ path }} stays back-compatible; arbitrary-logic holes rejected). - cli: objectstack compile validates flow / validation-rule / field-formula predicates against the resolved object schema, failing the build with located corrective messages. - service-ai: agent-callable validate_expression tool for author-time self-correction. - spec: fix FlowSchema JSDoc example that taught the bad single-brace form. Tests: formula 74, service-automation 149, service-ai 412, cli 152, spec 6608, objectql 484, runtime 334 — all green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| while ((m = PATH_RE.exec(source)) !== null) { | ||
| refs.push(m[1]); | ||
| HOLE_RE.lastIndex = 0; | ||
| while ((m = HOLE_RE.exec(source)) !== null) { |
CodeQL flagged the template hole matcher `/\{\{\s*([^}]*?)\s*\}\}/` as a
polynomial-ReDoS: `\s` ⊆ `[^}]`, so wrapping the lazy group in `\s*` makes the
matcher ambiguous on untrusted template source. Switch to a single greedy
`/\{\{([^}]*)\}\}/` and strip surrounding whitespace in parseHole — provably
linear, identical behavior (74 formula tests green).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Phase 1 of ADR-0032 — the AI-safety spine: make a malformed expression impossible to ship silently, and give authors (esp. agents) a precise, fixable error. Fixes the #1491 class where a brace-in-CEL condition (
{record.rating} >= 4) was silently swallowed tofalse, so a flow "fired" withsuccessbut did nothing.Scope = the parts that are non-breaking and verifiable; the breaking cutovers are staged follow-ups (see below).
Changes
evaluateConditionno longer swallows a CEL failure tofalse; it throws an attributed, corrective error.registerFlownow parse-validates every predicate (start / decision / edge condition) at registration and fails loudly with location + source + the fix.validateExpression(role, src, schema?)+introspectScope+CEL_STDLIB_FUNCTIONS(schema-aware field-existence with did-you-mean). The{{ }}template engine gains a formatter whitelist (currency/number/percent/date/datetime/truncate/upper/lower/default/json) with defined value→string semantics; arbitrary-logic holes rejected; plain{{ path }}stays back-compatible.objectstack compilevalidates every flow / validation-rule / field-formula predicate against the resolved object schema and fails the build with located, corrective messages. (Resolves ADR open question Add metamodel interfaces for ObjectQL/ObjectUI contract #1.)validate_expressiontool for author-time self-correction.FlowSchemaJSDoc example that taught the bad single-bracecondition: "{amount} < 500"form.Both ADR open questions resolved: #1 (schema available at compile) and #2 (formatter catalog decided).
Verification
All green locally: formula 74, service-automation 149, service-ai 412, cli 152, spec 6608, objectql 484, runtime 334. All touched packages build. New negative tests cover brace-in-CEL rejection at runtime/registration/build; formatter tests cover the catalog.
Deliberately NOT in this PR (staged, breaking / cross-repo)
string→CELcoercion + migrate authoring sites to typed builders (examples + templates).{x}node-field usages to{{x}}.../objectui, separate repo).Phase 1 already contains the #1491 risk (loud at runtime, registration, and build).
🤖 Generated with Claude Code