ForgeTrust.AppSurface.Durable.Provider 0.2.0-preview.6

This is a prerelease version of ForgeTrust.AppSurface.Durable.Provider.
dotnet add package ForgeTrust.AppSurface.Durable.Provider --version 0.2.0-preview.6
                    
NuGet\Install-Package ForgeTrust.AppSurface.Durable.Provider -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.Provider" 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.Provider" Version="0.2.0-preview.6" />
                    
Directory.Packages.props
<PackageReference Include="ForgeTrust.AppSurface.Durable.Provider" />
                    
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.Provider --version 0.2.0-preview.6
                    
#r "nuget: ForgeTrust.AppSurface.Durable.Provider, 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.Provider@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.Provider&version=0.2.0-preview.6&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=ForgeTrust.AppSurface.Durable.Provider&version=0.2.0-preview.6&prerelease
                    
Install as a Cake Tool

ForgeTrust.AppSurface.Durable.Provider

Public preview: the PostgreSQL provider supplies the current conformance path. This package contains SPI contracts, not a runtime.

ForgeTrust.AppSurface.Durable.Provider is the runtime-provider and operator SPI for ForgeTrust.AppSurface.Durable. It depends on that adopter package; the adopter package never depends on Provider. Production providers implement this public SPI without friend access.

Choose this package when

  • implementing a storage/runtime provider;
  • hosting a bounded provider pump explicitly;
  • exposing application-authorized health, drain, recovery, or operator operations; or
  • adapting a provider claim to an adopter-registered Work executor.

Ordinary applications and reusable modules should reference only ForgeTrust.AppSurface.Durable. This package does not provide PostgreSQL storage, migrations, polling, schedule execution, hosted services, endpoints, metrics, or tracing.

Slice 7 discovery boundary

This SPI remains a public preview. Provider contracts describe activation and operator boundaries, but storage registration is passive and does not imply worker hosting. The PostgreSQL provider requires an explicit AddWorkerHost() opt-in for continuous processing.

An opted-in host validates schema compatibility and the active runtime epoch during startup, then fails closed when they are incompatible. Startup never applies DDL or rewrites migration history. The ordered schema and reconciliation flow is documented in the Slice 7 Durable guide.

Activation and broker evolution

IDurableRuntimePump is the common bounded activation primitive for a continuously hosted loop, scheduled job, function, HTTP wake-up, or broker notification. A wake-up is advisory: implementations must recover eligible work from their authoritative state even when notifications are lost, duplicated, delayed, or reordered.

Do not translate broker receipt into a claim, effect permit, or terminal fact. A wake-only adapter must call the pump without carrying application payloads. A future targeted-dispatch or broker-native provider must revalidate its opaque reference against authoritative scope, revision, lease, runtime-epoch, and provider-effect state before invoking work. Slice 2 leaves that adapter shape open until a concrete broker topology proves the required routing and acknowledgement contract.

Public API by audience

Every public type in this package belongs to one of these provider-facing families. The member-level API snapshot is the canonical inventory.

Audience Public types Contract role
Runtime implementers DurableRuntimeSurface, DurableRuntimePumpRequest, DurableRuntimePumpResult, IDurableRuntimePump Run one bounded, externally activated pass
Health and host implementers DurableRuntimeHealthState, DurableRuntimeHealthSnapshot, IDurableRuntimeHealth, IDurableRuntimeDrainControl Report low-cardinality health and coordinate graceful drain
Work-store implementers DurableClaimedWork, DurablePreparedWorkInvocation, DurableProviderWorkAdapter Validate a claim, derive immutable execution identity, and invoke the adopter registry
Application-authorized control implementers Work get/cancel/list/snapshot types and IDurableWorkControlClient; scope disable types and IDurableScopeControlClient Expose bounded, scoped, payload-free operational control
Application-authorized operator implementers Operator outcome/resolution/result/request types and IDurableWorkOperatorClient Reconcile, resolve, safely retry, or recovery-release suspended Work
Application-authorized retention implementers IDurableFlowRetentionClient, bounded assessment/manifest/package/receipt/hold/purge types Prove one exact terminal Flow source set before a separately authorized purge
Flow-repair operator implementers IFlowRepairOperatorClient, repair request/evidence/assessment/result/receipt types Inspect and repair only the two evidence-backed child-effect assertions

The SPI accepts and returns public Durable identifiers and command fingerprints. Collection results defensively copy inputs, default identifiers are rejected, timestamps normalize to UTC, page sizes are bounded, and every mutation uses revision/generation fencing. Provider worker ids, terminal/problem codes, and registered Work names and versions use the Durable package's canonical identifier alphabet and bounds.

Provider work adaptation

A provider constructs DurableClaimedWork only after it owns a validated claim. Prepare maps that claim to the adopter-facing DurableWorkExecutionContext and resolves the registered executor. The resulting DurablePreparedWorkInvocation owns encoded input and exposes only the public invocation boundary.

The execution identity transition is enforceable: create the first identity from an activity id and current fences, then call Advance for a later attempt/lease/scope/runtime epoch. The provider key remains exactly the activity id so lease turnover cannot create a new external idempotency identity.

Command fingerprints

Work reconcile, manual resolution, safe retry, and recovery release each use a distinct v1 fingerprint schema. A provider persists the schema id and digest with command outcome truth. A repeated command id with UnsupportedSchema or Conflict fails closed; it must never repeat reconciliation merely because the command id matches.

Flow repair operator preview

