Skip to main content
← Back to list
01Issue
FeatureShippedSwamp CLI
Assigneesadam

#376 Expose cel-js Environment to extensions for custom CEL evaluation

Opened by adam · 5/19/2026· Shipped 5/19/2026

Problem

Extensions cannot currently evaluate CEL expressions as part of their own implementation. CEL is used internally for workflow conditions, data queries, forEach expansion, and definition evaluation, but the evaluator is not reachable from extension code.

A concrete use case: an SSH factory model that defines a fleet up front and exposes methods like exec. Users should be able to target hosts with expressions like tags.contains("web") && region == "us-east-1" — predicates the extension evaluates against fleet members at call time. More complex extensions may want to register their own functions, types, or operators scoped to their own evaluation context.

Proposed Solution

Expose cel-js Environment directly from src/libswamp/mod.ts via a factory that returns a fresh, isolated environment seeded with swamp's baseline registrations (bigint/double arithmetic overloads, namespace types). Extensions construct their own environment, register whatever functions or types they need, and call parse() / evaluate() themselves.

CEL should be CEL — no wrapper, no swamp-specific abstraction layer. The cel-js Environment API already provides everything needed:

  • parse(expression) returns a reusable evaluation function — extensions decide compile-once-evaluate-many vs re-parse per call
  • evaluate() is async and natively propagates Promises through registered functions
  • registerFunction / registerType / registerOperator / clone — extensions shape their own environment without touching swamp's global one

This is per-extension, not global registration — no collision concerns, no shared state, no impact on swamp's internal CEL surface.

Scope of Changes

  • New factory in src/infrastructure/cel/cel_evaluator.ts (or a sibling file) that builds a fresh Environment with the baseline registrations currently in CelEvaluator's constructor (lines 191–328)
  • Re-export Environment and the factory from src/libswamp/mod.ts
  • MethodContext (src/domain/models/model.ts:146) gets the factory available so model method extensions can call it
  • Documentation in the extension authoring docs covering registration and compile-once vs per-call parse patterns

Alternatives Considered

  1. celFilter(items, predicate) helper on MethodContext — narrowest API, covers the SSH targeting case directly, but locks extensions out of anything beyond predicate filtering (custom functions, custom types, richer integrations).
  2. Wrapped swamp-owned interface around Environment — gives swamp control over the public contract, but means re-exporting a subset of cel-js and giving up features like .check() for type validation. Delays the cost of a future cel-js replacement without eliminating it.
  3. Global CEL environment extension point — extensions register into the shared environment. Rejected: collision policy, lifecycle, and validation timing all become real design problems for no current need.

Direct `Environment` exposure is the simplest, most honest surface and matches the principle that CEL should be CEL.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPEDTRIAGE+ 12 MOREREVIEW+ 3 MOREPR_MERGEDSHIPPED

Shipped

5/19/2026, 10:29:40 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
adam assigned adam5/19/2026, 12:44:55 AM

Sign in to post a ripple.