ForgeTrust.AppSurface.Durable.Provider
Source of truth
Source-only public preview: the
PostgreSQL source providersupplies the current source-preview conformance path, but publication remains held pending coordinated release evidence. 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 part of the source-only public preview; publication is held pending coordinated release evidence.
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 |
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.
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:
- Assessment & Manifest:
AssessAsyncevaluates one Flow against boundary limits (maximum 10,000 closure items and 64 MiB package bytes). Non-safe outcomes (Blockeddue to active child Work, nonterminal state, or repair required;Indeterminatedue to unknown state) forbid manifest creation.CreateManifestAsyncfreezes source hashes and initializesLifecycleSequence = 1inFrozenstate. - Archive & Receipt:
BuildArchivePackageAsyncconstructs the canonicalDFA1archive byte array. The adopter writes the archive package to external storage and callsRecordArchiveReceiptAsyncwith sequence 1. - Verification:
VerifyArchiveAsyncvalidates source SHA-256 correspondence against the frozen manifest, advances state toVerified, and incrementsLifecycleSequenceto 3. - Hold & Purge:
SetHoldAsynccan place or release a legal hold (PlaceHold = true/false) and increments the sequence for every applied transition.PurgeAsyncrequires stateVerified, no active hold, and the current sequence. It transitions state toPurged, 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 any provider can be published, it must supply 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 source-preview PostgreSQL provider now supplies Work, Flow, Schedule, hosted activation, drain/recovery, and verified-retention conformance; coordinated release evidence remains the 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 both held packages and their local dependencies,
then compiles and runs isolated adopter and provider consumers against only those packages.
Release Guidance
This package has an explicitly experimental or publication-held contract. Do not treat it as a normal prerelease install; use the package chooser and release hub for the current publication decision, proof requirements, and migration guidance.