IFlowRepairOperatorClient is a separate application-authorized boundary for an ASDUR211 child-effect suspension. It intentionally exposes only AssertChildEffectCompleted and AssertChildEffectNotApplied. The first binds a retained terminal Work result; the second binds a named completed manual-resolution command whose persisted resolution_kind is proven_not_applied. Neither action can release an arbitrary suspension, mutate the child Work, invoke an executor, or force terminate an ambiguous effect.

Call GetAssessmentAsync with a trusted scope and Flow id to obtain an advisory, payload-free candidate. The assessment can go stale; submit the selected action through a fresh revision- and descriptor-digest-fenced request. RepairAsync returns an immutable receipt only for Applied and Duplicate; Refused, RaceLost, and Conflict carry no receipt. The receipt digest binds the request schema/digest, descriptor, action-specific Work history fact, audit actor/reason, transition states, and accepted timestamp. It is integrity evidence, not a signature or a claim that ActorId authorized the caller.

Do not call IDurableFlowClient.ReleaseSuspensionAsync as a fallback for this descriptor. The PostgreSQL provider rejects that broad lifecycle command with ASDUR211; follow the normative Flow repair protocol instead.

Verified Flow retention

IDurableFlowRetentionClient is an evidence boundary, not a cleanup scheduler. An application first assesses exactly one Flow and receives Safe, Blocked, or Indeterminate with a typed reason. Only a still-matching safe assessment can create an immutable manifest. The provider then builds a reproducible DFA1 package, records an adopter-supplied archive receipt, verifies source correspondence, permits an application-owned hold, and accepts a separate compare-and-swap purge command.

Canonical retention API reference

Operation Request type Result payload Required state Next sequence
AssessAsync DurableRetentionAssessmentRequest DurableRetentionAssessment Terminal Flow N/A
CreateManifestAsync DurableRetentionManifestCreateRequest DurableRetentionManifestCreateResult Safe assessment 1 (Frozen)
BuildArchivePackageAsync (scopeId, manifestId) DurableArchivePackageV1 Any active manifest Unchanged
RecordArchiveReceiptAsync DurableRetentionRecordArchiveReceiptRequest DurableRetentionMutationResult Frozen, sequence 1 2 (ArchiveReceiptRecorded)
VerifyArchiveAsync DurableRetentionVerifyArchiveRequest DurableRetentionMutationResult ArchiveReceiptRecorded, sequence 2 3 (Verified)
SetHoldAsync DurableRetentionHoldRequest DurableRetentionMutationResult Verified or Held Next monotonic sequence
PurgeAsync DurableRetentionPurgeRequest DurableRetentionMutationResult Verified, no active hold Next monotonic sequence (Purged)

Lifecycle state sequence and boundaries

The retention lifecycle uses monotonic sequence checks to prevent out-of-order or duplicate execution:

  1. Assessment & Manifest: AssessAsync evaluates one Flow against boundary limits (maximum 10,000 closure items and 64 MiB package bytes). Non-safe outcomes (Blocked due to active child Work, nonterminal state, or repair required; Indeterminate due to unknown state) forbid manifest creation. CreateManifestAsync freezes source hashes and initializes LifecycleSequence = 1 in Frozen state.
  2. Archive & Receipt: BuildArchivePackageAsync constructs the canonical DFA1 archive byte array. The adopter writes the archive package to external storage and calls RecordArchiveReceiptAsync with sequence 1.
  3. Verification: VerifyArchiveAsync validates source SHA-256 correspondence against the frozen manifest, advances state to Verified, and increments LifecycleSequence to 3.
  4. Hold & Purge: SetHoldAsync can place or release a legal hold (PlaceHold = true/false) and increments the sequence for every applied transition. PurgeAsync requires state Verified, no active hold, and the current sequence. It transitions state to Purged, clears terminal payloads, and deletes manifest-covered history rows.

Common failures and pitfalls

  • ASDUR102 (Command Conflict): Reusing a command identity with different request parameters fails closed.
  • ASDUR214 (Manifest Not Found): Specified manifest ID does not exist in the authorized scope.
  • ASDUR215 (Source Changed): Live Flow source items changed after assessment or manifest creation. Caller must create a new assessment and manifest.
  • ASDUR216 (Sequence Conflict): Expected lifecycle sequence is stale. Reload manifest state before retrying.
  • ASDUR217 (Lifecycle Rejected): Operation attempted out of order (e.g. purging before verification or while a legal hold is active).

The application must authorize every call and owns archive transport, encryption, retention duration, availability, and legal/compliance requirements. Receipt verification proves the package corresponds to the frozen PostgreSQL source; it does not prove external bytes are present or adequate. No API accepts an archive URI, raw SQL, age-range deletion, continuation token, or multi-Flow manifest. See the PostgreSQL retention deployment guidance.

Operational prerequisites

Before a provider is included in a coordinated prerelease, release review must verify storage and migration ownership, polling/schedule execution, restore fencing, graceful drain, privacy-bounded diagnostics and telemetry, packed-consumer proof, verified-retention evidence when the retention SPI is implemented, and conformance tests against this SPI. The PostgreSQL provider supplies Work, Flow, Schedule, hosted activation, drain/recovery, retention, and repair conformance; the review checklist remains the prerelease publication gate.

See the ASDURxxx diagnostics catalog for currently available contract, PostgreSQL Work, and hosted-runtime codes.

From the repository root, ./Durable/verify-packed-consumers.sh packs the three public-preview packages and their local dependencies, then compiles and runs isolated adopter and provider consumers against only those packages.

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 (1)

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

Package Downloads
ForgeTrust.AppSurface.Durable.PostgreSql

ForgeTrust.AppSurface.Durable.PostgreSql 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 123 8/12/2026