@voltro/runtime 0.81.0 → 0.82.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4551,7 +4551,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
4551
4551
  SOFTWARE.
4552
4552
  ```
4553
4553
 
4554
- ## undici@8.10.0
4554
+ ## undici@8.11.2
4555
4555
 
4556
4556
  License: MIT
4557
4557
 
package/dist/index.d.ts CHANGED
@@ -68,16 +68,19 @@ import { MetricBoundaries } from 'effect';
68
68
  import { MetricReader } from '@opentelemetry/sdk-metrics';
69
69
  import { MutationIdempotencyScope } from '@voltro/protocol';
70
70
  import { NoRowFound } from '@voltro/protocol';
71
+ import { NoSuchResource } from '@voltro/protocol';
71
72
  import { PendingApproval } from '@voltro/protocol';
72
73
  import { PluginHttpRoute } from '@voltro/protocol';
73
74
  import { PluginHttpRouteByteStream } from '@voltro/protocol';
74
75
  import { PluginRefOrphanPolicy } from '@voltro/database';
75
76
  import { Predicate } from '@voltro/database';
77
+ import { ProcedureWireError } from '@voltro/protocol';
76
78
  import { PublicApiSpec } from '@voltro/protocol';
77
79
  import { Query } from '@voltro/database';
78
80
  import { QueryDescriptor } from '@voltro/database';
79
81
  import { Redis } from 'ioredis';
80
82
  import { registerRetention } from '@voltro/database';
83
+ import { ResourceMissing } from '@voltro/protocol';
81
84
  import { RestRouteDescriptor } from '@voltro/protocol/rest';
82
85
  import { RetentionConflict } from '@voltro/database';
83
86
  import { RetentionSource } from '@voltro/database';
@@ -132,6 +135,9 @@ import { WorkflowControlRequest } from '@voltro/workflow';
132
135
  import { WorkflowControlResult as WorkflowControlResult_2 } from '@voltro/protocol';
133
136
  import { WorkflowParentClosePolicy } from '@voltro/protocol';
134
137
  import { WorkflowQueuedCancellationResult } from '@voltro/protocol';
138
+ import { WorkflowRestartCommand } from '@voltro/protocol';
139
+ import { WorkflowRestartObservation } from '@voltro/protocol';
140
+ import { WorkflowRestartResult } from '@voltro/protocol';
135
141
  import { WorkflowRetryObservation } from '@voltro/protocol';
136
142
  import { WorkflowRunHandle } from '@voltro/protocol';
137
143
  import { WorkflowRunSnapshot as WorkflowRunSnapshot_2 } from '@voltro/protocol';
@@ -1793,7 +1799,7 @@ export declare const bindConnectionCredential: (clientId: number, credential: Co
1793
1799
  * interrupt registry subscriptions use — so one reconnect policy, one devtools
1794
1800
  * view, one connection lifecycle for both primitives.
1795
1801
  */
1796
- export declare const bindEvent: (input: BindEventInput) => Stream.Stream<EventStreamEvent<unknown>, ScopeError | Unauthenticated, SubjectService | ConnectionInfo>;
1802
+ export declare const bindEvent: (input: BindEventInput) => Stream.Stream<EventStreamEvent<unknown>, ScopeError | Unauthenticated | NoSuchResource, SubjectService | ConnectionInfo>;
1797
1803
 
1798
1804
  export declare interface BindEventInput {
1799
1805
  readonly bus: EventBus;
@@ -2639,6 +2645,12 @@ export declare interface CoordinatedScheduleDeps {
2639
2645
  * it holds. Without either, a REMOTE replica's enqueue produces no local
2640
2646
  * event, and a disarmed task would sleep through it forever. The backoff
2641
2647
  * ceiling exists for exactly that case and is the correct choice there.
2648
+ *
2649
+ * The task's half of the bargain: an idle tick disarms only when it returns
2650
+ * `nextDueInMs: null` ("nothing is scheduled"). Work that comes due on a
2651
+ * clock is not an arrival, so the tick reports its instant as `nextDueInMs`
2652
+ * and the task is armed for exactly then. An idle tick that says neither
2653
+ * backs off instead of disarming.
2642
2654
  */
2643
2655
  readonly disarmWhenIdle?: boolean;
2644
2656
  }
@@ -2705,16 +2717,25 @@ export declare interface CoordinatedTickOutcome {
2705
2717
  readonly idle: boolean;
2706
2718
  /**
2707
2719
  * Milliseconds until the earliest thing this task already knows is coming —
2708
- * a debounce window closing, a lease expiring. Caps the backoff, so a task
2709
- * that is idle RIGHT NOW but has a deadline in 400 ms is armed for 400 ms
2710
- * rather than for 30 s.
2720
+ * a debounce window closing, a lease expiring, a retry or a re-poll whose
2721
+ * time arrives. Caps the backoff, so a task that is idle RIGHT NOW but has a
2722
+ * deadline in 400 ms is armed for 400 ms rather than for 30 s.
2723
+ *
2724
+ * `null` is a statement, not an absence: "I looked, and nothing is scheduled
2725
+ * — the next piece of work can only arrive as a write". It is the ONLY idle
2726
+ * report that lets a `disarmWhenIdle` task stop ticking. Omitting the field
2727
+ * means "I did not say", and a task that did not say backs off toward the
2728
+ * ceiling instead of disarming.
2711
2729
  *
2712
- * This is the part a fixed interval cannot express and the part that makes
2713
- * the backoff safe: without it, backing off is a bet that nothing time-based
2714
- * is pending, and deferring controls are exactly the case where that bet is
2715
- * wrong.
2730
+ * The distinction exists because the failure is silent and permanent. Work
2731
+ * that becomes due on a CLOCK — a row released with a future `enqueuedAt`, a
2732
+ * lease that runs out — produces no write, so no change event, so no
2733
+ * `wake()`. A dispatcher that reported `{ idle: true }` while holding such a
2734
+ * row disarmed and never came back; the row sat until an unrelated write
2735
+ * happened to wake it. Making "nothing scheduled" an explicit answer turns a
2736
+ * forgotten deadline into a slower tick rather than a hang.
2716
2737
  */
2717
- readonly nextDueInMs?: number;
2738
+ readonly nextDueInMs?: number | null;
2718
2739
  }
2719
2740
 
2720
2741
  export declare type CoordinationOutcome = 'single' | 'wonLock' | 'lostLock' | 'external' | 'cluster';
@@ -3269,6 +3290,18 @@ export declare const decideApprovalInvocation: (input: {
3269
3290
  readonly status: "approved" | "rejected";
3270
3291
  }>;
3271
3292
 
3293
+ /**
3294
+ * `unknown` when the executor's failures are all declared; otherwise a type the
3295
+ * handler cannot satisfy, whose one property spells out the undeclared tag(s)
3296
+ * and the three ways to resolve them — that text is what the compile error at
3297
+ * the handler shows.
3298
+ */
3299
+ export declare type DeclaredFailureCheck<D extends ExecutorDescriptor, R> = [
3300
+ UndeclaredErrorTags<D, R>
3301
+ ] extends [never] ? unknown : {
3302
+ readonly undeclaredFailure: `'${UndeclaredErrorTags<D, R>}' is not in this procedure's wire union — add it to the descriptor's \`error:\`, register it through a plugin's \`errorSchemas\`, or map it away (Effect.orDie for a defect)`;
3303
+ };
3304
+
3272
3305
  /**
3273
3306
  * Decrypt a value produced by `encryptField` or by an `.encrypted()` column —
3274
3307
  * one encoding, so that sentence is now true in both directions.
@@ -3539,7 +3572,7 @@ export declare const defineEventTrigger: <EventPayload = unknown, WorkflowPayloa
3539
3572
  * Runtime identity — returns `fn` unchanged; the whole value is the compile-time
3540
3573
  * check. See the module header for the failure it prevents.
3541
3574
  */
