ArchLinterNet.CEL 0.9.1

dotnet add package ArchLinterNet.CEL --version 0.9.1
                    
NuGet\Install-Package ArchLinterNet.CEL -Version 0.9.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ArchLinterNet.CEL" Version="0.9.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ArchLinterNet.CEL" Version="0.9.1" />
                    
Directory.Packages.props
<PackageReference Include="ArchLinterNet.CEL" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ArchLinterNet.CEL --version 0.9.1
                    
#r "nuget: ArchLinterNet.CEL, 0.9.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ArchLinterNet.CEL@0.9.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ArchLinterNet.CEL&version=0.9.1
                    
Install as a Cake Addin
#tool nuget:?package=ArchLinterNet.CEL&version=0.9.1
                    
Install as a Cake Tool

ArchLinterNet.CEL

A reusable, host-agnostic Common Expression Language (CEL) compilation and evaluation engine for .NET, implementing the ArchLinter CEL Profile v1 (arch-linter/cel/v1) — a deliberately bounded subset of CEL chosen for safety, determinism, and predictable evaluation cost.

ArchLinterNet.CEL has no dependency on ArchLinterNet.Core, ArchLinterNet.Cli, or ArchLinterNet.Testing, and pulls in no external CEL runtime, YAML, or reflection-based binding library. It can be referenced standalone by any .NET project that needs bounded expression evaluation over an explicit, schema-declared data model.

Status: early preview (0.x). The Profile v1 public API surface is stabilizing but is not yet guaranteed compatibility-frozen.

Install

dotnet add package ArchLinterNet.CEL

Quick start

using ArchLinterNet.CEL;
using ArchLinterNet.CEL.Profile;
using ArchLinterNet.CEL.Schema;
using ArchLinterNet.CEL.Values;

// 1. Declare the variables a predicate expression may reference.
var schemaBuilder = CelContextSchema.CreateBuilder("assembly-predicate-v1");
var source = schemaBuilder.AddVariable("source", CelType.ObjectOf("assembly"));
var target = schemaBuilder.AddVariable("target", CelType.ObjectOf("assembly"));
var schema = schemaBuilder.Build();

// 2. Declare the shape of any object types referenced above, so member access
//    (e.g. `source.role`) type-checks without CLR reflection.
var assemblySchemaBuilder = CelObjectSchema.CreateBuilder("assembly");
assemblySchemaBuilder.AddMember("role", CelType.String);
assemblySchemaBuilder.AddMember("namespace", CelType.String);
var assemblySchema = assemblySchemaBuilder.Build();

// 3. Build an immutable environment (compile-once, evaluate-many).
var environment = CelEnvironment.CreateBuilder(CelProfile.V1)
    .WithContextSchema(schema)
    .WithObjectSchema(assemblySchema)
    .Build();

// 4. Compile an expression. Invalid user input produces structured diagnostics —
//    CelEnvironment never throws on malformed or unsupported CEL syntax.
var compilation = environment.CompilePredicate(
    "source.role == 'service' && target.namespace.startsWith('Example.')");

if (!compilation.IsSuccess)
{
    foreach (var diagnostic in compilation.Diagnostics)
    {
        Console.WriteLine($"{diagnostic.Code}: {diagnostic.Message}");
    }

    return;
}

// 5. Build an evaluation context using the typed handles from step 1 — no string-keyed lookups.
var context = environment.CreateEvaluationContextBuilder()
    .Set(source, CelValue.Object(new CelObjectValue("assembly", new Dictionary<string, CelValue>
    {
        ["role"] = CelValue.String("service"),
        ["namespace"] = CelValue.String("Example.Services"),
    })))
    .Set(target, CelValue.Object(new CelObjectValue("assembly", new Dictionary<string, CelValue>
    {
        ["role"] = CelValue.String("domain"),
        ["namespace"] = CelValue.String("Example.Domain"),
    })))
    .Build();

