string FlowId { get; }
Source
Gets the stable flow identifier.
Describes a typed AppSurface Flow graph.
TContextSerializable context type carried between flow nodes.A definition is immutable after construction. Nodes are identified by stable string ids so local and durable hosts can store the current node without serializing executable code. Flow ids and versions should remain stable once durable instances have been started.
string FlowId { get; }
Source
Gets the stable flow identifier.
string Version { get; }
Source
Gets the graph version.
string StartNodeId { get; }
Source
Gets the node id where new instances start.
IReadOnlyDictionary<string, FlowNodeDescriptor<TContext>> Nodes { get; }
Source
Gets all node descriptors keyed by node id.
IReadOnlyDictionary<string, FlowExecutionNode<TContext>> ExecutionNodes { get; }
Source
Gets the internal execution view keyed by node id.
The execution view is built from the copied and validated node dictionary. It preserves the public Nodes graph view while giving runners pre-resolved next-node targets.
FlowExecutionNode<TContext> StartExecutionNode { get; }
Source
Gets the pre-resolved start node used by in-process runners.
Describes one AppSurface Flow node execution.
TContextSerializable context type carried by the flow.FlowIdStable flow id.VersionFlow graph version.NodeIdCurrent node id.StateCurrent typed state.ResumeEventOptional external event or timeout that resumed the node.The context is an immutable value-type snapshot so in-process runners can pass it to synchronous nodes without allocating a new reference object for every step. Runners always populate all members before invoking a node. Avoid using default instances as real execution contexts because value types can be default-created without the required flow, version, node, or state values.
FlowActivityWorkResult? ActivityResult { get; init; }
Source
Gets the optional typed activity result that resumed the node.
This property is null during initial execution and external-event resumption. Use the activity's FlowActivityCallsite{TWork,TResult} to validate and unwrap a result. A runner never supplies both ResumeEvent and this property for one evaluation.
Runs AppSurface Flow definitions until the next external-event wait, typed activity, or terminal outcome.
TContextSerializable context type carried by the flow.ValueTask<FlowRunResult<TContext>> RunAsync(FlowDefinition<TContext> definition, TContext initialContext, CancellationToken cancellationToken = default)
Source
Starts a new flow instance at the definition's start node.
definitionFlow definition to run.initialContextInitial context.cancellationTokenCancellation token.The result after execution pauses or ends.
ValueTask<FlowRunResult<TContext>> ResumeAsync(FlowDefinition<TContext> definition, string nodeId, TContext context, FlowResumeEvent resumeEvent, CancellationToken cancellationToken = default)
Source
Resumes a waiting node with an external event or timeout.
definitionFlow definition to run.nodeIdNode id that was waiting.contextPersisted context.resumeEventEvent that resumed the node.cancellationTokenCancellation token.The result after execution pauses or ends.
ValueTask<FlowRunResult<TContext>> ResumeActivityAsync(FlowDefinition<TContext> definition, string nodeId, TContext context, FlowActivityWorkResult activityResult, CancellationToken cancellationToken = default)
Source
Resumes a node that is waiting for one typed activity result.
definitionFlow definition to run.nodeIdNode id that requested the activity.contextContext persisted with the activity request.activityResultDecoded typed activity result.cancellationTokenCancellation token.The result after execution pauses or ends.
NotSupportedExceptionThrown by the default implementation when the runner has not implemented activity resumption.The default implementation preserves compatibility for custom v1 runners and reports that activity resumption is unsupported. Runners that surface FlowRunStatus.ActivityPending must override this method.
Result returned by a flow runner after executing until the next pause or terminal outcome.
TContextSerializable context type carried by the flow.FlowRunResult<TContext> Waiting(string nodeId, string eventName, TContext context, FlowTimeout? timeout = null)
Source
Creates a waiting result.
nodeIdNode id where the flow paused.eventNameExternal event name the node is waiting for.contextContext to preserve while the flow is waiting.timeoutOptional timeout associated with the wait.ArgumentExceptionThrown when nodeId or eventName is empty.ArgumentNullExceptionThrown when context is null.Inspect Status before reading wait-specific properties. timeout is optional and remains null for waits without a timeout.
FlowRunResult<TContext> Waiting(string nodeId, IFlowEventCallsite eventCallsite, TContext context, FlowTimeout? timeout = null)
Source
Creates a waiting result with an exact typed payload contract.
nodeIdNode id where the Flow paused.eventCallsiteExact event name and durable payload contract.contextContext to preserve while the Flow is waiting.timeoutOptional timeout associated with the wait.A waiting result that preserves immutable event metadata.
ArgumentExceptionThrown when nodeId or callsite text metadata is empty.ArgumentNullExceptionThrown when eventCallsite, its payload type, or context is null.FlowRunResult<TContext> Completed(string nodeId, TContext context)
Source
Creates a completed result.
nodeIdNode id that completed the flow.contextFinal flow context.ArgumentExceptionThrown when nodeId is empty.ArgumentNullExceptionThrown when context is null.A completed result does not carry wait, timeout, or fault details. Inspect Status before reading status-specific properties.
FlowRunResult<TContext> TimedOut(string nodeId, string eventName, TContext context)
Source
Creates a timed-out result.
nodeIdNode id that handled the timeout branch.eventNameEvent whose wait timed out.contextContext after timeout handling.ArgumentExceptionThrown when nodeId or eventName is empty.ArgumentNullExceptionThrown when context is null.A timed-out result means timeout handling ran; it is distinct from a waiting result that carries a future timeout. Inspect Status before reading timeout-specific properties.
FlowRunResult<TContext> Faulted(string nodeId, FlowFault fault)
Source
Creates a faulted result.
nodeIdNode id that produced the fault.faultFlow fault details.ArgumentExceptionThrown when nodeId is empty.ArgumentNullExceptionThrown when fault is null.Faulted results do not carry a context. Inspect Status before reading fault-specific properties.
FlowRunResult<TContext> ActivityPending(string nodeId, IFlowActivityRequest<TContext> activity)
Source
Creates a result that pauses local execution for one typed external activity.
nodeIdNode that requested the activity.activityTyped activity request and context.An activity-pending result.
ArgumentExceptionThrown when nodeId or activity metadata is empty, a contract version is invalid, or the work value does not implement its declared type.ArgumentNullExceptionThrown when activity or one of its required values is null.The in-memory runner does not execute activities. Execute the work through a test or host boundary, construct a result with the request's typed callsite, and call IFlowRunner{TContext}.ResumeActivityAsync.
FlowRunStatus Status { get; }
Source
Gets the runner status.
TContext? Context { get; }
Source
Gets the latest context when the result carries one.
string? NodeId { get; }
Source
Gets the node id where execution paused or ended.
string? WaitingEventName { get; }
Source
Gets the event name awaited by a waiting result.
IFlowEventCallsite? EventCallsite { get; }
Source
Gets the immutable typed event contract for a waiting result, or null for a string wait.
The runner preserves this metadata so a host can select an allowlisted payload codec. The result does not authorize, decode, or deduplicate event delivery.
FlowTimeout? Timeout { get; }
Source
Gets the optional timeout associated with a waiting result.
string? TimedOutEventName { get; }
Source
Gets the event whose timeout branch completed.
FlowFault? Fault { get; }
Source
Gets the fault details for a faulted result.
IFlowActivityRequest<TContext>? Activity { get; }
Source
Gets the typed activity request when Status is FlowRunStatus.ActivityPending.
Identifies the terminal or pause status returned by an AppSurface Flow runner.
The numeric values are part of the public compatibility contract for logs, persisted state, and tests. Do not reorder, renumber, remove, or reuse values. Add new statuses only at the end with explicit numeric values and a migration/versioning plan.
Represents the discriminated outcome returned by a flow node.
TContextSerializable context type carried by the flow.The sealed derived records form a stable discriminated-union style API that works on current C# compilers. Future native union syntax can be layered on as authoring sugar without changing the runtime contract.
FlowNext<TContext> Next(string nodeId, TContext context)
Source
Creates an outcome that moves execution to another declared node.
nodeIdTarget node id.contextContext to pass to the target node.A next-node outcome.
FlowWait<TContext> Wait(string eventName, TContext context, FlowTimeout? timeout = null)
Source
Creates an outcome that waits for an external event before executing this node again.
eventNameExternal event name.contextContext to persist while waiting.timeoutOptional wait timeout.A wait outcome.
FlowWait<TContext> Wait<TPayload>(FlowEventCallsite<TPayload> callsite, TContext context, FlowTimeout? timeout = null)
Source
Creates an outcome that waits for an external event carrying one exact typed payload contract.
TPayloadExpected allowlisted event payload type.callsiteStable event name and durable payload contract.contextContext to persist while waiting.timeoutOptional wait timeout.A typed external-event wait outcome.
ArgumentNullExceptionThrown when callsite or context is null.FlowTimedOut<TContext> TimedOut(string eventName, TContext context)
Source
Creates an outcome indicating the node handled a timeout branch.
eventNameEvent whose wait expired.contextContext after timeout handling.A timed-out outcome.
FlowComplete<TContext> Complete(TContext context)
Source
Creates a successful completion outcome.
contextFinal context.A completion outcome.
FlowFaultOutcome<TContext> Fault(string code, string message)
Source
Creates a fault outcome.
codeStable machine-readable code.messageHuman-readable diagnostic message.A fault outcome.
FlowActivity<TContext, TWork, TResult> Activity<TWork, TResult>(FlowActivityCallsite<TWork, TResult> callsite, TWork work, TContext context)
Source
Creates an outcome that schedules one typed external activity and pauses the Flow node for its result.
TWorkSerializable work contract sent to the activity executor.TResultSerializable result contract returned to the same node.callsiteStable typed activity callsite.workWork value to persist and execute.contextContext to persist atomically with the activity command.An activity outcome.
ArgumentNullExceptionThrown when callsite, work, or context is null.Returning this outcome does not execute work. A durable host records the transition and activity command atomically, executes the work through its provider-safe worker boundary, and resumes this same node with FlowActivityWorkResult{TResult}. Nodes must not perform the external effect themselves.
Moves execution to another node in the same flow definition.
TContextSerializable context type carried by the flow.string NodeId { get; }
Source
Gets the target node id.
TContext Context { get; }
Source
Gets the context to pass to the target node.
Pauses execution until a named external event or timeout is delivered by the host.
TContextSerializable context type carried by the flow.string EventName { get; }
Source
Gets the external event name.
IFlowEventCallsite? EventCallsite { get; }
Source
Gets the exact typed event contract, or null when this wait explicitly accepts no payload.
TContext Context { get; }
Source
Gets the context to persist while waiting.
FlowTimeout? Timeout { get; }
Source
Gets the optional wait timeout.
Reports that a timeout branch has been handled by a node.
TContextSerializable context type carried by the flow.string EventName { get; }
Source
Gets the event whose wait expired.
TContext Context { get; }
Source
Gets the context after timeout handling.
Completes a flow instance successfully.
TContextSerializable context type carried by the flow.TContext Context { get; }
Source
Gets the final context.
Fails a flow instance with a process-level fault.
TContextSerializable context type carried by the flow.FlowFault Fault { get; }
Source
Gets the fault details.
This member intentionally hides the static fault factory on FlowNodeOutcome{TContext}.
Schedules one typed external activity and pauses the current Flow node until its result is available.
TContextSerializable context type carried by the Flow.TWorkSerializable work contract sent to the activity executor.TResultSerializable result contract returned to the same node.The generic properties are convenient for node tests. Durable hosts should consume IFlowActivityRequest{TContext} to read declared CLR types, versions, work, and context without reflection.
FlowActivityCallsite<TWork, TResult> Callsite { get; }
Source
Gets the stable typed callsite.
TWork Work { get; }
Source
Gets the typed work value.
TContext Context { get; }
Source
Gets the Flow context to persist atomically with the activity command.
Registers the AppSurface Flow core services.
The module is passive: it adds the one-node transition evaluator, in-memory runner, definition registry, and options used by local tests and host-specific adapters. It does not start background workers, create storage, schedule timers, execute activities, or replace AppSurface startup composition.
Describes a fault returned by a flow node or adapter.
Faults are flow results, not exceptions. Use them for expected process failures that should be visible to callers or durable orchestration logs. Use exceptions for invalid definitions, host configuration errors, and programmer bugs.
string Code { get; }
Source
Gets the stable machine-readable code.
string Message { get; }
Source
Gets the human-readable diagnostic message.
Marks a partial type as the generated authoring specification for an AppSurface Flow.
Use generated authoring when a flow should be declared as typed transformer nodes with compile-time validation of outcome coverage. Use FlowGraphBuilder{TContext} directly when a host needs dynamic graph construction, low-level runtime control, or compatibility with hand-authored nodes. The annotated type must be a non-generic partial class. Record and nested generated flow specifications are not supported. Generated authoring is additive: the generator lowers the annotated specification into the existing FlowDefinition{TContext} runtime contract without changing low-level flow APIs. Avoid mixing generated definition helpers with manual low-level node registration for the same flow because that makes mapping ownership unclear.
string FlowId { get; }
Source
Gets the stable flow identifier used by generated definitions.
string Version { get; set; }
Source
Gets or sets the stable graph version. Defaults to 1.
Marks a partial nested type as a generated-authoring flow node.
Apply this attribute to a partial class nested inside a FlowAuthoringAttribute flow type. The node class must implement IFlowTransformerNode{TInput,TOutcome} where TInput matches InputContextType and TOutcome is the generated outcome union for that node.
string NodeId { get; }
Source
Gets the stable node identifier.
Type InputContextType { get; }
Source
Gets the context type consumed by the node.
Marks one generated-authoring node as the flow start node.
Exactly one node per generated flow must be marked with FlowStartAttribute. If a flow declares zero or multiple start nodes, the generator reports diagnostic ASFLOWA004 and does not produce the generated definition helpers for that invalid flow.
Declares one generated outcome case a transformer node can return.
Outcome contexts are nominal ports used by the generated graph validator. FlowOutcomeKind.Next must carry the input context type of exactly one target node. FlowOutcomeKind.Wait and FlowOutcomeKind.TimedOut resume the current node, so they must carry that node's input context type. FlowOutcomeKind.Fault must carry FlowFault. FlowOutcomeKind.Complete is terminal and does not require a target node. FlowOutcomeKind.Activity uses the five-argument constructor to declare work and result contracts, and its output context must match the current node input context.
string Name { get; }
Source
Gets the stable outcome name.
FlowOutcomeKind Kind { get; }
Source
Gets the outcome kind.
Type OutputContextType { get; }
Source
Gets the context type carried by this outcome.
Type? WorkType { get; }
Source
Gets the activity work contract type, when this is an FlowOutcomeKind.Activity declaration.
Type? ResultType { get; }
Source
Gets the activity result contract type, when this is an FlowOutcomeKind.Activity declaration.
string? CallsiteId { get; set; }
Source
Gets or sets an explicit stable activity callsite id.
When omitted, generated authoring uses <node-id>.<outcome-name>. Either form is a durable identifier within a Flow definition and must not change while nonterminal instances reference it.
int WorkContractVersion { get; set; }
Source
Gets or sets the positive serialized activity work contract version. Defaults to one.
int ResultContractVersion { get; set; }
Source
Gets or sets the positive serialized activity result contract version. Defaults to one.
Describes one generated graph mapping method for analyzer validation.
Do not apply this attribute manually. The generator emits it on generated GraphBuilder mapping methods so analyzers can validate explicit BuildDefinition lambda coverage. Manually applying it can make graph coverage diagnostics misleading. This attribute is emitted by generated authoring code. Application code should use FlowOutcomeAttribute to declare outcomes instead of applying this attribute manually.
string NodeId { get; }
Source
Gets the stable source node identifier.
string OutcomeName { get; }
Source
Gets the stable outcome name.
Type OutputContextType { get; }
Source
Gets the context type carried by this outcome.
Executes one generated-authoring transformer node.
TInputTyped input context consumed by the node.TOutcomeGenerated outcome union type returned by the node.Implementations receive a FlowTransformerContext{TInput} and must return a non-null generated outcome case. The generated adapter lowers that case into the v1 runtime contract and the runner enforces the non-null outcome requirement. Exceptions thrown by an implementation propagate to the caller; use FlowOutcomeKind.Fault with FlowFault for expected process failures that should be represented as flow results. Nodes should honor cancellation and must not perform externally visible side effects; return FlowOutcomeKind.Activity so a durable host can commit the command before executing work. A node may be evaluated more than once when a process dies before the returned transition commits.
ValueTask<TOutcome> ExecuteAsync(FlowTransformerContext<TInput> context, CancellationToken cancellationToken = default)
Source
Executes the node and returns a generated outcome case.
contextTyped authoring execution context.cancellationTokenCancellation token supplied by the runner. The default value is provided for manual invocation convenience.A generated outcome case.
Describes one generated-authoring transformer execution.
TInputTyped input context consumed by the node.FlowIdStable flow id.VersionFlow graph version.NodeIdCurrent node id.StateTyped input state.ResumeEventOptional external event or timeout that resumed the node.FlowId, Version, and NodeId identify the current definition and node being executed. State is the typed input context unwrapped from the generated envelope; the record does not validate it, and generated adapters assume it is non-null. ResumeEvent is null for initial execution and non-null when a node resumes after an external event or timeout. ActivityResult is non-null only when a typed activity resumes the node; runners never populate both resume forms at once.
FlowActivityWorkResult? ActivityResult { get; init; }
Source
Gets the optional typed activity result that resumed this transformer node.
Use the generated outcome callsite's TryGetResult or GetResult method instead of casting FlowActivityWorkResult.Result. The property is null on initial and external-event execution.
Runtime outcome kinds supported by generated AppSurface Flow authoring.
The numeric values are part of the public compatibility contract. Do not renumber or reorder existing values.
Stable fault codes shared by the built-in transition evaluator and runners that translate its decisions.
Input for one host-neutral Flow node evaluation.
TContextSerializable context type carried by the Flow.string NodeId { get; }
Source
Gets the current node id.
TContext Context { get; }
Source
Gets the current Flow context.
FlowResumeEvent? ResumeEvent { get; }
Source
Gets the optional external event or timeout that resumed the node.
FlowActivityWorkResult? ActivityResult { get; }
Source
Gets the optional typed activity result that resumed the node.
Host-neutral decision produced by evaluating exactly one Flow node.
TContextSerializable context type carried by the Flow.Inspect Kind before reading kind-specific properties. A durable host commits this decision before evaluating another node. It must atomically persist an FlowTransitionKind.Activity decision, its activity command, and the waiting context.
FlowTransition<TContext> Next(string nodeId, string nextNodeId, TContext context)
Source
Creates a next-node transition carrying the declared target and persisted context.
nodeIdNode that produced the transition.nextNodeIdDeclared target node.contextContext to persist for the target node.A transition whose target and context are populated.
FlowTransition<TContext> Waiting(string nodeId, string eventName, IFlowEventCallsite? eventCallsite, TContext context, FlowTimeout? timeout)
Source
Creates a wait transition carrying the event contract, persisted context, and optional timeout.
nodeIdNode that produced the transition.eventNameExternal event name.eventCallsiteExact typed event contract, or null for an explicit no-payload wait.contextContext to persist while waiting.timeoutOptional durable timeout.A transition whose event, context, and timeout fields are populated.
FlowTransition<TContext> TimedOut(string nodeId, string eventName, TContext context)
Source
Creates a timeout transition carrying the expired event name and resulting context.
nodeIdNode that handled the timeout.eventNameExternal event whose wait expired.contextContext after timeout handling.A transition whose event name and context are populated.
FlowTransition<TContext> Completed(string nodeId, TContext context)
Source
Creates a terminal completion transition carrying the final context.
nodeIdNode that completed the Flow.contextFinal context.A transition whose context is populated.
FlowTransition<TContext> Faulted(string nodeId, FlowFault fault)
Source
Creates a fault transition carrying only the process-level fault.
nodeIdNode associated with the fault.faultStable fault code and safe message.A transition whose fault is populated and whose context is absent.
FlowTransition<TContext> ActivityRequested(string nodeId, IFlowActivityRequest<TContext> activity)
Source
Creates an activity transition carrying the activity request and its persisted context.
nodeIdNode that requested the activity.activityTyped activity request produced by the node.A transition whose activity and context are populated.
FlowTransitionKind Kind { get; }
Source
Gets the transition kind.
string NodeId { get; }
Source
Gets the node that produced the transition.
TContext? Context { get; }
Source
Gets the context carried by non-fault transitions.
string? NextNodeId { get; }
Source
Gets the declared target for a FlowTransitionKind.Next transition.
string? EventName { get; }
Source
Gets the event name carried by wait and timeout transitions.
IFlowEventCallsite? EventCallsite { get; }
Source
Gets the exact typed event contract for a wait, or null for an explicit no-payload wait.
FlowTimeout? Timeout { get; }
Source
Gets the optional timeout carried by a wait transition.
FlowFault? Fault { get; }
Source
Gets the process-level fault carried by a fault transition.
IFlowActivityRequest<TContext>? Activity { get; }
Source
Gets the typed request metadata carried by an activity transition.
Evaluates exactly one Flow node and maps its outcome to a host-neutral transition.
TContextSerializable context type carried by the Flow.This is the shared semantic boundary for in-memory, Durable Task, and PostgreSQL hosts. It does not loop through FlowNext{TContext} transitions, persist state, validate serialization, schedule timers, or execute activities. Nodes can be evaluated again when a process dies before the host commits the returned transition, so they must be side-effect-free and must receive nondeterministic inputs through explicit context or resume contracts. Transition creation is package-owned so every runner observes the same mapping and validation semantics. External implementations should decorate and delegate to FlowTransitionEvaluator{TContext} for concerns such as telemetry; they cannot manufacture alternative transitions. Express custom process behavior through node outcomes instead of replacing the evaluator's transition semantics.
ValueTask<FlowTransition<TContext>> EvaluateAsync(FlowDefinition<TContext> definition, FlowTransitionInput<TContext> input, CancellationToken cancellationToken = default)
Source
Evaluates one declared node.
definitionImmutable Flow definition containing the node.inputNode id, context, and optional resume input.cancellationTokenToken that cancels node execution.One mapped transition. Missing nodes, undeclared next targets, and unsupported outcomes become fault transitions; caller argument errors, cancellation, and node exceptions propagate.
ArgumentNullExceptionThrown when definition or input is null, or when the selected node returns a null outcome.OperationCanceledExceptionThrown when cancellationToken is canceled before or during node execution.string EvaluatorId { get; }
Source
Gets the stable, host-independent evaluator identity used by durable execution manifests.
string EvaluatorVersion { get; }
Source
Gets the evaluator semantics version used by durable execution manifests.
Default host-neutral implementation of IFlowTransitionEvaluator{TContext}.
TContextSerializable context type carried by the Flow.Identifies the host-neutral decision produced by evaluating exactly one Flow node.
Numeric values are a compatibility contract for durable hosts and telemetry. Do not reorder, renumber, remove, or reuse values. Append new transition kinds with explicit numeric values.
Describes a timeout requested by a flow wait outcome.
The core in-memory runner returns timeout metadata to callers; durable hosts are responsible for turning it into a durable timer and racing that timer against the external event.
TimeSpan Duration { get; }
Source
Gets the timeout duration.
Describes one node in a flow definition.
TContextSerializable context type carried by the flow.string NodeId { get; }
Source
Gets the stable node id.
IFlowNode<TContext> Node { get; }
Source
Gets the executable node implementation.
IReadOnlySet<string> NextNodeIds { get; }
Source
Gets the allowed next-node targets.
Builds and validates typed AppSurface Flow graphs.
TContextSerializable context type carried by the flow.The builder validates declared transitions before returning a definition. Every target passed to AddNode(string, IFlowNode{TContext}, string[]) must exist in the final graph. Cycles are allowed because long-running business processes often revisit a review, remediation, or wait step.
FlowGraphBuilder<TContext> Create(string flowId, string version = "1")
Source
Creates a new builder.
flowIdStable flow id.versionFlow graph version. Defaults to 1.A new builder instance.
FlowGraphBuilder<TContext> AddNode(string nodeId, IFlowNode<TContext> node, params string[] nextNodeIds)
Source
Adds a node and declares the node ids it may return from a FlowNext{TContext} outcome.
nodeIdStable node id.nodeNode implementation.nextNodeIdsAllowed FlowNext{TContext}.NodeId targets.The current builder.
ArgumentExceptionThrown when the id is empty or duplicated.FlowGraphBuilder<TContext> StartAt(string nodeId)
Source
Sets the node id used for new flow instances.
nodeIdStart node id.The current builder.
FlowDefinition<TContext> Build()
Source
Validates and creates an immutable flow definition.
The validated definition.
FlowDefinitionExceptionThrown when the graph is incomplete or references missing nodes.Configures local AppSurface Flow execution behavior.
These options affect the in-memory runner only. Durable hosts should keep replay, persistence, external events, and timer policy in their durable orchestration layer and use this package's contracts for typed graph behavior.
int MaxStepsPerRun { get; set; }
Source
Gets or sets the maximum number of synchronous node transitions allowed during one in-memory run.
The default value, 1000, protects local tests and examples from accidental infinite loops. Set a higher value for intentionally dense local workflows. Values less than 1 are treated as configuration errors when a runner starts.
Runs AppSurface Flow definitions in memory for local development and tests.
TContextSerializable context type carried by the flow.This runner does not persist state, create durable timers, or buffer external events. It executes synchronously through FlowNext{TContext} outcomes and stops at FlowWait{TContext}, FlowActivity{TContext,TWork,TResult}, FlowComplete{TContext}, FlowTimedOut{TContext}, or FlowFaultOutcome{TContext}. It reports activities to the caller; it never executes external work itself.
Describes a typed external-event wait without exposing CLR type names to durable storage.
This interface describes manifest metadata only. A durable host validates an authorized event against its persisted wait registration, selects an allowlisted codec through ContractName and ContractVersion, validates the decoded value against PayloadType, and only then invokes the Flow evaluator. The evaluator does not authorize, decode, or deduplicate external events.
string EventName { get; }
Source
Gets the exact case-sensitive event name.
Type PayloadType { get; }
Source
Gets the expected event payload CLR type for allowlisted codec lookup.
string ContractName { get; }
Source
Gets the exact durable payload contract name.
string ContractVersion { get; }
Source
Gets the exact durable payload contract version.
Declares the exact typed payload contract accepted by one external Flow event wait.
TPayloadAllowlisted event payload type.The event name and contract identity are durable manifest values. Change them only with a new Flow definition version. Values are preserved exactly and compared ordinally by durable hosts; there is no trimming, case folding, or normalization. TPayload is runtime codec metadata rather than a durable wire identifier. Use the string-based Wait overload when an event intentionally carries no payload.
Validates and snapshots event-callsite metadata at public host boundaries.
IFlowEventCallsite is extensible, so implementations can expose mutable or inconsistent getters. Capturing each value once prevents later mutation from changing an already-created wait or durable decision.
IFlowEventCallsite Snapshot(IFlowEventCallsite eventCallsite, string parameterName)
Source
Creates an immutable, validated copy of an event callsite.
eventCallsiteCallsite supplied through a public API.parameterNamePublic parameter name used by validation exceptions.Immutable event metadata safe to retain.
Executes one typed step in an AppSurface Flow graph.
TContextSerializable context type carried by the flow.Nodes should be deterministic, idempotent where practical, and explicit about process outcomes. Durable hosts may replay orchestration decisions around node execution, so avoid hidden global side effects in nodes and keep external I/O behind durable activity boundaries.
ValueTask<FlowNodeOutcome<TContext>> ExecuteAsync(FlowExecutionContext<TContext> context, CancellationToken cancellationToken = default)
Source
Executes the node.
contextExecution context for the current node.cancellationTokenCancellation token supplied by the runner.A discriminated outcome that tells the runner how to continue.
Internal, prevalidated node view used by runners to avoid repeated graph-routing lookups.
TContextSerializable context type carried by the flow.Instances are created only by FlowDefinition{TContext} after the public node dictionary has been copied and validated. The public API remains FlowDefinition{TContext}.Nodes; this type exists only to keep execution routing internal and fail-closed.
void SetNextNodes(IReadOnlyDictionary<string, FlowExecutionNode<TContext>> nextNodes)
Source
Assigns the prevalidated next-node map once all execution nodes have been created.
nextNodesResolved next-node targets.FlowNodeDescriptor<TContext> Descriptor { get; }
Source
Gets the public descriptor executed for this node.
IReadOnlyDictionary<string, FlowExecutionNode<TContext>> NextNodes { get; set; }
Source
Gets the prevalidated next-node targets keyed by allowed target id.
Stores AppSurface Flow definitions by context type, flow id, and version.
void Register<TContext>(FlowDefinition<TContext> definition)
Source
Registers a flow definition.
TContextContext type for the definition.definitionDefinition to register.ArgumentExceptionThrown when the same context, flow id, and version are already registered.bool TryGet<TContext>(string flowId, string version, out FlowDefinition<TContext>? definition)
Source
Tries to resolve a registered flow definition.
TContextExpected context type.flowIdFlow id.versionFlow version.definitionResolved definition, when found.true when a matching definition exists.
FlowDefinition<TContext> GetRequired<TContext>(string flowId, string version)
Source
Resolves a registered flow definition or throws a diagnostic exception.
TContextExpected context type.flowIdFlow id.versionFlow version.The matching definition.
FlowDefinitionExceptionThrown when the definition is missing or registered with another context type.Thread-safe in-memory implementation of IFlowDefinitionRegistry.
Describes a typed, stable activity callsite in a Flow definition.
TWorkSerializable work contract sent to the activity executor.TResultSerializable result contract returned to the waiting Flow node.A callsite id and its contract versions are durable identifiers. Do not change them while nonterminal Flow instances can reference the callsite. Expected business failures belong in TResult; exhausted technical failures and ambiguous provider outcomes are host-level suspension concerns.
FlowActivityWorkResult<TResult> CreateResult(TResult result)
Source
Creates the typed result used to resume this callsite's Flow node.
resultDecoded activity result.A result carrying this callsite's identity and result contract version.
ArgumentNullExceptionThrown when result is null.bool TryGetResult(FlowActivityWorkResult? workResult, out TResult result)
Source
Attempts to read a resumed activity result for this exact callsite and result contract.
workResultActivity result supplied by the host, or null for initial node evaluation.resultThe typed result when the identity and contract match.true when the result belongs to this callsite; otherwise, false.
A mismatched result is not coerced. Durable hosts should normally prevent mismatches by validating the persisted wait registration before evaluating the node. Nodes can use this method to distinguish initial execution from activity resumption without casting or reflection.
TResult GetResult(FlowActivityWorkResult? workResult)
Source
Reads a resumed activity result for this exact callsite and result contract.
workResultActivity result supplied by the host.The typed activity result.
FlowDefinitionExceptionThrown when the result is absent or belongs to a different callsite, CLR type, or contract version.string CallsiteId { get; }
Source
Gets the stable callsite identifier.
int WorkContractVersion { get; }
Source
Gets the serialized work contract version.
int ResultContractVersion { get; }
Source
Gets the serialized result contract version.
Provides non-generic activity request metadata to durable Flow hosts.
TContextSerializable context persisted while the activity runs.The metadata is intentionally exposed without reflection so a host can select registered codecs from the declared CLR types and contract versions. The interface does not authorize execution or serialize values itself.
FlowActivityWorkResult CreateResult(object result)
Source
Wraps a decoded result in this request's typed callsite contract.
resultDecoded result whose runtime value must implement ResultType.A typed work result suitable for resuming the Flow node.
ArgumentNullExceptionThrown when result is null.ArgumentExceptionThrown when result has the wrong CLR type.InvalidOperationExceptionThrown by validated host-boundary wrappers when an extensible implementation returns null, substitutes a different decoded value, or returns callsite, type, or version metadata that differs from the captured request.This method lets a host bridge a registered non-generic codec back into the typed Flow result without reflection. Implementations must wrap the exact decoded value supplied by the host and preserve the request's callsite id, declared result type, and result contract version.
string CallsiteId { get; }
Source
Gets the stable callsite identifier.
Type WorkType { get; }
Source
Gets the declared work CLR type.
int WorkContractVersion { get; }
Source
Gets the serialized work contract version.
Type ResultType { get; }
Source
Gets the declared result CLR type.
int ResultContractVersion { get; }
Source
Gets the serialized result contract version.
object Work { get; }
Source
Gets the typed work value through a non-generic host boundary.
TContext Context { get; }
Source
Gets the Flow context to persist atomically with the activity command.
Validates and snapshots activity requests supplied through extensible public host boundaries.
A request snapshot preserves the metadata, work value, and context that a host must persist atomically. The work and context contracts themselves should be immutable or serialized immediately; this helper does not deep-clone application values.
IFlowActivityRequest<TContext> Snapshot<TContext>(IFlowActivityRequest<TContext> activity, string parameterName)
Source
Creates an immutable, validated activity-request wrapper.
TContextSerializable Flow context type.activityRequest supplied through a public API.parameterNamePublic parameter name used by validation exceptions.A request whose metadata cannot change after validation.
Base contract for a decoded activity result supplied when a waiting node resumes.
Results contain safe application contracts, not provider response bodies or credentials. Durable hosts validate the callsite, CLR type, and result contract version against the persisted activity wait before node evaluation.
string CallsiteId { get; }
Source
Gets the activity callsite that produced the result.
Type ResultType { get; }
Source
Gets the declared result CLR type.
int ResultContractVersion { get; }
Source
Gets the serialized result contract version.
object Result { get; }
Source
Gets the decoded result through a non-generic host boundary.
Carries a decoded, typed activity result for node resumption.
TResultSerializable result contract returned by the activity executor.TResult Value { get; }
Source
Gets the typed decoded result.
Represents an invalid flow definition or an attempt to execute a node transition that the definition does not allow.
Definition errors are deterministic authoring mistakes. They are surfaced as exceptions so tests and startup validation fail loudly before a durable instance is started.
Describes an external event or timeout that resumed a waiting flow node.
FlowResumeEvent Timeout(string eventName)
Source
Creates a timeout resume event for the supplied wait event.
eventNameWait event whose timeout expired.A timeout resume event.
string EventName { get; }
Source
Gets the event name.
object? Payload { get; }
Source
Gets the optional event payload.
bool IsTimeout { get; }
Source
Gets a value indicating whether this event represents a timeout.