Skip to main content

Release v0.0.60

Β· 8 min read
vNext Team
Burgan Tech Engineering

Overview​

This release lands two long-tracked capabilities and hardens the transition pipeline. Sandboxed, component-referenced custom C# script helpers let consuming teams ship their own helper classes as .csx components and reference them from a mapping's scripts.helpers, compiled and run under a two-layer sandbox (#710). State aliases expose role-scoped, multi-language state labels without touching the internal state identity (#648). The transition pipeline gains configurable async execution modes β€” continuation enqueueing, transition atomicity, chain-ownership gating, and a chain reaper for stuck instances (#725). FunctionScope is now enforced consistently on every function-invocation entry point (#709). A correctness fix removes EF compiled queries (broken under PGBouncer + multi-schema) and makes the duplicate-key check deterministic (#715), and an operations hardening pass disables production Swagger and promotes function/mapping failures to Error-level logging (#724). This bump also advances the component schema to 0.0.46.


Features​

Sandboxed, component-referenced custom C# script helpers (#710)​

Consuming developers can now ship their own C# helper classes as components β€” uploaded as .csx, just like flows, tasks, and views β€” reference them from a transition mapping, and have the runtime build the helper classes first, then compile and run the mapping against them. Helpers are sandboxed and cached by content hash.

  • Delivery: a helper is a component (.csx), source-compiled at runtime (not a precompiled DLL) β€” the only delivery the runtime can sandbox, since it owns the Roslyn compile.
  • Wiring: referenced from the mapping's scripts block via scripts.helpers[]. Explicit, per-flow, no global state. ScriptBase stays runtime-owned.
  • Sandbox grants: scripts.allowedAssemblies[] makes the reference allow-list dynamic per-mapping β€” merged on top of the global baseline (Scripting:Sandbox:AllowedAssemblies), so a flow grants only the assemblies its helpers need without widening the baseline for everyone.
  • Trust: restricted/sandboxed (best-effort) via a two-layer compile-time gate β€” reference allow-list plus a banned-API analyzer β€” compiled into a shared collectible AssemblyLoadContext.
// transition mapping β€” scripts block
"scripts": {
"helpers": [ // helper component references
{ "key": "rsa-crypto", "version": "1.0.0", "domain": "core", "flow": "sys-mappings" }
],
"allowedAssemblies": [ "System.Security.Cryptography" ] // per-mapping sandbox grant
}

Migration guide: for a detailed Turkish walkthrough of every v0.0.60 feature and its migration steps, see vNext v0.0.60 Migration Rehberi.

Reference: issue #710 β€” see also Mappings and the Mapping component.

