import type { BatchOperation } from '../../../storage/interface.ts'; import type { StartWorkflowOptions } from '../../types.ts'; import { type WorkflowHandle } from '../handles.ts'; import type { EngineInternals } from '../internals.ts'; import { type LifecycleCallbacks } from './shared.ts'; import { type BuildIdempotentStartOperations } from './start-commit.ts'; export declare function start(internals: EngineInternals, type: string, input: unknown, options: StartWorkflowOptions | undefined, callbacks: LifecycleCallbacks): Promise; export declare function startWorkflow(internals: EngineInternals, type: string, input: unknown, options: StartWorkflowOptions | undefined, additionalStartOperations: BatchOperation[] | undefined, callbacks: LifecycleCallbacks, buildIdempotentStartOperations?: BuildIdempotentStartOperations, /** * A pinned schedule's forward-looking revision commitment (WFT-20), * threaded from `ScheduleCallbacks.startWorkflow`'s own `revisionOverride` * parameter. When supplied, this call resolves and reserves EXACTLY this * revision (via {@link resolveAndReservePinnedExecutableRegistration}, * which enforces an exact-match check for an eager type rather than * silently falling back to whatever is active) instead of the ordinary * "whatever `resolveExecutableRegistration` currently resolves" * admission path, and the persisted `WorkflowState.revision` is this * value verbatim — never re-derived from `registeredCatalogRevisions`. * `undefined` (the default, every non-schedule start) is byte-for-byte * the pre-WFT-20 admission path. */ revisionOverride?: string, /** * Internal-only, never part of the public `StartOptions` type (WFT-95). * When truthy, `options.id` skips strict fresh-admission validation * (`assertValidWorkflowId`'s `.`/`..` rejection) and is instead validated * with the decode-compatible `assertDecodableWorkflowId`. This exists * ONLY to replay an id that was already durably accepted before strict * admission existed — never to let a genuinely fresh caller admit `.`/`..`. * * Set from exactly three internal call sites, all replaying an * already-persisted id rather than admitting a new one: * - `drainQueuedScheduleRun()` (via `ScheduledRunStartOptions.skipAdmissionIdCheck`, * threaded through `startScheduledRun()`), which restarts a schedule's * persisted `queuedRuns[].workflowId` — safe unconditionally (`true`), * since a queued run created after this fix was already validated as * non-`.`/`..` at schedule-admission time, so relaxing the check here * is a no-op for it and only matters for a historical pre-WFT-95 queued run. * - `retryFailedWorkflow()`'s checkpoint-absent fallback (`bulk-operations-retry.ts`), * which rebuilds an already-persisted, already-validated-at-the-time * `workflowId` from its stored input via `onTerminalConflict: 'start-new'`. * Passes the literal `'bulk-retry-only'` rather than `true` — see * {@link enforceReplayOnlyIdFence}'s doc comment for the TOCTOU race that * value fences: the retry's own confirmation read and * `resolveTerminalConflictForRestart`'s atomic read are not the same * read, so a concurrent purge under `ownership: 'workflow-lease'` can * leave nothing to purge-and-replace by the time this runs. * - `dispatchChildWorkflowStart()`'s crash-reattach retry, which passes * the literal `'reattach-only'` rather than `true` — see * {@link enforceReplayOnlyIdFence}'s doc comment for the same TOCTOU * race (this one only *speculatively* matched an existing record * before this call, unlike the schedule-drain site above). * * Every other caller (REST, JSON-RPC, direct `engine.start()`, * `engine.startOrSignal()`, a fresh `ctx.startChild()`) omits this * parameter and gets the strict check, because it is not part of * `StartOptions`/`StartWorkflowOptions` and therefore cannot be set from * any public surface. */ skipAdmissionIdCheck?: boolean | 'reattach-only' | 'bulk-retry-only'): Promise;