ForgeTrust.AppSurface.Durable 0.2.0-preview.6

This is a prerelease version of ForgeTrust.AppSurface.Durable.
dotnet add package ForgeTrust.AppSurface.Durable --version 0.2.0-preview.6
                    
NuGet\Install-Package ForgeTrust.AppSurface.Durable -Version 0.2.0-preview.6
                    
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="ForgeTrust.AppSurface.Durable" Version="0.2.0-preview.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ForgeTrust.AppSurface.Durable" Version="0.2.0-preview.6" />
                    
Directory.Packages.props
<PackageReference Include="ForgeTrust.AppSurface.Durable" />
                    
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 ForgeTrust.AppSurface.Durable --version 0.2.0-preview.6
                    
#r "nuget: ForgeTrust.AppSurface.Durable, 0.2.0-preview.6"
                    
#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 ForgeTrust.AppSurface.Durable@0.2.0-preview.6
                    
#: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=ForgeTrust.AppSurface.Durable&version=0.2.0-preview.6&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=ForgeTrust.AppSurface.Durable&version=0.2.0-preview.6&prerelease
                    
Install as a Cake Tool

ForgeTrust.AppSurface.Durable

Public preview: the PostgreSQL provider supplies the current conformance path. This package installs no runtime and starts no hosted service.

ForgeTrust.AppSurface.Durable is the adopter-facing contract package for durable Work, resumable AppSurface Flow, schedules, serialization, registration, and clients. Runtime-provider and operator APIs live in ForgeTrust.AppSurface.Durable.Provider.

Choose this package when

  • a reusable module needs to describe durable work without choosing storage;
  • a typed Flow must resume at explicit, persisted transition boundaries;
  • a host needs At, After, Every, or Cron schedule intent; or
  • an application needs stable command fingerprints for retry/conflict comparison.

Do not choose it for arbitrary replayable code, exactly-once external effects, child workflows, unbounded fan-out, a message bus, storage, or worker hosting.

Passive registration proof

AppSurfaceDurableModule registers only payload, Work, and Flow registries. This complete source consumer verifies that registration resolves those registries and leaves IHostedService empty:

using ForgeTrust.AppSurface.Core;
using ForgeTrust.AppSurface.Durable;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace ForgeTrust.AppSurface.Durable.Examples;

internal static class PassiveRegistrationProof
{
    internal static void Run()
    {
        var services = new ServiceCollection();
        new AppSurfaceDurableModule().ConfigureServices(
            new StartupContext([], new PassiveHostModule()),
            services);

        using var provider = services.BuildServiceProvider();
        _ = provider.GetRequiredService<IDurablePayloadCodecRegistry>();
        _ = provider.GetRequiredService<IDurableWorkRegistry>();
        _ = provider.GetRequiredService<IDurableFlowRegistry>();
        if (provider.GetService<IDurableWorkClient>() is not null
            || provider.GetService<IDurableFlowClient>() is not null
            || provider.GetService<IDurableScheduleClient>() is not null
            || provider.GetServices<IHostedService>().Any())
        {
            throw new InvalidOperationException("Durable contract registration must remain passive.");
        }

        Console.WriteLine("contracts registered; no runtime installed");
    }

    private sealed class PassiveHostModule : IAppSurfaceHostModule
    {
        public void ConfigureHostBeforeServices(StartupContext context, IHostBuilder builder)
        {
        }

        public void ConfigureHostAfterServices(StartupContext context, IHostBuilder builder)
        {
        }

        public void ConfigureServices(StartupContext context, IServiceCollection services)
        {
        }

        public void RegisterDependentModules(ModuleDependencyBuilder builder)
        {
        }
    }
}

From the repository root, the compile-and-run proof is one command:

dotnet test Durable/ForgeTrust.AppSurface.Durable.Tests/ForgeTrust.AppSurface.Durable.Tests.csproj \
  --filter PassiveRegistrationProof --artifacts-path /tmp/appsurface-durable-passive

Expected result: the named proof passes; no runtime, network call, DDL, poller, or hosted service starts. The proof emits contracts registered; no runtime installed.

Slice 7 discovery boundary

This package is a public preview. Registration is intentionally passive: it installs contract registries, not storage operations or worker hosting. PostgreSQL storage registration remains passive as well; continuous processing requires the explicit AddWorkerHost() opt-in.

When a host starts the opted-in worker, startup validates schema compatibility and the active runtime epoch. It fails closed when those values are incompatible and never applies DDL or advances migration history. See the Slice 7 discovery and reconciliation guide for the ordered 00010008 migration flow, canonical role recipe, preferred preflight sequence, recovery posture, and the implemented durable schema CLI commands.

Public API by audience

Every public type in this package belongs to one of these adopter-facing families. The member-level API snapshot is the canonical inventory; public types added to the corresponding source families inherit the audience and compatibility policy shown here.