// 6. Evaluate. The compiled predicate is immutable and thread-safe — evaluate it
//    concurrently against many contexts without recompiling.
var result = compilation.Program!.Evaluate(context);
Console.WriteLine(result.IsSuccess ? result.Value : result.Diagnostics[0].Message);

Compilation and evaluation lifecycle

  1. Compile once — CelEnvironment.CompilePredicate(...) / .Compile(...) parses, type-checks, and binds an expression against the environment's schema, returning a CelCompilationResult<T> with either a compiled program (CelCompiledPredicate / CelCompiledExpression) or structured CelDiagnostics. No exceptions are thrown for invalid user expressions.
  2. Evaluate many — a compiled program is immutable and thread-safe. Call .Evaluate(context) (or .Evaluate(context, limits) for evaluation-time budget overrides) as many times as needed against different CelEvaluationContext instances built from the same schema.
  3. Cache identity — CelCompilationResult<T>.CompilationKey is a deterministic, structurally comparable identity (source, profile, schema, result type, and both limit identities) usable to verify two compiled results are semantically equivalent. It cannot be constructed before a compile call — callers wanting a pre-compile "have I already compiled this?" cache should key by the raw expression source text instead, scoped to one compilation kind.

Limits, diagnostics, and thread-safety

  • Every compilation and evaluation is bounded: CelCompilationLimits and CelEvaluationLimits (with SafeDefaults) enforce maximum expression length, token/AST node/identifier counts, nesting depth, iteration count, and cost units. There is no unbounded evaluation path.
  • Failures — both compile-time (syntax errors, unsupported Profile v1 features, unresolved identifiers/members, type mismatches) and evaluation-time (missing keys, invalid indices, budget exceeded, schema mismatch) — are reported as structured CelDiagnostics with stable CelDiagnosticCodes and source spans, never as CLR exceptions from valid API usage.
  • CelEnvironment, compiled programs, and all public value/type/schema types are immutable after Build(). Concurrent evaluation of one compiled program from multiple threads is safe.

Non-goals (Profile v1)

Profile v1 is intentionally closed. It does not support: arithmetic operators, conditional (? :) expressions, uint/bytes/timestamp/duration literals, list/map/message literals, macros or comprehensions (all, exists, map, filter), regular expressions (matches), protobuf or other schema-backed message types, user-registered functions, arbitrary CLR object binding or reflection, or a public AST. These are tracked extension directions, not accidental omissions — see the repository's internal architecture blueprint for the governed path each would take if approved.

ArchLinterNet.CEL does not implement full CEL conformance and does not aim to.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on ArchLinterNet.CEL:

Package Downloads
ArchLinterNet.Core

YAML-first architecture contract engine for .NET projects. Loads declarative architecture policies, resolves assemblies, and validates dependency and Unity asmdef rules.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.9.1 0 9/28/2026
0.9.0 0 9/28/2026
0.9.0-preview.1 242 9/22/2026
0.8.2 249 9/19/2026
0.8.1 103 9/19/2026
0.8.0 447 9/5/2026
0.7.4 120 8/28/2026
0.7.3 115 8/27/2026
0.7.2 109 8/27/2026
0.7.1 123 8/26/2026
0.7.0 198 8/23/2026
0.6.5 126 8/15/2026
0.6.4 170 8/13/2026
0.6.3 122 8/12/2026
0.6.2 120 8/12/2026
0.6.1 119 8/10/2026
0.6.0 152 8/6/2026
0.5.0 140 7/19/2026

See GitHub release notes for v0.9.1. Private Relay is experimental / opt-in. Its full hosted/lifecycle acceptance is pending. Stable core governance plus private reports and public github-raw snapshots remain independent of Relay. Private default: none. There is no automatic cloud setup or badge egress. Adopter-owned infrastructure and explicit disclosure consent are required. Experimental is not a waiver for known security or privacy or integrity or data-corruption or false-PASS defects.