3542
- export declare const defineExecutor: <D extends ExecutorDescriptor, F extends (input: ExecutorInput<D>, ctx: AppContext) => ExecutorReturn<D, unknown, unknown>>(_descriptor: D, fn: F) => ((input: ExecutorInput<D>, ctx: AppContext) => ReturnType<F>);
3575
+ export declare const defineExecutor: <D extends ExecutorDescriptor, F extends (input: ExecutorInput<D>, ctx: AppContext) => ExecutorReturn<D, unknown, unknown>>(_descriptor: D, fn: F & DeclaredFailureCheck<D, ReturnType<F>>) => ((input: ExecutorInput<D>, ctx: AppContext) => ReturnType<F>);
3543
3576
 
3544
3577
  /**
3545
3578
  * Declare a data-quality expectation. Validates the shape at declaration time so
@@ -3843,6 +3876,9 @@ export declare class Dispatcher {
3843
3876
  /** Query labels already warned about for an undeclared raw read, so a hot
3844
3877
  * subscription logs once rather than once per subscriber. */
3845
3878
  private readonly rawReadWarned;
3879
+ /** The CRDT-managed columns of `table` (empty when it has none) — what a
3880
+ * subscription's backpressure outbox folds incrementally. */
3881
+ crdtColumnsFor(table: string): ReadonlySet<string>;
3846
3882
  constructor(deps: DispatcherDependencies);