State aliases with role-based visibility (#648)​

The same internal state can now be presented differently depending on the user's role, while the underlying workflow logic continues to use the real state identity. An applicant's case may internally sit in one of several detailed evaluation states, while the customer sees a single simplified alias such as "Application Under Review".

A state may declare an optional alias[] array, where each stateAlias carries:

FieldTypeRequiredDescription
namestringyesAlias name.
rolesroleGrant[]yesRoles for which this alias applies. DENY overrides ALLOW.
labelslanguageLabel[]yesMulti-language labels shown to matching users.

Multiple internal states can map to the same external alias, and alias resolution is layered on top of the existing role model (so DENY grants still win). Internal workflow logic, transitions, and persistence are unaffected β€” aliases only shape the presentation layer of query/response rendering.

Reference: issue #648 β€” see also Workflow component and Authorization.

Configurable async transition execution modes (#725)​

The transition pipeline gains configurable async execution, controlled by four runtime flags:

  • Continuation enqueueing β€” continuations can be enqueued (optionally via the outbox) for improved durability instead of running inline.
  • Transition atomicity β€” controls whether a transition and its continuation commit as one unit.
  • Chain ownership gating β€” a chain ownership token system provides fine-grained control over access to instances in the Busy state, preventing concurrent chains from stepping on each other.
  • Stuck-instance recovery β€” a new chain reaper service automatically resolves instances whose heartbeats have gone stale, releasing ownership so they can resume.

The change ships with EF Core migrations for the durability refactor schema changes, plus architecture documentation covering the execution modes and operational guidance.

Reference: PR #725 β€” see also Sync vs Async execution.

Consistent FunctionScope enforcement on invocation (#709)​

FunctionScope is now enforced uniformly across both function-invocation entry points (GetFunctionByKeyAsync and GetFunctionByInstanceAsync), which both funnel through ExecuteFunctionAsync:

ScopeRule
DomainAlways runs β€” exempt from every scope restriction.
InstanceOnly runs when an instance exists.
Flow (TaskScope.Flow, "F")Requires an instance and the function to be declared in that instance's flow (workflow.Functions).

Previously the guard only checked Flow membership, and only when an instance was present β€” so Instance/Flow-scoped functions could be invoked through the domain-level endpoint with no restriction, and scope failures leaked out as incidental 404s. Scope violations now return a deliberate 403 Forbidden (FunctionScopeNotSatisfied, Function:800002).

Reference: PR #709, closes #637 β€” see also Functions.


Fixes​

Remove EF compiled queries + deterministic duplicate-key check (#715)​

Two related defects in the EF instance repository layer:

  1. EF compiled queries break under PGBouncer + multi-schema. EF.CompileAsyncQuery caches the query plan β€” including the resolved schema β€” on a static readonly delegate shared across all requests. With per-request schema resolution (ICurrentSchema) and PGBouncer transaction pooling, the cached delegate could bind to the wrong schema / stale connection state. EF Core already caches non-compiled query plans transparently, so the compiled queries provided no benefit while causing correctness bugs β€” they are now removed.
  2. Non-deterministic duplicate-key check. CheckExistingInstanceAsync looked up an existing instance with no status filter and no ordering, so when multiple rows shared a key (terminal history plus a live one) Postgres could return an arbitrary row β€” occasionally allowing a second active instance with the same key. The check is now deterministic: a key is considered "in use" only by non-terminal (Active/Busy) instances, guaranteeing at most one live instance per key.

Reference: issue #715


Operations & Observability​

Disable production Swagger + harden function/mapping logging (#724)​

  • Swagger off in production. UseAetherApiVersioning now passes useSwagger/useSwaggerUi as !IsProduction() across the four pipelines (Orchestration, Execution, InboxWorker, OutboxWorker), so the public production surface no longer exposes the API explorer. The administrative PublishAsync endpoint is hidden from the API Explorer via [ApiExplorerSettings(IgnoreApi = true)].
  • Failures are visible. FunctionAppService.ExecuteFunctionAsync now catches task-coordinator exceptions and logs execution and output/script-mapping failures at Error level (returning a clear failure Result when mapping throws). Task business-failure logs in TaskExecutionEngine were promoted from Debug to Error.
  • No more NREs in executor logs. Direct context.ScriptContext.Instance.Id usage was replaced with Instance?.Id ?? Guid.Empty across the script / Dapr / HTTP / trigger executors, so custom functions running without an instance context no longer throw NullReferenceException while logging.

Reference: PR #724


Configuration Updates​

Configuration for v0.0.60:

{
"runtimeVersion": "0.0.60",
"schemaVersion": "0.0.46"
}

Note: Schema version advances to 0.0.46 (from 0.0.43). The bump adds scripts.helpers[] / scripts.allowedAssemblies[] on transition mappings (#710) and the alias[] / stateAlias definition on states (#648). Update @burgan-tech/vnext-schema in your domain project before validating against this runtime.

Container images: published at tag 0.0.60 under ghcr.io/burgan-tech/vnext/* (execution, orchestrator, init, inbox, outbox, db-migrator), Cosign-signed (keyless OIDC) with SBOM + provenance. Immutable digests are listed in the GitHub release.


Issues Referenced​

  • vnext #710 β€” Sandboxed, component-referenced custom C# script helpers.
  • vnext #648 β€” State alias support with role-based visibility.
  • vnext #725 β€” Configurable async transition execution modes (continuation, atomicity, chain ownership, chain reaper).
  • vnext #709 β€” Enforce FunctionScope on function invocation (closes #637).
  • vnext #715 β€” Remove EF compiled queries; deterministic instance-key check.
  • vnext #724 β€” Disable production Swagger; harden function/mapping error logging.

Summary​

  • Custom C# helpers ship as .csx components, referenced via scripts.helpers[] and sandboxed per-mapping with scripts.allowedAssemblies[].
  • State aliases expose role-scoped, multi-language state labels (DENY overrides ALLOW) without changing internal state identity.
  • Async transition modes add continuation enqueueing (outbox-capable), transition atomicity, chain-ownership tokens, and a chain reaper for stuck instances.
  • FunctionScope is enforced on every invocation path; violations now return 403 instead of incidental 404s.
  • Fix: EF compiled queries removed (PGBouncer + multi-schema safe); duplicate-key check is deterministic (one live instance per key).
  • Ops: production Swagger disabled; function/mapping failures logged at Error; executor-log NREs eliminated.
  • Schema advances to 0.0.46.

vNext Runtime Platform Team
Released June 13, 2026