Audience Public types Contract role
All adopters DurableScopeId, DurableWorkId, DurableCommandId, DurableProblem, DurableOperationResult<T>, DurableProblemCodes Opaque identity and safe diagnostics
Serialization authors DurableDataClassification, DurableEncodedPayload, IDurablePayloadCodec, IDurablePayloadCodec<T>, SystemTextJsonDurablePayloadCodec<T>, registry types Explicit, versioned, policy-approved payload bytes
Work authors DurableProviderSafety, retry/state/request/acceptance types, IDurableWorkClient, execution/prepared-work/registration/registry types, DurableServiceCollectionExtensions Declare, enqueue, and execute typed Work through a provider adapter
Flow authors Flow identifiers, state/request/result/snapshot/client types; evaluation, activity, event, registration, registry, and determinism-verifier types Persist one explicit Flow transition at a time
Schedule authors Schedule shapes/policies/targets, schedule request/result/snapshot/list/explain types, IDurableScheduleClient, DurableScheduleProblemCodes Author and inspect versioned schedule intent
Retry-aware clients and providers DurableCommandFingerprint, DurableCommandFingerprintMatch Compare canonical semantic command bytes without treating unknown schemas as equal
Effect-reconciliation authors DurableEffectReconciliationKind, reconciliation result types, IDurableEffectReconciler<TWork,TResult> Declare side-effect-free reconciliation for ambiguous provider outcomes
Composition roots AppSurfaceDurableModule Register passive contract registries only

The application surface intentionally excludes runtime pump, claim, health, drain, scope-control, and Work operator types. Those are Provider SPI.

Command fingerprints

Every command-bearing mutation exposes a computed DurableCommandFingerprint with a versioned schema id and SHA-256 digest. Fingerprints cover Work enqueue; Flow start, event, cancel, and recovery release; schedule create, update, pause, resume, delete, and recovery release. Provider operator commands have their own schemas in the Provider package.

Use Compare before treating a repeated command identity as equivalent. Exact means the schema and digest agree; Conflict means the known schema agrees but semantic bytes differ; UnsupportedSchema means the caller must not guess. Never persist a caller-supplied digest as authoritative.

Schedule targets are encoded by their registered codec when the target is constructed. Mutating the caller's input object afterward cannot change the fingerprint or the bytes a provider receives.

Identifiers, results, and limits

All request and result constructors reject default opaque identifiers at the public boundary. Collection-bearing results defensively copy caller collections. DurableWorkerExecutionIdentity can only be created through validated factories and advanced through its monotonic transition API; its provider key is the immutable activity id.

Durable identifier alphabet and bounds

Fields documented as durable identifiers accept only ASCII letters (A-Z, a-z), digits (0-9), hyphens (-), underscores (_), periods (.), and colons (:). They reject null, empty, or whitespace-only values, control characters, and every other character. The shared rule keeps persisted identity values ordinal, privacy-safe, and portable across providers.

Work and Flow names and other registered names are limited to 200 characters; immutable Work and Flow versions and other registered versions are limited to 100 characters. Provider health and inventory contracts apply the same alphabet with a 200-character worker-id limit and 120-character terminal/problem-code limit. These rules apply only to fields documented as durable identifiers. Human-readable labels, Cron expressions, time-zone ids, and encoded payloads have their own validation rules and must not be inferred from this alphabet.

Cron expression text is limited to 512 characters and the IANA time-zone id to 128 characters. These are contract limits, not proof that a string is valid Cronos grammar or a known time zone; a provider performs grammar and zone validation before persistence.

Preview compatibility

Change Preview policy
Additive request/result member Allowed only with a documented default and fingerprint review
Mutation semantics or canonical bytes Before either independent boundary—the first supported publication or any persisted deployment—v1 may be corrected in place with updated test vectors; after either, requires a new fingerprint schema id
Payload bytes Requires a new application contract version
Flow executable behavior Requires a new implementation version or explicit migration
Schedule dialect semantics Requires a new dialect/version, never reinterpret persisted occurrences
Provider SPI behavior Requires provider conformance evidence before adoption

Diagnostics available now cover contract validation, semantic conflicts, and PostgreSQL Work storage, schema, activation, and restore failures. Heartbeat, drain, and hosted-runtime diagnostics are provider-owned. See the ASDURxxx catalog.

Release Guidance

AppSurface ships as a coordinated package family. Before installing this package from a prerelease feed, check the package chooser and release hub for current release risk, migration guidance, and readiness.

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.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on ForgeTrust.AppSurface.Durable:

Package Downloads
ForgeTrust.AppSurface.Durable.PostgreSql

ForgeTrust.AppSurface.Durable.PostgreSql package for AppSurface application composition.

ForgeTrust.AppSurface.Durable.Provider

ForgeTrust.AppSurface.Durable.Provider package for AppSurface application composition.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.0-preview.6 125 8/12/2026