Release v0.0.91
Overview​
This release gives cross-domain calls a second transport. ServiceDiscovery:Provider switches between http and dapr: under dapr, address resolution moves from the discovery registry's per-call HTTP lookup to Dapr Name Resolution, and the Remote* app services gain a Dapr service-invocation transport, with the registry kept for registration and health (#964). The default stays http and is byte-for-byte the previous behaviour, so enabling dapr is an environment setting rather than an upgrade step. Inline auto-chain hops reuse the context they already hold, and subflow starts and forwards execute synchronously for more predictable completion (#968). Post-commit settlement gets a named parent span so the fresh-parent settle stops rendering as loose siblings, and runtime-internal child start/forward calls skip a response enrichment whose result is thrown away — the reload, schema filter, script context and extensions were all being built for a caller that reads only IsSuccess and Status (#969). A further round of trace refinements tightens span naming, job-handler activity creation and event trace parenting (#963). This release runs on component schema 0.0.53.
Features​
Cross-domain calls over Dapr name resolution and service invocation (#964)​
Under ServiceDiscovery:Provider = http, every cross-domain hop paid a registry GET to learn the target's address. GetEndpointAsync is called from roughly 35 sites — the trigger task executors and the whole Remote* family, with RemoteInstanceCommandAppService alone accounting for twelve — so a cross-domain subflow start burned a full lookup before doing any work.
A single switch selects the transport:
{
"ServiceDiscovery": {
"Provider": "http",
"Dapr": {
"NamespaceTemplate": "",
"PreferRegistryAppId": true,
"RequireRegistryEntry": false,
"CacheSeconds": 60,
"DomainOverrides": {}
}
}
}
Provider: "dapr"derives the target app-id by convention:vnext-{domain}-app, optionally qualified asvnext-{domain}-app.{namespace}throughNamespaceTemplatefor cross-namespace calls.RequireRegistryEntrydefaults tofalse, so the hot path makes no registry call at all.DomainOverridespins one domain to an explicit app-id — or back to aurl— for a staged rollout or a targeted rollback, without moving the whole environment.- A transport shell
IRemoteTransport<TClient>routes onEndpointKind: HTTP keeps the existing pipeline unchanged, and Dapr goes overDaprClient.CreateInvokeHttpClient()(the SDK's non-obsolete surface). Every obsoleteDaprClient.InvokeMethod*call site is removed. - Sidecar
ERR_*500s are normalised toHttpRequestException, so error boundaries keep seeingremote_network_errorrather than a transport-specific shape. - Retry is split by
RemoteServiceProfile: read clients retry; mutating clients — start, subflow-forward, transitions,sub/*, busy, retry — are attempted exactly once. - New
Discovery.Resolvespan tags and log events (EventIds 50032–50035) make the resolution path visible.
Verified against a local three-domain lab on Dapr 1.18.0: 11 integration tests green with Provider=dapr, and the same 11 green after a rollback drill to Provider=http.
Requires Dapr ≥ 1.18. On daprd 1.16.x the nameformat option is unusable — the sidecar reports "couldn't find name resolver" — so a local compose stack on that line must pin the mdns resolver explicitly. Cross-namespace qualification depends on ServiceDiscovery__Dapr__NamespaceTemplate being rendered by your chart.
Reference: PR #964 — see also Service discovery configuration.
Inline auto-chain context reuse and synchronous subflow starts (#968)​
Two execution-path changes that make chained work cheaper and its completion more predictable:
- Inline continuation reuses the context it already holds.
TransitionContextFactoryandInlineContinuationStrategycarry the resolved context forward across an inline auto-chain hop instead of rebuilding it, so a chain of automatic transitions pays the construction cost once rather than once per hop. - Subflow starts and forwarded transitions execute synchronously.
SubflowStarterandForwardToSubflowJobHandlerno longer take the asynchronous route for the handoff itself, so a start or forward has completed — or failed — by the time the caller continues, rather than leaving a window in which neither the parent nor the child reflects the handoff yet.
The release also refreshes the execution-model documentation this behaviour rests on, including new architecture notes on inline chain context reuse and subflow execution.
Reference: PR #968 — see also Async and sync execution.
Post-commit settlement spans and skipped response enrichment (#969)​
Two phases of a transition hop rendered as loose siblings in Elastic APM and were hard to attribute: the fresh-parent settlement after PostCommit.Coordinate, and the sync response projection that landed under SubFlow.Start / SubFlow.Forward. Both now have a named parent span.
PostCommit.Settle/PostCommit.Faultwrap the parent mutation, withLock.Acquire, the reloadDb.SELECTs,Transition.Settle,Uow.CommitandLock.Releaseas children, and an error status when the mutation fails.Instance.EnrichResponsecarriesvnext.enrich.source(pipeline|reload) andvnext.extensions.requested.
Three pieces of redundant work go with them:
- A repeated flow resolution in every post-commit scope. Both post-commit scopes now pass the definition they already hold, so the
Cache.Get/sys-flows:…under coordination and settlement disappears. - The parent's latest-data row on async settlement.
FindForPostCommitSettlementAsync(id, includeLatestData)loads open correlations always, but latest data only for a sync caller or a fault. A fault always loads it, because whether the faulted instance is a SubFlow — whose data is published upward in the fault event — is only known after the reload, and faults are the exceptional path. - Full response enrichment on runtime-internal child start/forward calls.
SuppressResponseEnrichmentis a server-only flag (the same posture asChainReserved), set bySubflowStarter,ForwardToSubflowJobHandlerand thesub/instances/startandinternal/subflow-forwardendpoints. It is never bound from a client request body, so there is no DTO or version drift — and even if a caller managed to set it, the only effect would be a thinner response for that caller. Client-visible responses are unchanged: the attributes and extensions a client receives always came from the parent's own enrichment.
Reference: PR #969 — see also Observability.
Trace refinements (#963)​
A follow-up pass over the span tree established in v0.0.87 and v0.0.90: background-job activity creation is consolidated in BackgroundJobActivityHelper and applied consistently across the flow-timeout, long-poll-ack, state-notify and transition-timer handlers; JobTimeoutRecoveryService participates in tracing; pipeline step, transition record and validation spans get more precise tags; FlatLaneActivity and ActivationActivity are simplified; and event trace parenting and EventTraceScope behaviour are pinned by additional tests. The monitoring and orchestration host telemetry configuration is updated to match.
Reference: PR #963 — see also Telemetry configuration.
Fixes​
- A cache hit on discovery resolution was invisible in traces —
HttpDomainDiscoveryProvidertagged the spanregistryafter the resolution returned, so the resolution source was always reported as the registry (#964). - Every post-commit scope re-resolved the flow definition it already held, adding a
Cache.Get/sys-flows:…per coordination and per settlement (#969). - Async post-commit settlement loaded the parent's latest data row and discarded it (#969).
- Runtime-internal child start/forward calls paid a full response enrichment — reload, schema filter, script context and extensions — for a response read only for
IsSuccessandStatus(#969).
Configuration Updates​
Configuration for v0.0.91:
{
"runtimeVersion": "0.0.91",
"schemaVersion": "0.0.53"
}
Note: Schema version is unchanged at 0.0.53.
New settings:
ServiceDiscovery:Provider—http(default, unchanged behaviour) ordapr.ServiceDiscovery:Dapr:*—NamespaceTemplate(default""),PreferRegistryAppId(true),RequireRegistryEntry(false),CacheSeconds(60),DomainOverrides({}).
Switching to dapr is an environment setting and is reversible: set Provider back to http, or pin a single domain back to a url through DomainOverrides, without redeploying. Dapr sidecar configurations gain an explicit name resolver and otel tracing block, and the internal gRPC port is fixed.
Dapr ≥ 1.18 is required for the dapr provider. nameformat is unusable on daprd 1.16.x, so a stack on that line must pin mdns explicitly.
Container images: published at tag 0.0.91 under ghcr.io/burgan-tech/vnext/*, Cosign-signed (keyless OIDC) with SBOM + provenance. Immutable digests are listed in the GitHub release.
Issues Referenced​
- vnext #964 — Resolve cross-domain calls via Dapr name resolution and service invocation.
- vnext #968 — Inline auto-chain context reuse and synchronous subflow starts and forwards.
- vnext #969 — Group post-commit settlement spans and skip discarded response enrichment.
- vnext #963 — Trace refinements across background jobs, pipeline steps and event parenting.
Summary​
ServiceDiscovery:Provider = http | dapr—daprresolvesvnext-{domain}-app[.{namespace}]by convention with no registry call on the hot path;DomainOverridespins or rolls back one domain at a time; the registry stays for registration and health.- Sidecar
ERR_*500s normalise toHttpRequestException, so error boundaries keep seeingremote_network_error; read clients retry, mutating clients are attempted exactly once. - Inline auto-chain hops reuse their context, and subflow starts and forwards execute synchronously.
PostCommit.Settle/PostCommit.FaultandInstance.EnrichResponsegive two previously loose phases a named parent; a repeated flow resolution and an unused latest-data load are removed.SuppressResponseEnrichment(server-only) skips a discarded enrichment on runtime-internal child start/forward calls; client-visible responses are unchanged.- Requires Dapr ≥ 1.18 for the
daprprovider;nameformatis unusable on 1.16.x. - Schema stays at 0.0.53; no breaking changes in this release.
vNext Runtime Platform Team Released September 7, 2026