3847
3883
  /**
3848
3884
  * REL-14 — a raw read that nothing can invalidate, said out loud.
@@ -4100,7 +4136,10 @@ export declare interface DrainResult {
4100
4136
  */
4101
4137
  readonly scanned: number;
4102
4138
  /**
4103
- * When the earliest NOT-yet-due pending row comes due, as an epoch ms.
4139
+ * When the queue next has work that no write will announce, as an epoch ms:
4140
+ * the earliest NOT-yet-due pending row, or the earliest `delivering` claim
4141
+ * whose lease runs out (its deliverer may be gone, and the reclaim is due
4142
+ * then).
4104
4143
  *
4105
4144
  * `undefined` means nothing in the read window is waiting. A LOWER bound (the
4106
4145
  * window is capped by `batchSize`), which is the safe direction: understating
@@ -4108,7 +4147,10 @@ export declare interface DrainResult {
4108
4147
  *
4109
4148
  * This is what lets the runner arm for a backoff instead of polling until it
4110
4149
  * expires — the one thing in this loop that genuinely needs a clock, since a
4111
- * retry becoming due is not a write anybody can be notified about.
4150
+ * retry becoming due, or a lease running out, is not a write anybody can be
4151
+ * notified about. A runner that stopped ticking on an empty due window
4152
+ * without this would leave a lost deliverer's row claimed until something
4153
+ * unrelated wrote to the table.
4112
4154
  */
4113
4155
  readonly nextAttemptAt?: number;
4114
4156
  }
@@ -4700,8 +4742,13 @@ export declare interface ExecutorDescriptor {
4700
4742
  readonly kind: 'query' | 'mutation' | 'action';
4701
4743
  readonly input: Schema.Schema.Any;
4702
4744
  readonly output: Schema.Schema.Any;
4745
+ readonly error: Schema.Schema.All;
4703
4746
  }
4704
4747
 
4748
+ /** The failure type of an executor's return, when it returns an Effect. A
4749
+ * Promise's rejection is untyped and a plain value cannot fail. */
4750
+ declare type ExecutorFailure<R> = R extends Effect.Effect<infer _A, infer E, infer _R> ? E : never;
4751
+
4705
4752
  /** The decoded INPUT a handler receives (the Type side of the input schema). */
4706
4753
  export declare type ExecutorInput<D extends ExecutorDescriptor> = Schema.Schema.Type<D['input']>;
4707
4754
 
@@ -5304,6 +5351,14 @@ export declare type ExternalTriggerOutcome =
5304
5351
 
5305
5352
  export { extractDbCause }
5306
5353
 
