@zero-transfer/mft 0.4.0 → 0.4.6

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.
package/dist/index.d.mts CHANGED
@@ -394,7 +394,7 @@ interface TlsProfile {
394
394
  * hex form with or without colons. When present, the TLS handshake additionally requires the
395
395
  * leaf certificate's SHA-256 fingerprint to match one of these values.
396
396
  *
397
- * Not required for normal CA-trusted endpoints public CAs and `ca` bundles already gate
397
+ * Not required for normal CA-trusted endpoints - public CAs and `ca` bundles already gate
398
398
  * trust via `rejectUnauthorized`. Pinning is **recommended for production** when you control
399
399
  * the server and want defence-in-depth against rogue certificates issued by trusted CAs.
400
400
  *
@@ -833,7 +833,41 @@ interface TransferEngineOptions {
833
833
  /** Clock used for receipts and progress events. Defaults to `new Date()`. */
834
834
  now?: () => Date;
835
835
  }
836
- /** Executes transfer jobs and produces audit-friendly receipts. */
836
+ /**
837
+ * Executes transfer jobs and produces audit-friendly receipts.
838
+ *
839
+ * The engine is the lowest-level entry point in the transfer stack: it owns
840
+ * retry policy, attempt history, abort propagation, progress event
841
+ * normalization, and receipt construction. Most callers reach the engine
842
+ * indirectly through {@link runRoute}, {@link uploadFile}, {@link downloadFile},
843
+ * {@link copyBetween}, or {@link TransferQueue}; instantiate it directly when
844
+ * you need full control over execution semantics.
845
+ *
846
+ * @example Execute a single job with a custom executor
847
+ * ```ts
848
+ * import { TransferEngine, type TransferExecutor, type TransferJob } from "@zero-transfer/sdk";
849
+ *
850
+ * const engine = new TransferEngine();
851
+ *
852
+ * const executor: TransferExecutor = async ({ job, signal, onProgress }) => {
853
+ * onProgress?.({ jobId: job.id, bytesTransferred: 0 });
854
+ * // … perform the bytes here, honoring `signal` …
855
+ * return { jobId: job.id, bytesTransferred: 1234, completedAt: new Date() };
856
+ * };
857
+ *
858
+ * const job: TransferJob = {
859
+ * id: "manual-1",
860
+ * operation: "upload",
861
+ * source: { profile: localProfile, path: "./data.bin" },
862
+ * destination: { profile: s3Profile, path: "/data/data.bin" },
863
+ * };
864
+ *
865
+ * const receipt = await engine.execute(job, executor, {
866
+ * retry: { maxAttempts: 3, baseDelayMs: 250 },
867
+ * });
868
+ * console.log(receipt.attempts.length); // 1 on success
869
+ * ```
870
+ */
837
871
  declare class TransferEngine {
838
872
  private readonly now;
839
873
  /**
@@ -1416,9 +1450,41 @@ interface RunRouteOptions {
1416
1450
  /**
1417
1451
  * Executes an MFT route as a single transfer through the supplied client.
1418
1452
  *
1453
+ * Connects the source and destination profiles, runs the route's transfer
1454
+ * through the engine, and returns the resulting receipt. The friendly helpers
1455
+ * {@link uploadFile}, {@link downloadFile}, and {@link copyBetween} synthesize
1456
+ * routes and delegate to this function, so behaviour around retry, abort,
1457
+ * progress, timeout, and bandwidth limits is identical.
1458
+ *
1419
1459
  * @param options - Client, route, and optional engine/abort/retry hooks.
1420
1460
  * @returns Receipt produced by the underlying transfer engine.
1421
1461
  * @throws {@link ConfigurationError} When the route is disabled.
1462
+ *
1463
+ * @example Run a pre-built route with progress + retry
1464
+ * ```ts
1465
+ * import { createTransferClient, runRoute, type MftRoute } from "@zero-transfer/sdk";
1466
+ *
1467
+ * const route: MftRoute = {
1468
+ * id: "nightly-export",
1469
+ * operation: "copy",
1470
+ * source: {
1471
+ * path: "/exports/daily.csv",
1472
+ * profile: { host: "sftp.example.com", provider: "sftp", username: "etl" },
1473
+ * },
1474
+ * destination: {
1475
+ * path: "warehouse/daily.csv",
1476
+ * profile: { host: "warehouse", provider: "s3", s3: { region: "us-east-1" } },
1477
+ * },
1478
+ * };
1479
+ *
1480
+ * const receipt = await runRoute({
1481
+ * client,
1482
+ * route,
1483
+ * onProgress: (e) => console.log(`${e.bytesTransferred}/${e.totalBytes ?? "?"}`),
1484
+ * retry: { maxAttempts: 3, baseDelayMs: 500 },
1485
+ * });
1486
+ * console.log(`Job ${receipt.jobId} moved ${receipt.bytesTransferred} bytes…`);
1487
+ * ```
1422
1488
  */
1423
1489
  declare function runRoute(options: RunRouteOptions): Promise<TransferReceipt>;
1424
1490
 
@@ -1592,8 +1658,20 @@ interface ClientDiagnostics {
1592
1658
  /**
1593
1659
  * Returns a redaction-safe snapshot of the providers registered with a client.
1594
1660
  *
1661
+ * Use this when rendering a setup screen, generating a support bundle, or
1662
+ * asserting in tests that the expected provider factories were registered.
1663
+ *
1595
1664
  * @param client - Transfer client to inspect.
1596
1665
  * @returns Provider id and capability snapshot tuples.
1666
+ *
1667
+ * @example List registered providers
1668
+ * ```ts
1669
+ * import { summarizeClientDiagnostics } from "@zero-transfer/sdk";
1670
+ *
1671
+ * for (const { id, capabilities } of summarizeClientDiagnostics(client).providers) {
1672
+ * console.log(`${id}: streaming=${capabilities.readStream} resume=${capabilities.resumeDownload}`);
1673
+ * }
1674
+ * ```
1597
1675
  */
1598
1676
  declare function summarizeClientDiagnostics(client: TransferClient): ClientDiagnostics;
1599
1677
  /** Per-step duration measurements collected by {@link runConnectionDiagnostics}. */
@@ -1646,8 +1724,36 @@ interface RunConnectionDiagnosticsOptions {
1646
1724
  /**
1647
1725
  * Connects to a profile, captures capability and listing samples, and returns a redaction-safe report.
1648
1726
  *
1727
+ * Useful for connectivity "ping" pages, smoke tests, and bug reports. Secrets
1728
+ * in the profile are redacted via {@link redactConnectionProfile} before being
1729
+ * returned. The session is always disconnected before the function returns,
1730
+ * including when probes throw.
1731
+ *
1649
1732
  * @param options - Diagnostic probe options.
1650
1733
  * @returns Diagnostic report including timings and any captured error.
1734
+ *
1735
+ * @example Probe an SFTP connection
1736
+ * ```ts
1737
+ * import { runConnectionDiagnostics } from "@zero-transfer/sdk";
1738
+ *
1739
+ * const report = await runConnectionDiagnostics({
1740
+ * client,
1741
+ * profile: {
1742
+ * host: "sftp.example.com",
1743
+ * provider: "sftp",
1744
+ * username: "deploy",
1745
+ * ssh: { privateKey: { path: "./keys/id_ed25519" } },
1746
+ * },
1747
+ * listPath: "/uploads",
1748
+ * });
1749
+ *
1750
+ * if (!report.ok) {
1751
+ * console.error("connection failed:", report.error);
1752
+ * } else {
1753
+ * console.log(`connect=${report.timings.connectMs}ms list=${report.timings.listMs}ms`);
1754
+ * console.log(report.sample); // up to 5 entries from /uploads
1755
+ * }
1756
+ * ```
1651
1757
  */
1652
1758
  declare function runConnectionDiagnostics(options: RunConnectionDiagnosticsOptions): Promise<ConnectionDiagnosticsResult>;
1653
1759
 
@@ -1656,7 +1762,7 @@ interface ConnectionPoolOptions {
1656
1762
  /**
1657
1763
  * Maximum number of *idle* sessions retained per pool key.
1658
1764
  *
1659
- * Active leases are not counted against this limit the cap only applies
1765
+ * Active leases are not counted against this limit - the cap only applies
1660
1766
  * to sessions waiting in the pool. When more than `maxIdlePerKey` sessions
1661
1767
  * become idle simultaneously, the oldest ones are disconnected. Defaults
1662
1768
  * to `4`.
@@ -1754,8 +1860,29 @@ interface MemoryProviderOptions {
1754
1860
  /**
1755
1861
  * Creates a provider factory backed by deterministic in-memory fixture entries.
1756
1862
  *
1863
+ * Useful for tests and examples where you want a real `TransferSession` without
1864
+ * touching disk or the network. Entries are pre-seeded; mutations made through
1865
+ * the session are visible to subsequent operations on the same provider.
1866
+ *
1757
1867
  * @param options - Optional fixture entries to expose through the memory provider.
1758
1868
  * @returns Provider factory suitable for `createTransferClient({ providers: [...] })`.
1869
+ *
1870
+ * @example Seed entries and read them back
1871
+ * ```ts
1872
+ * import { createMemoryProviderFactory, createTransferClient } from "@zero-transfer/sdk";
1873
+ *
1874
+ * const client = createTransferClient({
1875
+ * providers: [createMemoryProviderFactory({
1876
+ * entries: [
1877
+ * { path: "/fixtures/hello.txt", content: "hello world" },
1878
+ * { path: "/fixtures/data.bin", content: new Uint8Array([1, 2, 3]) },
1879
+ * ],
1880
+ * })],
1881
+ * });
1882
+ *
1883
+ * const session = await client.connect({ host: "fixtures", provider: "memory" });
1884
+ * console.log(await session.fs.list("/fixtures"));
1885
+ * ```
1759
1886
  */
1760
1887
  declare function createMemoryProviderFactory(options?: MemoryProviderOptions): ProviderFactory;
1761
1888
 
@@ -2493,9 +2620,47 @@ interface TransferPlanSummary {
2493
2620
  /** Counts grouped by action. */
2494
2621
  actions: Record<string, number>;
2495
2622
  }
2496
- /** Creates a transfer plan from dry-run planning input. */
2623
+ /**
2624
+ * Creates a transfer plan from dry-run planning input.
2625
+ *
2626
+ * Plans are immutable, structured descriptions of intended work. Pair with
2627
+ * {@link createSyncPlan} or {@link createAtomicDeployPlan} for end-to-end
2628
+ * planning, or build steps by hand when you need full control. Pass the plan
2629
+ * to {@link createTransferJobsFromPlan} to materialize executable jobs.
2630
+ *
2631
+ * @example Build a plan with two upload steps and inspect it
2632
+ * ```ts
2633
+ * import { createTransferPlan, summarizeTransferPlan } from "@zero-transfer/sdk";
2634
+ *
2635
+ * const plan = createTransferPlan({
2636
+ * id: "manual-batch",
2637
+ * steps: [
2638
+ * { action: "upload", source: "./a.bin", destination: "/lake/a.bin", expectedBytes: 1024 },
2639
+ * { action: "upload", source: "./b.bin", destination: "/lake/b.bin", expectedBytes: 2048 },
2640
+ * ],
2641
+ * });
2642
+ *
2643
+ * console.table(summarizeTransferPlan(plan));
2644
+ * ```
2645
+ */
2497
2646
  declare function createTransferPlan(input: TransferPlanInput): TransferPlan;
2498
- /** Summarizes a transfer plan for diagnostics, previews, and tests. */
2647
+ /**
2648
+ * Summarizes a transfer plan for diagnostics, previews, and tests.
2649
+ *
2650
+ * Returns aggregate counts (total / executable / skipped / destructive),
2651
+ * total expected bytes, and a per-action histogram. Useful for printing a
2652
+ * one-line plan summary before executing or for asserting plan shape in
2653
+ * tests.
2654
+ *
2655
+ * @example Print a plan preview
2656
+ * ```ts
2657
+ * import { summarizeTransferPlan } from "@zero-transfer/sdk";
2658
+ *
2659
+ * const summary = summarizeTransferPlan(plan);
2660
+ * console.log(`${summary.executableSteps} steps, ${summary.totalExpectedBytes} bytes total`);
2661
+ * console.log("Actions:", summary.actions);
2662
+ * ```
2663
+ */
2499
2664
  declare function summarizeTransferPlan(plan: TransferPlan): TransferPlanSummary;
2500
2665
  /** Converts executable plan steps into transfer jobs while preserving order. */
2501
2666
  declare function createTransferJobsFromPlan(plan: TransferPlan): TransferJob[];
@@ -2572,7 +2737,41 @@ interface TransferQueueSummary {
2572
2737
  /** Failed queue items in queue order. */
2573
2738
  failures: TransferQueueItem[];
2574
2739
  }
2575
- /** Minimal transfer queue with concurrency, pause/resume, cancellation, and drain summaries. */
2740
+ /**
2741
+ * Minimal transfer queue with concurrency, pause/resume, cancellation, and drain summaries.
2742
+ *
2743
+ * Wrap a {@link TransferEngine} with a queue when you need to run many transfers
2744
+ * concurrently with bounded parallelism, observe per-job progress, or drive
2745
+ * a UI from a single source of truth. Items are FIFO; failures and successes
2746
+ * are surfaced via observers and in the final {@link TransferQueueSummary}.
2747
+ *
2748
+ * @example Run a batch of uploads with concurrency=4
2749
+ * ```ts
2750
+ * import {
2751
+ * TransferQueue,
2752
+ * createProviderTransferExecutor,
2753
+ * } from "@zero-transfer/sdk";
2754
+ *
2755
+ * const queue = new TransferQueue({
2756
+ * concurrency: 4,
2757
+ * executor: createProviderTransferExecutor({ client }),
2758
+ * onProgress: (e) => console.log(`${e.jobId}: ${e.bytesTransferred}`),
2759
+ * onError: (item, err) => console.error(`${item.job.id} failed`, err),
2760
+ * });
2761
+ *
2762
+ * for (const file of files) {
2763
+ * queue.enqueue({
2764
+ * id: file.name,
2765
+ * operation: "upload",
2766
+ * source: { profile: localProfile, path: file.path },
2767
+ * destination: { profile: s3Profile, path: `/lake/${file.name}` },
2768
+ * });
2769
+ * }
2770
+ *
2771
+ * const summary = await queue.drain();
2772
+ * console.log(`Completed ${summary.completed} / ${summary.total}`);
2773
+ * ```
2774
+ */
2576
2775
  declare class TransferQueue {
2577
2776
  private readonly engine;
2578
2777
  private readonly items;
@@ -2843,7 +3042,7 @@ interface DiffRemoteTreesOptions {
2843
3042
  * Compares two remote subtrees and produces an entry-level diff.
2844
3043
  *
2845
3044
  * Source and destination paths are walked independently; entries are then aligned by
2846
- * the relative path from each tree root. Directory equality is structural directories
3045
+ * the relative path from each tree root. Directory equality is structural - directories
2847
3046
  * are equal when their relative paths match and the entry types agree.
2848
3047
  *
2849
3048
  * @param source - Source-side remote file system.
@@ -2852,6 +3051,26 @@ interface DiffRemoteTreesOptions {
2852
3051
  * @param destinationPath - Destination-side root path being compared.
2853
3052
  * @param options - Optional comparison controls.
2854
3053
  * @returns Diff result containing entries and a summary.
3054
+ *
3055
+ * @example Diff two SFTP subtrees and feed the result into createSyncPlan
3056
+ * ```ts
3057
+ * import { createSyncPlan, diffRemoteTrees } from "@zero-transfer/sdk";
3058
+ *
3059
+ * const diff = await diffRemoteTrees(
3060
+ * srcSession.fs, "/exports",
3061
+ * dstSession.fs, "/exports",
3062
+ * { compareUniqueId: true },
3063
+ * );
3064
+ *
3065
+ * console.log(diff.summary); // { added, removed, changed, unchanged }
3066
+ *
3067
+ * const plan = createSyncPlan({
3068
+ * id: "exports-sync",
3069
+ * diff,
3070
+ * source: { provider: "sftp", rootPath: "/exports" },
3071
+ * destination: { provider: "sftp", rootPath: "/exports" },
3072
+ * });
3073
+ * ```
2855
3074
  */
2856
3075
  declare function diffRemoteTrees(source: RemoteFileSystem, sourcePath: string, destination: RemoteFileSystem, destinationPath: string, options?: DiffRemoteTreesOptions): Promise<RemoteTreeDiff>;
2857
3076
 
@@ -2923,6 +3142,31 @@ interface CreateSyncPlanOptions {
2923
3142
  * @param options - Inputs and policies that shape the plan.
2924
3143
  * @returns Transfer plan ready for `createTransferJobsFromPlan` or queue execution.
2925
3144
  * @throws {@link ConfigurationError} When `conflictPolicy: "error"` encounters a conflict.
3145
+ *
3146
+ * @example Mirror SFTP → S3 with deletes
3147
+ * ```ts
3148
+ * import {
3149
+ * createSyncPlan,
3150
+ * diffRemoteTrees,
3151
+ * summarizeTransferPlan,
3152
+ * } from "@zero-transfer/sdk";
3153
+ *
3154
+ * const diff = await diffRemoteTrees(
3155
+ * srcSession.fs, "/dist",
3156
+ * dstSession.fs, "/releases/current",
3157
+ * );
3158
+ *
3159
+ * const plan = createSyncPlan({
3160
+ * id: "release-mirror",
3161
+ * diff,
3162
+ * source: { provider: "sftp", rootPath: "/dist" },
3163
+ * destination: { provider: "s3", rootPath: "/releases/current" },
3164
+ * deletePolicy: "mirror",
3165
+ * conflictPolicy: "overwrite",
3166
+ * });
3167
+ *
3168
+ * console.table(summarizeTransferPlan(plan));
3169
+ * ```
2926
3170
  */
2927
3171
  declare function createSyncPlan(options: CreateSyncPlanOptions): TransferPlan;
2928
3172
 
@@ -3038,9 +3282,39 @@ interface CreateAtomicDeployPlanOptions {
3038
3282
  /**
3039
3283
  * Builds an {@link AtomicDeployPlan} that stages a release, swaps it live, and prunes old releases.
3040
3284
  *
3285
+ * The plan describes a blue/green-style deploy:
3286
+ * 1. Upload to a timestamped staging directory under `<destination>/.releases/`.
3287
+ * 2. Atomically swap the `current` symlink/rename to point at the new release.
3288
+ * 3. Optionally prune old releases beyond `retain`.
3289
+ *
3290
+ * No I/O is performed - the host executes the plan steps. Pair with
3291
+ * {@link createTransferPlan} or {@link createTransferJobsFromPlan} to execute.
3292
+ *
3041
3293
  * @param options - Inputs and policies that shape the deploy.
3042
3294
  * @returns Structured deploy plan ready for execution by the calling host.
3043
3295
  * @throws {@link ConfigurationError} When `retain` is less than `1` or the destination root is empty.
3296
+ *
3297
+ * @example Plan a release with rollback path
3298
+ * ```ts
3299
+ * import { createAtomicDeployPlan } from "@zero-transfer/sdk";
3300
+ *
3301
+ * const plan = createAtomicDeployPlan({
3302
+ * id: "web-2026-04-28",
3303
+ * source: { rootPath: "./dist" },
3304
+ * destination: {
3305
+ * profile: { host: "web1.example.com", provider: "sftp", username: "deploy" },
3306
+ * rootPath: "/srv/www",
3307
+ * },
3308
+ * retain: 5,
3309
+ * existingReleases: [
3310
+ * "/srv/www/.releases/2026-04-21T00-00-00Z",
3311
+ * "/srv/www/.releases/2026-04-14T00-00-00Z",
3312
+ * ],
3313
+ * });
3314
+ *
3315
+ * console.log(plan.swap); // staging → current rename
3316
+ * console.log(plan.prune); // releases scheduled for removal
3317
+ * ```
3044
3318
  */
3045
3319
  declare function createAtomicDeployPlan(options: CreateAtomicDeployPlanOptions): AtomicDeployPlan;
3046
3320
 
@@ -3233,6 +3507,12 @@ declare function joinRemotePath(...segments: string[]): string;
3233
3507
  */
3234
3508
  declare function basenameRemotePath(input: string): string;
3235
3509
 
3510
+ /**
3511
+ * Returns `true` when the file containing `import.meta.url` is the entry point
3512
+ * of the current Node.js process. Returns `false` outside Node.
3513
+ */
3514
+ declare function isMainModule(importMetaUrl: string): boolean;
3515
+
3236
3516
  /** Mutable in-memory registry of MFT routes. */
3237
3517
  declare class RouteRegistry {
3238
3518
  private readonly routes;
@@ -3634,9 +3914,33 @@ interface CreateWebhookAuditLogOptions {
3634
3914
  *
3635
3915
  * Entries whose `type` is not in `target.types` are silently dropped. `list()`
3636
3916
  * always returns an empty array because webhook deliveries are not buffered.
3917
+ * Payloads are HMAC-signed with `target.secret` (when provided) so receivers
3918
+ * can verify authenticity before acting on them.
3637
3919
  *
3638
3920
  * @param options - Webhook target plus optional retry/observer hooks.
3639
3921
  * @returns An audit log that delivers each `record` call to the webhook.
3922
+ *
3923
+ * @example Compose a webhook log with an in-memory log for local replay
3924
+ * ```ts
3925
+ * import {
3926
+ * InMemoryAuditLog,
3927
+ * composeAuditLogs,
3928
+ * createWebhookAuditLog,
3929
+ * } from "@zero-transfer/sdk";
3930
+ *
3931
+ * const memory = new InMemoryAuditLog();
3932
+ * const webhook = createWebhookAuditLog({
3933
+ * target: {
3934
+ * url: "https://hooks.example.com/zt",
3935
+ * secret: { env: "ZT_WEBHOOK_SECRET" },
3936
+ * types: ["transfer.success", "transfer.failure"],
3937
+ * },
3938
+ * onDelivery: ({ result }) => console.log("delivered", result.statusCode),
3939
+ * });
3940
+ *
3941
+ * const audit = composeAuditLogs(memory, webhook);
3942
+ * await audit.record({ type: "transfer.success", receipt });
3943
+ * ```
3640
3944
  */
3641
3945
  declare function createWebhookAuditLog(options: CreateWebhookAuditLogOptions): MftAuditLog;
3642
3946
 
@@ -3791,7 +4095,48 @@ interface MftSchedulerOptions {
3791
4095
  /** Timer/clock injection used by tests. */
3792
4096
  timer?: ScheduleTimerHooks;
3793
4097
  }
3794
- /** Runs routes on configured schedules. */
4098
+ /**
4099
+ * Runs routes on configured schedules.
4100
+ *
4101
+ * Subscribes to a {@link ScheduleRegistry}, computes the next fire time for
4102
+ * each schedule (cron or interval), and dispatches the matching route through
4103
+ * a runner of your choice (`runRoute` by default, or a wrapped runner for
4104
+ * approvals / rate limiting / circuit breaking). Observers fire on each cycle
4105
+ * for telemetry. Tests can inject a deterministic timer via `timer`.
4106
+ *
4107
+ * @example Wire a cron schedule with audit + approval
4108
+ * ```ts
4109
+ * import {
4110
+ * ApprovalRegistry,
4111
+ * InMemoryAuditLog,
4112
+ * MftScheduler,
4113
+ * RouteRegistry,
4114
+ * ScheduleRegistry,
4115
+ * createApprovalGate,
4116
+ * runRoute,
4117
+ * } from "@zero-transfer/sdk";
4118
+ *
4119
+ * const audit = new InMemoryAuditLog();
4120
+ * const approvals = new ApprovalRegistry();
4121
+ *
4122
+ * const scheduler = new MftScheduler({
4123
+ * client,
4124
+ * routes: new RouteRegistry([route]),
4125
+ * schedules: new ScheduleRegistry([
4126
+ * { id: "nightly", routeId: route.id, cron: "0 2 * * *" },
4127
+ * ]),
4128
+ * runner: createApprovalGate({
4129
+ * registry: approvals,
4130
+ * approvalId: ({ route }) => `release:${route.id}`,
4131
+ * runner: ({ client: c, route: r, signal }) => runRoute({ client: c, route: r, signal }),
4132
+ * }),
4133
+ * onResult: ({ receipt }) => audit.record({ type: "transfer.success", receipt }),
4134
+ * onError: ({ error }) => audit.record({ type: "transfer.failure", error }),
4135
+ * });
4136
+ *
4137
+ * scheduler.start();
4138
+ * ```
4139
+ */
3795
4140
  declare class MftScheduler {
3796
4141
  private readonly options;
3797
4142
  private readonly now;
@@ -3935,10 +4280,33 @@ interface CreateApprovalGateOptions {
3935
4280
  *
3936
4281
  * The returned runner creates an approval request, waits for resolution, and
3937
4282
  * dispatches the underlying runner only when the request is approved. Rejection
3938
- * surfaces an {@link ApprovalRejectedError}.
4283
+ * surfaces an {@link ApprovalRejectedError}. Pair with {@link MftScheduler} to
4284
+ * implement two-person rules and human-in-the-loop release flows.
3939
4285
  *
3940
4286
  * @param options - Registry, downstream runner, approval-id derivation, hooks.
3941
4287
  * @returns A {@link ScheduleRouteRunner} that gates execution behind approval.
4288
+ *
4289
+ * @example Two-person rule on a release route
4290
+ * ```ts
4291
+ * import {
4292
+ * ApprovalRegistry,
4293
+ * createApprovalGate,
4294
+ * runRoute,
4295
+ * } from "@zero-transfer/sdk";
4296
+ *
4297
+ * const approvals = new ApprovalRegistry();
4298
+ *
4299
+ * const gatedRunner = createApprovalGate({
4300
+ * registry: approvals,
4301
+ * approvalId: ({ route }) => `release:${route.id}:${Date.now()}`,
4302
+ * onRequested: (req) => notifyOnCallChannel(req),
4303
+ * runner: ({ client, route, signal }) => runRoute({ client, route, signal }),
4304
+ * });
4305
+ *
4306
+ * // Elsewhere, an authorized operator approves or rejects:
4307
+ * approvals.approve(approvalId, { actor: "alice@example.com" });
4308
+ * // approvals.reject(approvalId, { actor: "bob@example.com", reason: "hold release" });
4309
+ * ```
3942
4310
  */
3943
4311
  declare function createApprovalGate(options: CreateApprovalGateOptions): ScheduleRouteRunner;
3944
4312
 
@@ -3979,4 +4347,4 @@ declare function parseCronExpression(expression: string): CronExpression;
3979
4347
  */
3980
4348
  declare function nextCronFireAt(expression: CronExpression, from: Date, timezone?: "utc" | "local"): Date | undefined;
3981
4349
 
3982
- export { AbortError, type AgeRetentionPolicy, ApprovalRegistry, ApprovalRejectedError, type ApprovalRequest, type ApprovalStatus, type AtomicDeployActivateOperation, type AtomicDeployActivateStep, type AtomicDeployPlan, type AtomicDeployPruneStep, type AtomicDeployStrategy, type AuthenticationCapability, AuthenticationError, AuthorizationError, type BandwidthSleep, type BandwidthThrottle, type BandwidthThrottleOptions, type Base64EnvSecretSource, type BuiltInProviderId, CLASSIC_PROVIDER_IDS, type CapabilitySet, type ChecksumCapability, type ClassicProviderId, type ClientDiagnostics, type CompareRemoteManifestsOptions, ConfigurationError, type ConnectionDiagnosticTimings, type ConnectionDiagnosticsResult, ConnectionError, type ConnectionPoolOptions, type ConnectionProfile, type ConventionEndpoint, type CopyBetweenOptions, type CountRetentionPolicy, type CreateApprovalGateOptions, type CreateAtomicDeployPlanOptions, type CreateInboxRouteOptions, type CreateOutboxRouteOptions, type CreateRemoteBrowserOptions, type CreateRemoteManifestOptions, type CreateSyncPlanOptions, type CreateWebhookAuditLogOptions, type CronExpression, type CronField, type CronScheduleTrigger, DEFAULT_FAILED_SUBDIR, DEFAULT_PROCESSED_SUBDIR, type DiffRemoteTreesOptions, type DispatchWebhookOptions, type DispatchWebhookResult, type DownloadFileOptions, type EnvSecretSource, type EvaluateRetentionOptions, type FileSecretSource, type FileZillaSite, type FriendlyTransferOptions, type FtpReplyErrorInput, type ImportFileZillaSitesResult, type ImportOpenSshConfigOptions, type ImportOpenSshConfigResult, type ImportWinScpSessionsResult, InMemoryAuditLog, type IntervalScheduleTrigger, type JsonlWriter, type KnownHostsEntry, type KnownHostsMarker, type ListOptions, type LocalProviderOptions, type LogLevel, type LogRecord, type LogRecordInput, type LoggerMethod, type MemoryProviderEntry, type MemoryProviderOptions, type MetadataCapability, type MftAuditEntry, type MftAuditEntryType, type MftAuditLog, type MftInboxConvention, type MftOutboxConvention, type MftRoute, type MftRouteEndpoint, type MftRouteFilter, type MftRouteOperation, type MftSchedule, type MftScheduleTrigger, MftScheduler, type MftSchedulerOptions, type MkdirOptions, type OAuthAccessToken, type OAuthRefreshCallback, type OAuthTokenSecretSourceOptions, type OpenSshConfigEntry, ParseError, PathAlreadyExistsError, PathNotFoundError, PermissionDeniedError, type PooledTransferClient, type ProgressEventInput, ProtocolError, type AuthenticationCapability as ProviderAuthenticationCapability, type CapabilitySet as ProviderCapabilities, type ChecksumCapability as ProviderChecksumCapability, type ProviderFactory, type ProviderId, type MetadataCapability as ProviderMetadataCapability, ProviderRegistry, type ProviderSelection, type ProviderTransferEndpointRole, type ProviderTransferExecutorOptions, type ProviderTransferOperations, type ProviderTransferReadRequest, type ProviderTransferReadResult, type ProviderTransferRequest, type ProviderTransferSessionResolver, type ProviderTransferSessionResolverInput, type ProviderTransferWriteRequest, type ProviderTransferWriteResult, REDACTED, REMOTE_MANIFEST_FORMAT_VERSION, type RemoteBreadcrumb, type RemoteBrowser, type RemoteBrowserFilter, type RemoteBrowserSnapshot, type RemoteEntry, type RemoteEntrySortKey, type RemoteEntrySortOrder, type RemoteEntryType, type RemoteFileAdapter, type RemoteFileEndpoint, type RemoteFileSystem, type RemoteManifest, type RemoteManifestEntry, type RemotePermissions, type RemoteProtocol, type RemoteStat, type RemoteTreeDiff, type RemoteTreeDiffEntry, type RemoteTreeDiffReason, type RemoteTreeDiffStatus, type RemoteTreeDiffSummary, type RemoteTreeEntry, type RemoteTreeFilter, type RemoveOptions, type RenameOptions, type ResolveSecretOptions, type ResolvedConnectionProfile, type ResolvedOpenSshHost, type ResolvedSshProfile, type ResolvedTlsProfile, type RetentionEvaluation, type RetentionPolicy, type RmdirOptions, RouteRegistry, type RunConnectionDiagnosticsOptions, type RunRouteOptions, ScheduleRegistry, type ScheduleRouteRunner, type ScheduleTimerHooks, type SecretProvider, type SecretSource, type SecretValue, type SpecializedErrorDetails, type SshAgentSource, type SshAlgorithms, type SshKeyboardInteractiveChallenge, type SshKeyboardInteractiveHandler, type SshKeyboardInteractivePrompt, type SshKnownHostsSource, type SshProfile, type SshSocketFactory, type SshSocketFactoryContext, type StatOptions, type SyncConflictPolicy, type SyncDeletePolicy, type SyncDirection, type SyncEndpointInput, TimeoutError, type TlsProfile, type TlsSecretSource, type TransferAttempt, type TransferAttemptError, type TransferBandwidthLimit, type TransferByteRange, TransferClient, type TransferClientOptions, type TransferDataChunk, type TransferDataSource, type TransferEndpoint, TransferEngine, type TransferEngineExecuteOptions, type TransferEngineOptions, TransferError, type TransferExecutionContext, type TransferExecutionResult, type TransferExecutor, type TransferJob, type TransferOperation, type TransferPlan, type TransferPlanAction, type TransferPlanInput, type TransferPlanStep, type TransferPlanSummary, type TransferProgressEvent, type TransferProvider, TransferQueue, type TransferQueueExecutorResolver, type TransferQueueItem, type TransferQueueItemStatus, type TransferQueueOptions, type TransferQueueRunOptions, type TransferQueueSummary, type TransferReceipt, type TransferResult, type TransferResultInput, type TransferRetryDecisionInput, type TransferRetryPolicy, type TransferSession, type TransferTimeoutPolicy, type TransferVerificationResult, UnsupportedFeatureError, type UploadFileOptions, type ValueSecretSource, VerificationError, type WalkRemoteTreeOptions, type WebhookRetryPolicy, type WebhookSignature, type WebhookTarget, type WinScpSession, ZeroTransfer, type ZeroTransferCapabilities, ZeroTransferError, type ZeroTransferErrorDetails, type ZeroTransferLogger, type ZeroTransferOptions, assertSafeFtpArgument, basenameRemotePath, buildRemoteBreadcrumbs, compareRemoteManifests, composeAuditLogs, copyBetween, createApprovalGate, createAtomicDeployPlan, createBandwidthThrottle, createInboxRoute, createJsonlAuditLog, createLocalProviderFactory, createMemoryProviderFactory, createOAuthTokenSecretSource, createOutboxRoute, createPooledTransferClient, createProgressEvent, createProviderTransferExecutor, createRemoteBrowser, createRemoteManifest, createSyncPlan, createTransferClient, createTransferJobsFromPlan, createTransferPlan, createTransferResult, createWebhookAuditLog, diffRemoteTrees, dispatchWebhook, downloadFile, emitLog, errorFromFtpReply, evaluateRetention, filterRemoteEntries, freezeReceipt, importFileZillaSites, importOpenSshConfig, importWinScpSessions, inboxFailedPath, inboxProcessedPath, isClassicProviderId, isSensitiveKey, joinRemotePath, matchKnownHosts, matchKnownHostsEntry, nextCronFireAt, nextScheduleFireAt, noopLogger, normalizeRemotePath, parentRemotePath, parseCronExpression, parseKnownHosts, parseOpenSshConfig, parseRemoteManifest, redactCommand, redactConnectionProfile, redactObject, redactSecretSource, redactValue, resolveConnectionProfileSecrets, resolveOpenSshHost, resolveProviderId, resolveSecret, runConnectionDiagnostics, runRoute, serializeRemoteManifest, signWebhookPayload, sortRemoteEntries, summarizeClientDiagnostics, summarizeError, summarizeTransferPlan, throttleByteIterable, uploadFile, validateConnectionProfile, validateSchedule, walkRemoteTree };
4350
+ export { AbortError, type AgeRetentionPolicy, ApprovalRegistry, ApprovalRejectedError, type ApprovalRequest, type ApprovalStatus, type AtomicDeployActivateOperation, type AtomicDeployActivateStep, type AtomicDeployPlan, type AtomicDeployPruneStep, type AtomicDeployStrategy, type AuthenticationCapability, AuthenticationError, AuthorizationError, type BandwidthSleep, type BandwidthThrottle, type BandwidthThrottleOptions, type Base64EnvSecretSource, type BuiltInProviderId, CLASSIC_PROVIDER_IDS, type CapabilitySet, type ChecksumCapability, type ClassicProviderId, type ClientDiagnostics, type CompareRemoteManifestsOptions, ConfigurationError, type ConnectionDiagnosticTimings, type ConnectionDiagnosticsResult, ConnectionError, type ConnectionPoolOptions, type ConnectionProfile, type ConventionEndpoint, type CopyBetweenOptions, type CountRetentionPolicy, type CreateApprovalGateOptions, type CreateAtomicDeployPlanOptions, type CreateInboxRouteOptions, type CreateOutboxRouteOptions, type CreateRemoteBrowserOptions, type CreateRemoteManifestOptions, type CreateSyncPlanOptions, type CreateWebhookAuditLogOptions, type CronExpression, type CronField, type CronScheduleTrigger, DEFAULT_FAILED_SUBDIR, DEFAULT_PROCESSED_SUBDIR, type DiffRemoteTreesOptions, type DispatchWebhookOptions, type DispatchWebhookResult, type DownloadFileOptions, type EnvSecretSource, type EvaluateRetentionOptions, type FileSecretSource, type FileZillaSite, type FriendlyTransferOptions, type FtpReplyErrorInput, type ImportFileZillaSitesResult, type ImportOpenSshConfigOptions, type ImportOpenSshConfigResult, type ImportWinScpSessionsResult, InMemoryAuditLog, type IntervalScheduleTrigger, type JsonlWriter, type KnownHostsEntry, type KnownHostsMarker, type ListOptions, type LocalProviderOptions, type LogLevel, type LogRecord, type LogRecordInput, type LoggerMethod, type MemoryProviderEntry, type MemoryProviderOptions, type MetadataCapability, type MftAuditEntry, type MftAuditEntryType, type MftAuditLog, type MftInboxConvention, type MftOutboxConvention, type MftRoute, type MftRouteEndpoint, type MftRouteFilter, type MftRouteOperation, type MftSchedule, type MftScheduleTrigger, MftScheduler, type MftSchedulerOptions, type MkdirOptions, type OAuthAccessToken, type OAuthRefreshCallback, type OAuthTokenSecretSourceOptions, type OpenSshConfigEntry, ParseError, PathAlreadyExistsError, PathNotFoundError, PermissionDeniedError, type PooledTransferClient, type ProgressEventInput, ProtocolError, type AuthenticationCapability as ProviderAuthenticationCapability, type CapabilitySet as ProviderCapabilities, type ChecksumCapability as ProviderChecksumCapability, type ProviderFactory, type ProviderId, type MetadataCapability as ProviderMetadataCapability, ProviderRegistry, type ProviderSelection, type ProviderTransferEndpointRole, type ProviderTransferExecutorOptions, type ProviderTransferOperations, type ProviderTransferReadRequest, type ProviderTransferReadResult, type ProviderTransferRequest, type ProviderTransferSessionResolver, type ProviderTransferSessionResolverInput, type ProviderTransferWriteRequest, type ProviderTransferWriteResult, REDACTED, REMOTE_MANIFEST_FORMAT_VERSION, type RemoteBreadcrumb, type RemoteBrowser, type RemoteBrowserFilter, type RemoteBrowserSnapshot, type RemoteEntry, type RemoteEntrySortKey, type RemoteEntrySortOrder, type RemoteEntryType, type RemoteFileAdapter, type RemoteFileEndpoint, type RemoteFileSystem, type RemoteManifest, type RemoteManifestEntry, type RemotePermissions, type RemoteProtocol, type RemoteStat, type RemoteTreeDiff, type RemoteTreeDiffEntry, type RemoteTreeDiffReason, type RemoteTreeDiffStatus, type RemoteTreeDiffSummary, type RemoteTreeEntry, type RemoteTreeFilter, type RemoveOptions, type RenameOptions, type ResolveSecretOptions, type ResolvedConnectionProfile, type ResolvedOpenSshHost, type ResolvedSshProfile, type ResolvedTlsProfile, type RetentionEvaluation, type RetentionPolicy, type RmdirOptions, RouteRegistry, type RunConnectionDiagnosticsOptions, type RunRouteOptions, ScheduleRegistry, type ScheduleRouteRunner, type ScheduleTimerHooks, type SecretProvider, type SecretSource, type SecretValue, type SpecializedErrorDetails, type SshAgentSource, type SshAlgorithms, type SshKeyboardInteractiveChallenge, type SshKeyboardInteractiveHandler, type SshKeyboardInteractivePrompt, type SshKnownHostsSource, type SshProfile, type SshSocketFactory, type SshSocketFactoryContext, type StatOptions, type SyncConflictPolicy, type SyncDeletePolicy, type SyncDirection, type SyncEndpointInput, TimeoutError, type TlsProfile, type TlsSecretSource, type TransferAttempt, type TransferAttemptError, type TransferBandwidthLimit, type TransferByteRange, TransferClient, type TransferClientOptions, type TransferDataChunk, type TransferDataSource, type TransferEndpoint, TransferEngine, type TransferEngineExecuteOptions, type TransferEngineOptions, TransferError, type TransferExecutionContext, type TransferExecutionResult, type TransferExecutor, type TransferJob, type TransferOperation, type TransferPlan, type TransferPlanAction, type TransferPlanInput, type TransferPlanStep, type TransferPlanSummary, type TransferProgressEvent, type TransferProvider, TransferQueue, type TransferQueueExecutorResolver, type TransferQueueItem, type TransferQueueItemStatus, type TransferQueueOptions, type TransferQueueRunOptions, type TransferQueueSummary, type TransferReceipt, type TransferResult, type TransferResultInput, type TransferRetryDecisionInput, type TransferRetryPolicy, type TransferSession, type TransferTimeoutPolicy, type TransferVerificationResult, UnsupportedFeatureError, type UploadFileOptions, type ValueSecretSource, VerificationError, type WalkRemoteTreeOptions, type WebhookRetryPolicy, type WebhookSignature, type WebhookTarget, type WinScpSession, ZeroTransfer, type ZeroTransferCapabilities, ZeroTransferError, type ZeroTransferErrorDetails, type ZeroTransferLogger, type ZeroTransferOptions, assertSafeFtpArgument, basenameRemotePath, buildRemoteBreadcrumbs, compareRemoteManifests, composeAuditLogs, copyBetween, createApprovalGate, createAtomicDeployPlan, createBandwidthThrottle, createInboxRoute, createJsonlAuditLog, createLocalProviderFactory, createMemoryProviderFactory, createOAuthTokenSecretSource, createOutboxRoute, createPooledTransferClient, createProgressEvent, createProviderTransferExecutor, createRemoteBrowser, createRemoteManifest, createSyncPlan, createTransferClient, createTransferJobsFromPlan, createTransferPlan, createTransferResult, createWebhookAuditLog, diffRemoteTrees, dispatchWebhook, downloadFile, emitLog, errorFromFtpReply, evaluateRetention, filterRemoteEntries, freezeReceipt, importFileZillaSites, importOpenSshConfig, importWinScpSessions, inboxFailedPath, inboxProcessedPath, isClassicProviderId, isMainModule, isSensitiveKey, joinRemotePath, matchKnownHosts, matchKnownHostsEntry, nextCronFireAt, nextScheduleFireAt, noopLogger, normalizeRemotePath, parentRemotePath, parseCronExpression, parseKnownHosts, parseOpenSshConfig, parseRemoteManifest, redactCommand, redactConnectionProfile, redactObject, redactSecretSource, redactValue, resolveConnectionProfileSecrets, resolveOpenSshHost, resolveProviderId, resolveSecret, runConnectionDiagnostics, runRoute, serializeRemoteManifest, signWebhookPayload, sortRemoteEntries, summarizeClientDiagnostics, summarizeError, summarizeTransferPlan, throttleByteIterable, uploadFile, validateConnectionProfile, validateSchedule, walkRemoteTree };