5354
+ /** The literal `_tag`s of a failure type. `any` contributes none (nothing can
5355
+ * be proven about it); `UnknownException` — Effect's wrapper for a failure it
5356
+ * could not type, e.g. `Effect.tryPromise` without `catch` — counts as
5357
+ * untagged, which is what it means. */
5358
+ declare type FailureTag<E> = 0 extends (1 & E) ? never : E extends {
5359
+ readonly _tag: infer T;
5360
+ } ? T extends 'UnknownException' ? never : T extends string ? T : never : never;
5361
+
5307
5362
  export declare interface FieldChange {
5308
5363
  readonly from: unknown;
5309
5364
  readonly to: unknown;
@@ -6660,8 +6715,18 @@ export declare const makeEventPublisher: (ctx: EventPublishContext) => EventPubl
6660
6715
 
6661
6716
  export declare const makeEventsFacade: (options: EventsFacadeOptions) => EventsAppContext;
6662
6717
 
6663
- /** Convenience: derive a key from a passphrase and build the cipher. */
6664
- export declare const makeFieldCipher: (passphrase: string) => FieldCipher;
6718
+ /**
6719
+ * Derive a key from a passphrase and build the cipher — with the keys a
6720
+ * ROTATION retires, when there are any.
6721
+ *
6722
+ * Writes use the current key; reads try the current one, then each previous
6723
+ * one. GCM authenticates, so a wrong key fails its tag rather than producing
6724
+ * garbage, and trying them in turn is safe. Without this, a key change made
6725
+ * every value written before it unreadable — measured: every sleeping or
6726
+ * suspended run of an `encrypted: true` workflow failed its replay with
6727
+ * `MalformedMessage`, and every `.encrypted()` column read failed.
6728
+ */
6729
+ export declare const makeFieldCipher: (passphrase: string, previous?: ReadonlyArray<string>) => FieldCipher;
6665
6730
 
6666
6731
  /** Build the fluent `select` / `update` / `delete` entry functions over a
6667
6732
  * backend + scope. Wired into `wrapStoreWithMixinBehaviour` so they hang
@@ -7103,6 +7168,16 @@ declare interface MemoryRywOptions {
7103
7168
  */
7104
7169
  export declare const memoryRywPositionStore: (options?: MemoryRywOptions) => RywPositionStore;
7105
7170
 
7171
+ /**
7172
+ * Merge a compression result's headers onto a response's own. `Vary` is a
7173
+ * LIST: a route that already varies (`Vary: Authorization, Cookie` — a
7174
+ * cached answer that differs per credential) keeps its fields and gains
7175
+ * `Accept-Encoding`. Spreading the two objects instead let the lower-case
7176
+ * `vary` replace the route's `Vary` (HTTP header names are case-insensitive),
7177
+ * and a shared cache could then serve one caller's answer to another.
7178
+ */
7179
+ export declare const mergeCompressionHeaders: <V>(own: Readonly<Record<string, V>>, compression: Readonly<Record<string, string>>) => Record<string, V | string>;
7180
+
7106
7181
  /**
7107
7182
  * Merge a name→value map into a `Cookie` header string, replacing same-named
7108
7183
  * pairs and preserving every other cookie the connection carries.
@@ -7847,6 +7922,10 @@ export declare interface OutboxFacadeDeps {
7847
7922
  readonly afterCommit?: (work: () => Promise<unknown>) => void;
7848
7923
  /** Wake the drain loop. */
7849
7924
  readonly nudge?: () => void;
7925
+ /** The declared handler's `maxAttempts` for an effect. The row carries its
7926
+ * attempt budget from the moment it is enqueued, so this is where a
7927
+ * handler's `maxAttempts` takes effect; an enqueue's own option wins. */
7928
+ readonly maxAttemptsOf?: (effect: string) => number | undefined;
7850
7929
  readonly now?: () => Date;
7851
7930
  }
7852
7931
 
@@ -8857,7 +8936,7 @@ export declare const recordTableAccess: (table: string, op: ObservedOp) => void;
8857
8936
 
8858
8937
  /** Feed a committed change into the process recorder (gated + loop-safe). The
8859
8938
  * serve paths call this from their `store.onChange` tap. */
8860
- export declare const recordTimelineEvent: (change: CdcChange & {
8939
+ export declare const recordTimelineEvent: (change: CdcChange & Pick<ChangeEvent, "oversized" | "netChange"> & {
8861
8940
  readonly tenantId?: string | null;
8862
8941
  }) => void;
8863
8942
 
@@ -10691,10 +10770,13 @@ export declare type ScheduleFireInterceptor = (next: () => Promise<void>, ctx: S
10691
10770
  * thing that silently did nothing. Same bridge a file-based migration's `up`
10692
10771
  * has carried since it shipped.
10693
10772
  *
10694
- * The app supplies its outbound HttpClient, including its tracing and SSRF
10695
- * policy. Other requirements must be provided by the handler.
10773
+ * The app supplies its outbound HttpClient (tracing and SSRF policy
10774
+ * included) AND the same service layer a mutation handler runs under —
10775
+ * plugin services such as `MailService`, the app's own layers — so a schedule
10776
+ * may `yield*` them. Both `voltro dev` and `voltro serve` build the runner
10777
+ * from that layer; the type is open on requirements for exactly that reason.
10696
10778
  */
10697
- export declare type ScheduleHandler = (ctx: ScheduleContext) => void | Promise<void> | Effect.Effect<unknown, unknown, HttpClient.HttpClient>;
10779
+ export declare type ScheduleHandler = (ctx: ScheduleContext) => void | Promise<void> | Effect.Effect<unknown, unknown, HttpClient.HttpClient | unknown>;
10698
10780
 
10699
10781
  /** What happens when a firing arrives while the previous run of the
10700
10782
  * same schedule is still in flight. */
@@ -11899,6 +11981,19 @@ export declare interface SubscriptionBackpressureOptions {
11899
11981
  readonly oversizedEventBytes: number;
11900
11982
  /** Query tag for logs + metrics. */
11901
11983
  readonly label: string;
11984
+ /**
11985
+ * The subscription's CRDT columns (plan 18), when its table has any. Its
11986
+ * deltas carry those cells as INCREMENTAL updates (`mergeCells`), so the
11987
+ * rows kept here fold them into the held cells (`merge`), and a coalesced
11988
+ * patch diffs them incrementally again (`incremental`). Without it a held
11989
+ * cell would become the last increment, and a coalesced patch would REPLACE
11990
+ * the client's whole text with it.
11991
+ */
11992
+ readonly crdt?: {
11993
+ readonly columns: ReadonlySet<string>;
11994
+ readonly merge: (column: string, held: unknown, update: unknown) => unknown;
11995
+ readonly incremental: (column: string, prevValue: unknown, nextValue: unknown) => unknown | undefined;
11996
+ };
11902
11997
  readonly now?: () => number;
11903
11998
  readonly warn?: (message: string, fields: Record<string, unknown>) => void;
11904
11999
  }
@@ -12159,6 +12254,9 @@ export declare const TERMINAL_RUN_STATUSES: ReadonlySet<string>;
12159
12254
  export declare type TimeBucket = 'minute' | 'hour' | 'day' | 'week' | 'month';
12160
12255
 
12161
12256
  export declare interface TimelineEvent {
12257
+ /** Preserves the store's warning that images are not original commit images. */
12258
+ readonly oversized?: ChangeEvent['oversized'];
12259
+ readonly netChange?: ChangeEvent['netChange'];
12162
12260
  /** Monotonic per-process sequence — the scrubber's x-axis. */
12163
12261
  readonly seq: number;
12164
12262
  /** Wall-clock ms when recorded. */
@@ -12192,13 +12290,18 @@ export declare class TimelineRecorder {
12192
12290
  private readonly mode;
12193
12291
  private readonly capacity;
12194
12292
  private readonly now;
12293
+ /** Identity of this bounded history; sequence numbers are only meaningful within it. */
12294
+ private historyId;
12295
+ get recorderId(): string;
12296
+ /** A proven delivery gap makes every earlier reconstruction unsafe. */
12297
+ invalidate(): void;
12195
12298
  private readonly ring;
12196
12299
  private seqCounter;
12197
12300
  constructor(mode?: TimelineMode, capacity?: number, now?: () => number);
12198
12301
  get enabled(): boolean;
12199
12302
  /** Record one change (assigns the next seq, redacts, applies the mode gate +
12200
12303
  * the no-feedback skip). Returns the assigned seq, or -1 when skipped. */
12201
- record(change: CdcChange & {
12304
+ record(change: CdcChange & Pick<ChangeEvent, 'oversized' | 'netChange'> & {
12202
12305
  readonly tenantId?: string | null;
12203
12306
  }): number;
12204
12307
  /** The highest seq recorded so far (the scrubber's "now"). */
@@ -12482,6 +12585,17 @@ export declare const tryClaimWakeup: (store: DataStore, ref: WakeupRef) => Promi
12482
12585
  * `_voltro_rebac_tuples`; an app whose relationships live in its own tables
12483
12586
  * (a `teamMembers` row, say) registers its own instead of copying data into a
12484
12587
  * framework table.
12588
+ *
12589
+ * Return `'missing'` when the resource itself does not exist for this caller:
12590
+ * the guard then refuses with the typed `NoSuchResource` instead of
12591
+ * `ScopeError`, so an id-route can answer "not found" before its executor runs.
12592
+ * The source is the only place that can know — an empty tuple list means "no
12593
+ * relation", never "no row", because inferring absence from it would tell any
12594
+ * caller which ids exist. Decide the disclosure yourself: answer `'missing'`
12595
+ * from a tenant-scoped read (a row in another tenant then reads as missing, not
12596
+ * as "exists, not yours"), and never for a resource the caller could not have
12597
+ * learnt about otherwise. An anonymous caller never receives it, whatever the
12598
+ * source answers.
12485
12599
  */
12486
12600
  export declare type TupleSource = (req: {
12487
12601
  readonly subjectId: string | null;
@@ -12527,7 +12641,7 @@ export declare type TupleSource = (req: {
12527
12641
  * legitimately have no request.
12528
12642
  */
12529
12643
  readonly load: DataLoader | undefined;
12530
- }) => Promise<ReadonlyArray<RelationTuple>> | ReadonlyArray<RelationTuple>;
12644
+ }) => Promise<ReadonlyArray<RelationTuple> | ResourceMissing> | ReadonlyArray<RelationTuple> | ResourceMissing;
12531
12645
 
12532
12646
  /** The mutation runner's key for opening the read-version map on a transaction
12533
12647
  * view it obtained from the dialect store directly. */
@@ -12546,6 +12660,32 @@ declare interface TypedUpsertOptions<T extends AnyWritableTable> {
12546
12660
  */
12547
12661
  export declare const unbindConnection: (clientId: number) => void;
12548
12662
 
12663
+ /**
12664
+ * The tagged failures an executor can produce that its procedure's wire union
12665
+ * does not carry.
12666
+ *
12667
+ * Such a failure does not reach the caller as itself. On a mutation or action
12668
+ * the server refuses to encode a tag its union cannot represent and sends
12669
+ * `InternalError` instead; on a query it arrives under a tag the client's typed
12670
+ * union does not know. Either way the error the author raised is not the error
12671
+ * the caller can match on — and before this check, widening a shared helper's
12672
+ * error type compiled at every call site while every one of them started
12673
+ * failing that way.
12674
+ *
12675
+ * UNTAGGED failures (`Error`, `unknown`) are not reported: they never claimed to
12676
+ * be a typed outcome, and the runtime treats them as defects by construction.
12677
+ *
12678
+ * Nor are the STORE's refusals (`StoreError`: `ConstraintViolation`,
12679
+ * `TenantScopeViolation`, …). The framework raises them, not the handler's
12680
+ * author, and what an undeclared one does is a documented contract: it reaches
12681
+ * the caller as `InternalError` carrying its own sentence; declare it to surface
12682
+ * it typed. Every `EffectStore` write carries the whole set in its failure
12683
+ * channel, so counting them made the check fire on every write executor —
12684
+ * measured on one app: 550 of 564 findings, burying the 14 that were the
12685
+ * app's own tags, which is what this check exists to find.
12686
+ */
12687
+ export declare type UndeclaredErrorTags<D extends ExecutorDescriptor, R> = Exclude<FailureTag<ExecutorFailure<R>>, FailureTag<ProcedureWireError<D>> | FailureTag<StoreError>>;
12688
+
12549
12689
  export declare class UndeclaredTableAccess extends Error {
12550
12690
  readonly table: string;
12551
12691
  readonly operation: string;
@@ -13213,11 +13353,10 @@ export declare interface WorkflowFacadeOptions {
13213
13353
  * Inspect HTTP + the `voltro workflows retry` CLI delegate to the same
13214
13354
  * implementation. */
13215
13355
  readonly retry?: (runId: string, options: WorkflowRetryOptions) => Promise<WorkflowRetryResult>;
13216
- /** Backs {@link WorkflowsAppContext.redrive}. Supplied by the CLI's facade
13217
- * builder, which owns the runs/steps store query + the cluster journal
13218
- * adapter. Inspect HTTP + `voltro workflows redrive` delegate to the same
13219
- * implementation. */
13220
- readonly redrive?: (runId: string) => Promise<WorkflowRedriveResult>;
13356
+ /** Shared resident-authorized restart command and receipt adapters. */
13357
+ readonly restart?: (command: WorkflowRestartCommand) => Promise<WorkflowRestartResult>;
13358
+ readonly readRestart?: (target: Pick<WorkflowRestartCommand, 'runId' | 'requestId'>) => Promise<WorkflowRestartObservation>;
13359
+ readonly withdrawRestart?: (command: WorkflowRestartCommand) => Promise<WorkflowRestartObservation>;
13221
13360
  /** Fired (fire-and-forget) right after a workflow is ENQUEUED — a start,
13222
13361
  * child, or run. The CLI wires this to a cross-replica "wake" broadcast so
13223
13362
  * the replica that OWNS the new run's shard polls immediately instead of
@@ -13395,16 +13534,6 @@ export declare interface WorkflowReadCtx {
13395
13534
  } | undefined;
13396
13535
  }
13397
13536
 
13398
- /** Result of {@link WorkflowsAppContext.redrive} — whether the failed run's
13399
- * durable journal was re-driven, how many failed step attempts were reset so
13400
- * they re-execute, and a `reason` when it declined (no journal / still
13401
- * running / already succeeded). */
13402
- export declare interface WorkflowRedriveResult {
13403
- readonly redriven: boolean;
13404
- readonly activitiesReset: number;
13405
- readonly reason: string | null;
13406
- }
13407
-
13408
13537
  /** Options for {@link WorkflowsAppContext.retry}. */
13409
13538
  export declare interface WorkflowRetryOptions {
13410
13539
  /** Persist once per deliberate retry and reuse after a lost response. */
@@ -13592,14 +13721,13 @@ export declare interface WorkflowsAppContext {
13592
13721
  retry(runId: string, options: WorkflowRetryOptions): Promise<WorkflowRetryResult>;
13593
13722
  /** Observe a durable retry intent without submitting another attempt. */
13594
13723
  readRetry(runId: string, requestId: string): Promise<WorkflowRetryObservation>;
13595
- /** Re-drive a terminally-`failed` run from the step it died on, reusing
13596
- * its durable journal — the counterpart to {@link retry} (fresh execution,
13597
- * empty journal) and to {@link resume} (which only re-drives a *suspended*
13598
- * run). Addressed by run id (`wfrun_…`). Completed steps replay from the
13599
- * journal; only the failed steps re-execute. Fix the downstream cause
13600
- * first, then redrive. Refuses a run that is not a not-yet-discarded
13601
- * failure. */
13602
- redrive(runId: string): Promise<WorkflowRedriveResult>;
13724
+ /** Restart a failed run with its recorded successful steps. Persist the request
13725
+ * ID and selection before submitting; a pending receipt is not engine entry. */
13726
+ restart(runId: string, options: Omit<WorkflowRestartCommand, 'runId'>): Promise<WorkflowRestartResult>;
13727
+ /** Read a saved restart request without dispatching work. */
13728
+ readRestart(runId: string, requestId: string): Promise<WorkflowRestartObservation>;
13729
+ /** Permanently fence an unreserved request. Accepted work is returned unchanged. */
13730
+ withdrawRestart(runId: string, options: Omit<WorkflowRestartCommand, 'runId'>): Promise<WorkflowRestartObservation>;
13603
13731
  }
13604
13732
 
13605
13733
  export declare interface WorkflowSignalTarget {
@@ -13751,3 +13879,10 @@ export declare const wrapStoreWithMixinBehaviour: (rawUnderlying: DataStore, ctx
13751
13879
  export declare const writeReplicaObservation: (store: DataStore, kind: ReplicaObservationKind, payload: unknown) => Promise<void>;
13752
13880
 
13753
13881
  export { }
13882
+
13883
+
13884
+ declare module '@voltro/protocol' {
13885
+ interface VoltroPluginErrors {
13886
+ readonly '@fixture/errors#RegisteredByPlugin': RegisteredByPlugin;
13887
+ }
13888
+ }