@dudousxd/nestjs-durable 0.50.0 → 0.52.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.
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { WorkflowCtx, SearchAttributes, WorkflowClass, StandardSchemaV1, StepError, OnErrorInput, WorkflowRef, SingletonConfig, ConcurrencyConfig, SearchAttributesSchema, StateStore, Transport, NamedTransport, ControlPlane, StalledRunInfo, ScheduledWorkflow, RetentionPolicy, QueueConfig, AdmissionBackend, WorkflowInputOf, StartOptions, RunResult, RunGateway, WorkflowEngine, EntityHandler, DurableTopology, RunDetailOptions, RunDetail, FanPageQuery, FanPage, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, GroupHealth, RunWaiting, EngineEvent, RunRequest, RunReply, StepInvocation, WorkflowRun, TenantEvent } from '@dudousxd/nestjs-durable-core';
2
- export { AttributeFilter, DynamicWorkflowCtx, EngineEvent, InferSearchAttributes, OnErrorInput, RunDetail, RunGateway, RunListItem, RunQuery, RunStatus, RunWaiting, SearchAttributes, SearchAttributesSchema, StepCheckpoint, StepEvent, StepLogger, WorkflowCtx, WorkflowEngine, WorkflowHandler, WorkflowRun, readSearchAttributes } from '@dudousxd/nestjs-durable-core';
1
+ import { WorkflowCtx, SearchAttributes, WorkflowClass, StandardSchemaV1, StepError, OnErrorInput, WorkflowRef, SingletonConfig, ConcurrencyConfig, SearchAttributesSchema, StateStore, Transport, NamedTransport, ControlPlane, StalledRunInfo, ScheduledWorkflow, RetentionPolicy, QueueConfig, AdmissionBackend, TenantVerifier, TenantTokenSource, WorkflowInputOf, StartOptions, RunResult, RunGateway, WorkflowEngine, EntityHandler, DurableTopology, RunDetailOptions, RunDetail, FanPageQuery, FanPage, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, GroupHealth, RunWaiting, EngineEvent, RunRequest, RunReply, StepInvocation, WorkflowRun, TenantEvent } from '@dudousxd/nestjs-durable-core';
2
+ export { AttributeFilter, DynamicWorkflowCtx, EngineEvent, InferSearchAttributes, OnErrorInput, RunDetail, RunGateway, RunListItem, RunQuery, RunSchedulesOptions, RunStatus, RunWaiting, ScheduledWorkflow, SearchAttributes, SearchAttributesSchema, StepCheckpoint, StepEvent, StepLogger, TenantTokenSource, TenantVerifier, VerifiedTenant, WorkflowCtx, WorkflowEngine, WorkflowHandler, WorkflowRun, hmacTenantVerifier, prevCronFireMs, readSearchAttributes, runSchedules, scheduleRunIdAt, scheduledRunId, signTenantToken } from '@dudousxd/nestjs-durable-core';
3
3
  import { z } from 'zod';
4
4
  import { ConcurrencyOption, StartRunDeps, RunRedisWorkerOptions, RunningWorker, DurableWorkerRuntime } from '@dudousxd/durable-worker';
5
5
  import { DynamicModule, InjectionToken, OnModuleInit, OnApplicationBootstrap, OnApplicationShutdown, Provider } from '@nestjs/common';
@@ -242,14 +242,16 @@ interface WorkflowOptions {
242
242
  inputSchema?: IoSchema;
243
243
  /**
244
244
  * A custom check at `start` (throw to reject) for a rule a schema can't express — a cross-field
245
- * invariant, an async lookup. It sees the input as it was sent, and runs after `input` parses.
245
+ * invariant, an async lookup. It runs after `input` parses and receives the parsed value (the input
246
+ * as sent when there is no `input` schema).
246
247
  */
247
248
  validateInput?: (input: unknown) => void | Promise<void>;
248
249
  /**
249
250
  * Validate this workflow's {@link WorkflowCtx.upsertSearchAttributes} writes against a **Standard
250
251
  * Schema** (https://standardschema.dev — zod 3.24+, valibot, arktype, …). `ctx.upsertSearchAttributes`
251
252
  * validates the MERGED result (existing attributes shallow-merged with the patch) on every call —
252
- * an invalid merge throws, naming this workflow, the offending key(s), and the schema's issues. The
253
+ * an invalid merge throws a `SchemaValidationError` (code `schema_validation`) naming this workflow,
254
+ * with the schema's issues. The
253
255
  * schema's inferred output must be search-attribute-shaped (flat `string`/`number`/`boolean` values
254
256
  * only) — a schema whose output has a nested object/array is a compile-time error here. Omit for
255
257
  * the prior unvalidated behavior.
@@ -788,6 +790,26 @@ interface DurableModuleOptions {
788
790
  /** Timeout for a thin worker's `RunGateway` round-trip over `transport` before it rejects. Defaults
789
791
  * to 10_000ms inside `ProxyRunGateway`. Ignored for an operator (bound to `StoreRunGateway`). */
790
792
  runGatewayTimeoutMs?: number;
793
+ /**
794
+ * **Operator.** Verifies the signed tenant token a store-less tenant worker presents in the wire
795
+ * `tenant` field of every run request and start-run message, and DERIVES the tenant from it,
796
+ * discarding the wire claim. An invalid, tampered or absent token is rejected: a run request gets
797
+ * an `unauthorized` error reply, a start-run creates nothing. Use `hmacTenantVerifier(secret)`
798
+ * (tokens minted by `signTenantToken`, wire-compatible with Agora) or supply your own.
799
+ *
800
+ * Optional. Absent: the wire `tenant` is trusted verbatim (prefix/network isolation only), exactly
801
+ * as before. An explicit `topology: { role: 'control-plane' }` without a verifier logs a warning
802
+ * at boot; a plain operator (`store` + `transport`, no `topology`) boots silently.
803
+ */
804
+ verifyTenant?: TenantVerifier;
805
+ /**
806
+ * **Tenant worker.** The signed token (see `signTenantToken`) this worker presents, verbatim, in
807
+ * the `tenant` field of every run request (`ProxyRunGateway`) and start-run (`engine.start`), so
808
+ * an operator with {@link verifyTenant} can authenticate it. A string, or a function called before
809
+ * every request (rotation, short-lived tokens). Optional: absent, the raw {@link partition} is
810
+ * sent, as before. Live-tail stays keyed by the partition, never the token.
811
+ */
812
+ tenantToken?: TenantTokenSource;
791
813
  /**
792
814
  * An explicit preset that NAMES the deployment role instead of leaving it to `store`/`connection`
793
815
  * inference, and VALIDATES the axes that are otherwise only prose (see the interface doc's role
@@ -1089,13 +1111,29 @@ declare class ProxyRunGateway implements RunGateway {
1089
1111
  private readonly tenant;
1090
1112
  private readonly timeoutMs;
1091
1113
  private readonly capabilityTtlMs;
1114
+ /**
1115
+ * The tenant's signed token (see `signTenantToken`), presented VERBATIM in the `tenant` field of
1116
+ * every {@link RunRequest} so an operator with `verifyTenant` can authenticate it and derive the
1117
+ * tenant from it. A function is called before every request (rotation / short-lived tokens).
1118
+ * Omit to send the raw `tenant` (prefix/network isolation only). The live-tail channel always
1119
+ * stays keyed by `tenant`, never the token: the operator republishes by the run's namespace.
1120
+ */
1121
+ private readonly tenantToken?;
1092
1122
  private readonly pending;
1093
1123
  /** Verb → when to ask the control plane for it again, after it answered that it does not know it.
1094
1124
  * During a rolling upgrade the control plane is several pods of mixed versions behind one queue,
1095
1125
  * and a reply does not say which pod sent it, so the whole control plane is assumed old until the
1096
1126
  * entry expires. */
1097
1127
  private readonly unsupportedUntil;
1098
- constructor(transport: Transport, tenant: string, timeoutMs?: number, capabilityTtlMs?: number);
1128
+ constructor(transport: Transport, tenant: string, timeoutMs?: number, capabilityTtlMs?: number,
1129
+ /**
1130
+ * The tenant's signed token (see `signTenantToken`), presented VERBATIM in the `tenant` field of
1131
+ * every {@link RunRequest} so an operator with `verifyTenant` can authenticate it and derive the
1132
+ * tenant from it. A function is called before every request (rotation / short-lived tokens).
1133
+ * Omit to send the raw `tenant` (prefix/network isolation only). The live-tail channel always
1134
+ * stays keyed by `tenant`, never the token: the operator republishes by the run's namespace.
1135
+ */
1136
+ tenantToken?: TenantTokenSource | undefined);
1099
1137
  private handleReply;
1100
1138
  private request;
1101
1139
  topology(): DurableTopology;
@@ -1163,6 +1201,22 @@ interface RunRequestTransport {
1163
1201
  onRunRequest(handler: (msg: RunRequest) => Promise<void>): void;
1164
1202
  publishRunReply(reply: RunReply): Promise<void>;
1165
1203
  }
1204
+ /** Options for {@link RunRequestResponder}. */
1205
+ interface RunRequestResponderOptions {
1206
+ /**
1207
+ * Verifies the signed token a tenant presents in the wire `tenant` field and DERIVES the real
1208
+ * tenant from it (see `hmacTenantVerifier`). Present: an invalid, tampered or absent token is
1209
+ * rejected with an `unauthorized` error reply and the wire claim is discarded in favour of the
1210
+ * verified tenant. Absent: the wire `tenant` is trusted verbatim (prefix/network isolation only).
1211
+ */
1212
+ verifyTenant?: TenantVerifier | undefined;
1213
+ /**
1214
+ * Warn at construction when no {@link verifyTenant} is set. Default `true`. `DurableModule` passes
1215
+ * `true` only for an explicit `topology: { role: 'control-plane' }`, so a plain operator app that
1216
+ * never serves tenants boots silently.
1217
+ */
1218
+ warnWithoutVerifier?: boolean | undefined;
1219
+ }
1166
1220
  /**
1167
1221
  * Operator-side consumer of a tenant's {@link RunRequest}s: answers each one against a
1168
1222
  * `RunGateway`, enforcing the tenant boundary before touching the run. For every runId-bearing
@@ -1171,11 +1225,17 @@ interface RunRequestTransport {
1171
1225
  * verb, so a tenant can never read or act on another tenant's run. `listRuns` is scoped by
1172
1226
  * overwriting the query's `namespace` with the requester's tenant, ignoring whatever the client
1173
1227
  * sent. This is the security boundary of the tenant run gateway — do not weaken it.
1228
+ *
1229
+ * With {@link RunRequestResponderOptions.verifyTenant}, every request is authenticated FIRST: the
1230
+ * wire `tenant` is treated as a signed token, the real tenant is derived from it, and an invalid
1231
+ * token short-circuits into an `unauthorized` error reply before any run is touched. A verifier
1232
+ * that throws becomes an error reply too.
1174
1233
  */
1175
1234
  declare class RunRequestResponder {
1176
1235
  private readonly transport;
1177
1236
  private readonly gateway;
1178
- constructor(transport: RunRequestTransport, gateway: RunGateway);
1237
+ private readonly verifyTenant;
1238
+ constructor(transport: RunRequestTransport, gateway: RunGateway, options?: RunRequestResponderOptions);
1179
1239
  /** Register the consumer on the transport. Each request is answered independently; a handler
1180
1240
  * failure never throws back into the transport (errors are captured into an error reply). */
1181
1241
  start(): void;
@@ -1373,4 +1433,4 @@ declare class WorkflowService {
1373
1433
  }): Promise<number>;
1374
1434
  }
1375
1435
 
1376
- export { CONTEXT_ACCESSOR, type ContextAccessor, type ContextStore, DEAD_LETTER_METADATA, DURABLE_STEP_METADATA, DURABLE_WORKER_RUNNERS, DURABLE_WORKER_RUNTIME, DeadLetter, type DtoClass, DurableModule, type DurableModuleAsyncOptions, type DurableModuleOptions, type DurableRetentionOptions, DurableStartClient, DurableStep, type DurableStepInterceptor, type DurableStepMeta, ENTITY_METADATA, ENTITY_ON_METADATA, Entity, EntityService, type ErrorClassWithCode, IN_APP_RUN_REDIS_WORKER, IN_APP_WORKER_BINDING, IN_APP_WORKER_RUNNERS, IN_APP_WORKER_RUNTIME, type InAppWorkerBinding, InAppWorkerBootstrap, type IoSchema, ON_ERROR_METADATA, ON_EVENT_METADATA, On, OnDurableEvent, OnError, type OnErrorMethod, OnEvent, ProxyRunGateway, RUN_GATEWAY, RUN_REDIS_WORKER, type RunLookupStore, type RunRedisWorkerFn, RunRequestResponder, type RunRequestTransport, STEP_INTERCEPTOR_METADATA, Step, StepInterceptor, type StepOptions, StoreRunGateway, TenantEventRepublisher, ThinStepRegistrar, ThinWorkerBootstrap, ThinWorkflowRegistrar, UNSUPPORTED_RUN_REQUEST, type UserRef, WORKFLOW_METADATA, Workflow, type WorkflowAttributesOf, type WorkflowMeta, type WorkflowOptions, WorkflowService, attributesOf, entityConfigFor, getDurableStepMeta, getEntityMeta, getOnEvents, getWorkflowMeta, inAppWorkerProviders, isDeadLetterHandler, isDrivingOperator, isOperatorRole, isStepInterceptor, onErrorCodesOf, thinWorkerProviders, unavailableRunGateway };
1436
+ export { CONTEXT_ACCESSOR, type ContextAccessor, type ContextStore, DEAD_LETTER_METADATA, DURABLE_STEP_METADATA, DURABLE_WORKER_RUNNERS, DURABLE_WORKER_RUNTIME, DeadLetter, type DtoClass, DurableModule, type DurableModuleAsyncOptions, type DurableModuleOptions, type DurableRetentionOptions, DurableStartClient, DurableStep, type DurableStepInterceptor, type DurableStepMeta, ENTITY_METADATA, ENTITY_ON_METADATA, Entity, EntityService, type ErrorClassWithCode, IN_APP_RUN_REDIS_WORKER, IN_APP_WORKER_BINDING, IN_APP_WORKER_RUNNERS, IN_APP_WORKER_RUNTIME, type InAppWorkerBinding, InAppWorkerBootstrap, type IoSchema, ON_ERROR_METADATA, ON_EVENT_METADATA, On, OnDurableEvent, OnError, type OnErrorMethod, OnEvent, ProxyRunGateway, RUN_GATEWAY, RUN_REDIS_WORKER, type RunLookupStore, type RunRedisWorkerFn, RunRequestResponder, type RunRequestResponderOptions, type RunRequestTransport, STEP_INTERCEPTOR_METADATA, Step, StepInterceptor, type StepOptions, StoreRunGateway, TenantEventRepublisher, ThinStepRegistrar, ThinWorkerBootstrap, ThinWorkflowRegistrar, UNSUPPORTED_RUN_REQUEST, type UserRef, WORKFLOW_METADATA, Workflow, type WorkflowAttributesOf, type WorkflowMeta, type WorkflowOptions, WorkflowService, attributesOf, entityConfigFor, getDurableStepMeta, getEntityMeta, getOnEvents, getWorkflowMeta, inAppWorkerProviders, isDeadLetterHandler, isDrivingOperator, isOperatorRole, isStepInterceptor, onErrorCodesOf, thinWorkerProviders, unavailableRunGateway };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { WorkflowCtx, SearchAttributes, WorkflowClass, StandardSchemaV1, StepError, OnErrorInput, WorkflowRef, SingletonConfig, ConcurrencyConfig, SearchAttributesSchema, StateStore, Transport, NamedTransport, ControlPlane, StalledRunInfo, ScheduledWorkflow, RetentionPolicy, QueueConfig, AdmissionBackend, WorkflowInputOf, StartOptions, RunResult, RunGateway, WorkflowEngine, EntityHandler, DurableTopology, RunDetailOptions, RunDetail, FanPageQuery, FanPage, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, GroupHealth, RunWaiting, EngineEvent, RunRequest, RunReply, StepInvocation, WorkflowRun, TenantEvent } from '@dudousxd/nestjs-durable-core';
2
- export { AttributeFilter, DynamicWorkflowCtx, EngineEvent, InferSearchAttributes, OnErrorInput, RunDetail, RunGateway, RunListItem, RunQuery, RunStatus, RunWaiting, SearchAttributes, SearchAttributesSchema, StepCheckpoint, StepEvent, StepLogger, WorkflowCtx, WorkflowEngine, WorkflowHandler, WorkflowRun, readSearchAttributes } from '@dudousxd/nestjs-durable-core';
1
+ import { WorkflowCtx, SearchAttributes, WorkflowClass, StandardSchemaV1, StepError, OnErrorInput, WorkflowRef, SingletonConfig, ConcurrencyConfig, SearchAttributesSchema, StateStore, Transport, NamedTransport, ControlPlane, StalledRunInfo, ScheduledWorkflow, RetentionPolicy, QueueConfig, AdmissionBackend, TenantVerifier, TenantTokenSource, WorkflowInputOf, StartOptions, RunResult, RunGateway, WorkflowEngine, EntityHandler, DurableTopology, RunDetailOptions, RunDetail, FanPageQuery, FanPage, RunQuery, RunListItem, RunFacetQuery, RunFacetRow, RunValueAxis, RunValueFacetOptions, RunValueFacetRow, GroupHealth, RunWaiting, EngineEvent, RunRequest, RunReply, StepInvocation, WorkflowRun, TenantEvent } from '@dudousxd/nestjs-durable-core';
2
+ export { AttributeFilter, DynamicWorkflowCtx, EngineEvent, InferSearchAttributes, OnErrorInput, RunDetail, RunGateway, RunListItem, RunQuery, RunSchedulesOptions, RunStatus, RunWaiting, ScheduledWorkflow, SearchAttributes, SearchAttributesSchema, StepCheckpoint, StepEvent, StepLogger, TenantTokenSource, TenantVerifier, VerifiedTenant, WorkflowCtx, WorkflowEngine, WorkflowHandler, WorkflowRun, hmacTenantVerifier, prevCronFireMs, readSearchAttributes, runSchedules, scheduleRunIdAt, scheduledRunId, signTenantToken } from '@dudousxd/nestjs-durable-core';
3
3
  import { z } from 'zod';
4
4
  import { ConcurrencyOption, StartRunDeps, RunRedisWorkerOptions, RunningWorker, DurableWorkerRuntime } from '@dudousxd/durable-worker';
5
5
  import { DynamicModule, InjectionToken, OnModuleInit, OnApplicationBootstrap, OnApplicationShutdown, Provider } from '@nestjs/common';
@@ -242,14 +242,16 @@ interface WorkflowOptions {
242
242
  inputSchema?: IoSchema;
243
243
  /**
244
244
  * A custom check at `start` (throw to reject) for a rule a schema can't express — a cross-field
245
- * invariant, an async lookup. It sees the input as it was sent, and runs after `input` parses.
245
+ * invariant, an async lookup. It runs after `input` parses and receives the parsed value (the input
246
+ * as sent when there is no `input` schema).
246
247
  */
247
248
  validateInput?: (input: unknown) => void | Promise<void>;
248
249
  /**
249
250
  * Validate this workflow's {@link WorkflowCtx.upsertSearchAttributes} writes against a **Standard
250
251
  * Schema** (https://standardschema.dev — zod 3.24+, valibot, arktype, …). `ctx.upsertSearchAttributes`
251
252
  * validates the MERGED result (existing attributes shallow-merged with the patch) on every call —
252
- * an invalid merge throws, naming this workflow, the offending key(s), and the schema's issues. The
253
+ * an invalid merge throws a `SchemaValidationError` (code `schema_validation`) naming this workflow,
254
+ * with the schema's issues. The
253
255
  * schema's inferred output must be search-attribute-shaped (flat `string`/`number`/`boolean` values
254
256
  * only) — a schema whose output has a nested object/array is a compile-time error here. Omit for
255
257
  * the prior unvalidated behavior.
@@ -788,6 +790,26 @@ interface DurableModuleOptions {
788
790
  /** Timeout for a thin worker's `RunGateway` round-trip over `transport` before it rejects. Defaults
789
791
  * to 10_000ms inside `ProxyRunGateway`. Ignored for an operator (bound to `StoreRunGateway`). */
790
792
  runGatewayTimeoutMs?: number;
793
+ /**
794
+ * **Operator.** Verifies the signed tenant token a store-less tenant worker presents in the wire
795
+ * `tenant` field of every run request and start-run message, and DERIVES the tenant from it,
796
+ * discarding the wire claim. An invalid, tampered or absent token is rejected: a run request gets
797
+ * an `unauthorized` error reply, a start-run creates nothing. Use `hmacTenantVerifier(secret)`
798
+ * (tokens minted by `signTenantToken`, wire-compatible with Agora) or supply your own.
799
+ *
800
+ * Optional. Absent: the wire `tenant` is trusted verbatim (prefix/network isolation only), exactly
801
+ * as before. An explicit `topology: { role: 'control-plane' }` without a verifier logs a warning
802
+ * at boot; a plain operator (`store` + `transport`, no `topology`) boots silently.
803
+ */
804
+ verifyTenant?: TenantVerifier;
805
+ /**
806
+ * **Tenant worker.** The signed token (see `signTenantToken`) this worker presents, verbatim, in
807
+ * the `tenant` field of every run request (`ProxyRunGateway`) and start-run (`engine.start`), so
808
+ * an operator with {@link verifyTenant} can authenticate it. A string, or a function called before
809
+ * every request (rotation, short-lived tokens). Optional: absent, the raw {@link partition} is
810
+ * sent, as before. Live-tail stays keyed by the partition, never the token.
811
+ */
812
+ tenantToken?: TenantTokenSource;
791
813
  /**
792
814
  * An explicit preset that NAMES the deployment role instead of leaving it to `store`/`connection`
793
815
  * inference, and VALIDATES the axes that are otherwise only prose (see the interface doc's role
@@ -1089,13 +1111,29 @@ declare class ProxyRunGateway implements RunGateway {
1089
1111
  private readonly tenant;
1090
1112
  private readonly timeoutMs;
1091
1113
  private readonly capabilityTtlMs;
1114
+ /**
1115
+ * The tenant's signed token (see `signTenantToken`), presented VERBATIM in the `tenant` field of
1116
+ * every {@link RunRequest} so an operator with `verifyTenant` can authenticate it and derive the
1117
+ * tenant from it. A function is called before every request (rotation / short-lived tokens).
1118
+ * Omit to send the raw `tenant` (prefix/network isolation only). The live-tail channel always
1119
+ * stays keyed by `tenant`, never the token: the operator republishes by the run's namespace.
1120
+ */
1121
+ private readonly tenantToken?;
1092
1122
  private readonly pending;
1093
1123
  /** Verb → when to ask the control plane for it again, after it answered that it does not know it.
1094
1124
  * During a rolling upgrade the control plane is several pods of mixed versions behind one queue,
1095
1125
  * and a reply does not say which pod sent it, so the whole control plane is assumed old until the
1096
1126
  * entry expires. */
1097
1127
  private readonly unsupportedUntil;
1098
- constructor(transport: Transport, tenant: string, timeoutMs?: number, capabilityTtlMs?: number);
1128
+ constructor(transport: Transport, tenant: string, timeoutMs?: number, capabilityTtlMs?: number,
1129
+ /**
1130
+ * The tenant's signed token (see `signTenantToken`), presented VERBATIM in the `tenant` field of
1131
+ * every {@link RunRequest} so an operator with `verifyTenant` can authenticate it and derive the
1132
+ * tenant from it. A function is called before every request (rotation / short-lived tokens).
1133
+ * Omit to send the raw `tenant` (prefix/network isolation only). The live-tail channel always
1134
+ * stays keyed by `tenant`, never the token: the operator republishes by the run's namespace.
1135
+ */
1136
+ tenantToken?: TenantTokenSource | undefined);
1099
1137
  private handleReply;
1100
1138
  private request;
1101
1139
  topology(): DurableTopology;
@@ -1163,6 +1201,22 @@ interface RunRequestTransport {
1163
1201
  onRunRequest(handler: (msg: RunRequest) => Promise<void>): void;
1164
1202
  publishRunReply(reply: RunReply): Promise<void>;
1165
1203
  }
1204
+ /** Options for {@link RunRequestResponder}. */
1205
+ interface RunRequestResponderOptions {
1206
+ /**
1207
+ * Verifies the signed token a tenant presents in the wire `tenant` field and DERIVES the real
1208
+ * tenant from it (see `hmacTenantVerifier`). Present: an invalid, tampered or absent token is
1209
+ * rejected with an `unauthorized` error reply and the wire claim is discarded in favour of the
1210
+ * verified tenant. Absent: the wire `tenant` is trusted verbatim (prefix/network isolation only).
1211
+ */
1212
+ verifyTenant?: TenantVerifier | undefined;
1213
+ /**
1214
+ * Warn at construction when no {@link verifyTenant} is set. Default `true`. `DurableModule` passes
1215
+ * `true` only for an explicit `topology: { role: 'control-plane' }`, so a plain operator app that
1216
+ * never serves tenants boots silently.
1217
+ */
1218
+ warnWithoutVerifier?: boolean | undefined;
1219
+ }
1166
1220
  /**
1167
1221
  * Operator-side consumer of a tenant's {@link RunRequest}s: answers each one against a
1168
1222
  * `RunGateway`, enforcing the tenant boundary before touching the run. For every runId-bearing
@@ -1171,11 +1225,17 @@ interface RunRequestTransport {
1171
1225
  * verb, so a tenant can never read or act on another tenant's run. `listRuns` is scoped by
1172
1226
  * overwriting the query's `namespace` with the requester's tenant, ignoring whatever the client
1173
1227
  * sent. This is the security boundary of the tenant run gateway — do not weaken it.
1228
+ *
1229
+ * With {@link RunRequestResponderOptions.verifyTenant}, every request is authenticated FIRST: the
1230
+ * wire `tenant` is treated as a signed token, the real tenant is derived from it, and an invalid
1231
+ * token short-circuits into an `unauthorized` error reply before any run is touched. A verifier
1232
+ * that throws becomes an error reply too.
1174
1233
  */
1175
1234
  declare class RunRequestResponder {
1176
1235
  private readonly transport;
1177
1236
  private readonly gateway;
1178
- constructor(transport: RunRequestTransport, gateway: RunGateway);
1237
+ private readonly verifyTenant;
1238
+ constructor(transport: RunRequestTransport, gateway: RunGateway, options?: RunRequestResponderOptions);
1179
1239
  /** Register the consumer on the transport. Each request is answered independently; a handler
1180
1240
  * failure never throws back into the transport (errors are captured into an error reply). */
1181
1241
  start(): void;
@@ -1373,4 +1433,4 @@ declare class WorkflowService {
1373
1433
  }): Promise<number>;
1374
1434
  }
1375
1435
 
1376
- export { CONTEXT_ACCESSOR, type ContextAccessor, type ContextStore, DEAD_LETTER_METADATA, DURABLE_STEP_METADATA, DURABLE_WORKER_RUNNERS, DURABLE_WORKER_RUNTIME, DeadLetter, type DtoClass, DurableModule, type DurableModuleAsyncOptions, type DurableModuleOptions, type DurableRetentionOptions, DurableStartClient, DurableStep, type DurableStepInterceptor, type DurableStepMeta, ENTITY_METADATA, ENTITY_ON_METADATA, Entity, EntityService, type ErrorClassWithCode, IN_APP_RUN_REDIS_WORKER, IN_APP_WORKER_BINDING, IN_APP_WORKER_RUNNERS, IN_APP_WORKER_RUNTIME, type InAppWorkerBinding, InAppWorkerBootstrap, type IoSchema, ON_ERROR_METADATA, ON_EVENT_METADATA, On, OnDurableEvent, OnError, type OnErrorMethod, OnEvent, ProxyRunGateway, RUN_GATEWAY, RUN_REDIS_WORKER, type RunLookupStore, type RunRedisWorkerFn, RunRequestResponder, type RunRequestTransport, STEP_INTERCEPTOR_METADATA, Step, StepInterceptor, type StepOptions, StoreRunGateway, TenantEventRepublisher, ThinStepRegistrar, ThinWorkerBootstrap, ThinWorkflowRegistrar, UNSUPPORTED_RUN_REQUEST, type UserRef, WORKFLOW_METADATA, Workflow, type WorkflowAttributesOf, type WorkflowMeta, type WorkflowOptions, WorkflowService, attributesOf, entityConfigFor, getDurableStepMeta, getEntityMeta, getOnEvents, getWorkflowMeta, inAppWorkerProviders, isDeadLetterHandler, isDrivingOperator, isOperatorRole, isStepInterceptor, onErrorCodesOf, thinWorkerProviders, unavailableRunGateway };
1436
+ export { CONTEXT_ACCESSOR, type ContextAccessor, type ContextStore, DEAD_LETTER_METADATA, DURABLE_STEP_METADATA, DURABLE_WORKER_RUNNERS, DURABLE_WORKER_RUNTIME, DeadLetter, type DtoClass, DurableModule, type DurableModuleAsyncOptions, type DurableModuleOptions, type DurableRetentionOptions, DurableStartClient, DurableStep, type DurableStepInterceptor, type DurableStepMeta, ENTITY_METADATA, ENTITY_ON_METADATA, Entity, EntityService, type ErrorClassWithCode, IN_APP_RUN_REDIS_WORKER, IN_APP_WORKER_BINDING, IN_APP_WORKER_RUNNERS, IN_APP_WORKER_RUNTIME, type InAppWorkerBinding, InAppWorkerBootstrap, type IoSchema, ON_ERROR_METADATA, ON_EVENT_METADATA, On, OnDurableEvent, OnError, type OnErrorMethod, OnEvent, ProxyRunGateway, RUN_GATEWAY, RUN_REDIS_WORKER, type RunLookupStore, type RunRedisWorkerFn, RunRequestResponder, type RunRequestResponderOptions, type RunRequestTransport, STEP_INTERCEPTOR_METADATA, Step, StepInterceptor, type StepOptions, StoreRunGateway, TenantEventRepublisher, ThinStepRegistrar, ThinWorkerBootstrap, ThinWorkflowRegistrar, UNSUPPORTED_RUN_REQUEST, type UserRef, WORKFLOW_METADATA, Workflow, type WorkflowAttributesOf, type WorkflowMeta, type WorkflowOptions, WorkflowService, attributesOf, entityConfigFor, getDurableStepMeta, getEntityMeta, getOnEvents, getWorkflowMeta, inAppWorkerProviders, isDeadLetterHandler, isDrivingOperator, isOperatorRole, isStepInterceptor, onErrorCodesOf, thinWorkerProviders, unavailableRunGateway };
package/dist/index.js CHANGED
@@ -264,7 +264,7 @@ function attributesOf(workflow, run) {
264
264
  __name(attributesOf, "attributesOf");
265
265
 
266
266
  // src/durable-start-client.ts
267
- import { workflowName } from "@dudousxd/nestjs-durable-core";
267
+ import { resolveTenantToken, workflowName } from "@dudousxd/nestjs-durable-core";
268
268
  import { Injectable } from "@nestjs/common";
269
269
 
270
270
  // src/worker-sdk.ts
@@ -322,7 +322,9 @@ var DurableStartClient = class {
322
322
  async start(workflow, input, runId = globalThis.crypto.randomUUID(), opts) {
323
323
  const name = workflowName(workflow);
324
324
  await startRun(this.options.connection, {
325
- tenant: this.tenant,
325
+ // The signed token (when configured) rides in the `tenant` field, as on every run request; an
326
+ // operator with `verifyTenant` derives the run's namespace from it.
327
+ tenant: this.options.tenantToken !== void 0 ? await resolveTenantToken(this.options.tenantToken) : this.tenant,
326
328
  workflow: name,
327
329
  input,
328
330
  runId,
@@ -393,34 +395,20 @@ import { Inject, Injectable as Injectable2 } from "@nestjs/common";
393
395
  import { DiscoveryService, MetadataScanner } from "@nestjs/core";
394
396
 
395
397
  // src/schema-parse.ts
396
- import { FatalError } from "@dudousxd/nestjs-durable-core";
398
+ import { SchemaValidationError } from "@dudousxd/nestjs-durable-core";
397
399
  function schemaParser(schema, kind, label) {
398
400
  const code = kind === "input" ? "invalid_input" : "invalid_output";
399
401
  if (isStandardSchema(schema)) {
400
402
  return async (value) => {
401
403
  const result = await schema["~standard"].validate(value);
402
- if (result.issues) {
403
- const issues = result.issues.map((i) => ({
404
- message: i.message,
405
- ...i.path ? {
406
- path: i.path.map((p) => String(typeof p === "object" ? p.key : p))
407
- } : {}
408
- }));
409
- throw new FatalError(`invalid ${label}: ${formatIssues(issues)}`, code, issues);
410
- }
404
+ if (result.issues) throw new SchemaValidationError(label, result.issues, code);
411
405
  return result.value;
412
406
  };
413
407
  }
414
408
  if (isZodLike(schema)) {
415
409
  return async (value) => {
416
410
  const result = schema.safeParse(value);
417
- if (!result.success) {
418
- const issues = result.error.issues.map((i) => ({
419
- message: i.message,
420
- path: i.path.map(String)
421
- }));
422
- throw new FatalError(`invalid ${label}: ${formatIssues(issues)}`, code, issues);
423
- }
411
+ if (!result.success) throw new SchemaValidationError(label, result.error.issues, code);
424
412
  return result.data;
425
413
  };
426
414
  }
@@ -440,12 +428,11 @@ function classValidatorParser(cls, code, label) {
440
428
  }
441
429
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
442
430
  const got = value === null ? "null" : Array.isArray(value) ? "an array" : typeof value;
443
- const message = `expected an object, got ${got}`;
444
- throw new FatalError(`invalid ${label}: ${message}`, code, [
431
+ throw new SchemaValidationError(label, [
445
432
  {
446
- message
433
+ message: `expected an object, got ${got}`
447
434
  }
448
- ]);
435
+ ], code);
449
436
  }
450
437
  const instance = ct.plainToInstance(cls, value);
451
438
  const errors = await cv.validate(instance, {
@@ -460,8 +447,8 @@ function classValidatorParser(cls, code, label) {
460
447
  String(e.property)
461
448
  ]
462
449
  }));
463
- const message = issues.map((i) => i.message).join("; ");
464
- throw new FatalError(`invalid ${label}: ${message}`, code, issues);
450
+ const summary = issues.map((i) => i.message).join("; ");
451
+ throw new SchemaValidationError(label, issues, code, summary);
465
452
  }
466
453
  return instance;
467
454
  };
@@ -475,10 +462,6 @@ function isZodLike(schema) {
475
462
  return typeof schema === "object" && schema !== null && typeof schema.safeParse === "function";
476
463
  }
477
464
  __name(isZodLike, "isZodLike");
478
- function formatIssues(issues) {
479
- return issues.map((i) => i.path && i.path.length > 0 ? `${i.path.join(".")}: ${i.message}` : i.message).join("; ");
480
- }
481
- __name(formatIssues, "formatIssues");
482
465
 
483
466
  // src/discovery-helpers.ts
484
467
  function scanWorkflows(discovery, register) {
@@ -558,8 +541,8 @@ function workflowIo(meta) {
558
541
  const validateInput = meta.validateInput;
559
542
  return {
560
543
  validateAtStart: parseInput || validateInput ? async (input) => {
561
- if (parseInput) await parseInput(input);
562
- await validateInput?.(input);
544
+ const parsed = parseInput ? await parseInput(input) : input;
545
+ await validateInput?.(parsed);
563
546
  } : void 0,
564
547
  wrap: /* @__PURE__ */ __name((body) => !parseInput && !parseOutput ? body : async (ctx, input) => {
565
548
  const output = await body(ctx, parseInput ? await parseInput(input) : input);
@@ -1178,10 +1161,11 @@ function inAppWorkerProviders() {
1178
1161
  __name(inAppWorkerProviders, "inAppWorkerProviders");
1179
1162
 
1180
1163
  // src/proxy-run-gateway.ts
1181
- import { SUMMARY_CHILD_LIMIT, childIdsOf, pageFan, summarizeTimeline } from "@dudousxd/nestjs-durable-core";
1164
+ import { SUMMARY_CHILD_LIMIT, childIdsOf, pageFan, resolveTenantToken as resolveTenantToken2, summarizeTimeline } from "@dudousxd/nestjs-durable-core";
1182
1165
  import { Injectable as Injectable6 } from "@nestjs/common";
1183
1166
 
1184
1167
  // src/run-request-responder.ts
1168
+ import { resolveWireTenant } from "@dudousxd/nestjs-durable-core";
1185
1169
  var UNSUPPORTED_RUN_REQUEST = "unsupported-request";
1186
1170
  var KNOWN_KINDS = /* @__PURE__ */ new Set([
1187
1171
  "getRunDetail",
@@ -1203,9 +1187,14 @@ var RunRequestResponder = class {
1203
1187
  }
1204
1188
  transport;
1205
1189
  gateway;
1206
- constructor(transport, gateway) {
1190
+ verifyTenant;
1191
+ constructor(transport, gateway, options = {}) {
1207
1192
  this.transport = transport;
1208
1193
  this.gateway = gateway;
1194
+ this.verifyTenant = options.verifyTenant;
1195
+ if (!this.verifyTenant && options.warnWithoutVerifier !== false) {
1196
+ console.warn("[nestjs-durable] run-request responder started WITHOUT a tenant verifier: the wire `tenant` claim is trusted verbatim (prefix/network isolation only). Any broker client can act as any tenant. Configure `verifyTenant` (e.g. hmacTenantVerifier(secret)) and signed tenant tokens unless your broker is fully isolated per tenant.");
1197
+ }
1209
1198
  }
1210
1199
  /** Register the consumer on the transport. Each request is answered independently; a handler
1211
1200
  * failure never throws back into the transport (errors are captured into an error reply). */
@@ -1228,7 +1217,24 @@ var RunRequestResponder = class {
1228
1217
  await this.transport.publishRunReply(reply);
1229
1218
  });
1230
1219
  }
1231
- async handle(msg) {
1220
+ async handle(wire) {
1221
+ const tenant = await resolveWireTenant(wire.tenant, this.verifyTenant);
1222
+ if (tenant === null) {
1223
+ return {
1224
+ requestId: wire.requestId,
1225
+ result: {
1226
+ ok: false,
1227
+ error: {
1228
+ message: "invalid or unauthorized tenant token",
1229
+ code: "unauthorized"
1230
+ }
1231
+ }
1232
+ };
1233
+ }
1234
+ const msg = {
1235
+ ...wire,
1236
+ tenant
1237
+ };
1232
1238
  const { body } = msg;
1233
1239
  if (!KNOWN_KINDS.has(body.kind)) {
1234
1240
  return {
@@ -1421,17 +1427,19 @@ var ProxyRunGateway = class {
1421
1427
  tenant;
1422
1428
  timeoutMs;
1423
1429
  capabilityTtlMs;
1430
+ tenantToken;
1424
1431
  pending = /* @__PURE__ */ new Map();
1425
1432
  /** Verb → when to ask the control plane for it again, after it answered that it does not know it.
1426
1433
  * During a rolling upgrade the control plane is several pods of mixed versions behind one queue,
1427
1434
  * and a reply does not say which pod sent it, so the whole control plane is assumed old until the
1428
1435
  * entry expires. */
1429
1436
  unsupportedUntil = /* @__PURE__ */ new Map();
1430
- constructor(transport, tenant, timeoutMs = 1e4, capabilityTtlMs = 6e4) {
1437
+ constructor(transport, tenant, timeoutMs = 1e4, capabilityTtlMs = 6e4, tenantToken) {
1431
1438
  this.transport = transport;
1432
1439
  this.tenant = tenant;
1433
1440
  this.timeoutMs = timeoutMs;
1434
1441
  this.capabilityTtlMs = capabilityTtlMs;
1442
+ this.tenantToken = tenantToken;
1435
1443
  this.transport.onRunReply?.((reply) => this.handleReply(reply));
1436
1444
  }
1437
1445
  handleReply(reply) {
@@ -1444,7 +1452,10 @@ var ProxyRunGateway = class {
1444
1452
  } else if (reply.result.error.code === UNSUPPORTED_RUN_REQUEST) {
1445
1453
  pending.reject(new UnsupportedRunRequestError(reply.result.error.message));
1446
1454
  } else {
1447
- pending.reject(new Error(reply.result.error.message));
1455
+ const { message, code } = reply.result.error;
1456
+ pending.reject(code !== void 0 ? Object.assign(new Error(message), {
1457
+ code
1458
+ }) : new Error(message));
1448
1459
  }
1449
1460
  }
1450
1461
  request(body) {
@@ -1459,11 +1470,17 @@ var ProxyRunGateway = class {
1459
1470
  reject,
1460
1471
  timer
1461
1472
  });
1462
- this.transport.dispatchRunRequest?.({
1473
+ const source = this.tenantToken;
1474
+ const dispatched = typeof source === "function" ? resolveTenantToken2(source).then((tenant) => this.transport.dispatchRunRequest?.({
1463
1475
  requestId,
1464
- tenant: this.tenant,
1476
+ tenant,
1465
1477
  body
1466
- }).catch((error) => {
1478
+ })) : this.transport.dispatchRunRequest?.({
1479
+ requestId,
1480
+ tenant: source ?? this.tenant,
1481
+ body
1482
+ });
1483
+ dispatched?.catch((error) => {
1467
1484
  const stillPending = this.pending.get(requestId);
1468
1485
  if (!stillPending) return;
1469
1486
  clearTimeout(stillPending.timer);
@@ -1621,7 +1638,8 @@ ProxyRunGateway = _ts_decorate6([
1621
1638
  typeof Transport === "undefined" ? Object : Transport,
1622
1639
  String,
1623
1640
  void 0,
1624
- void 0
1641
+ void 0,
1642
+ typeof TenantTokenSource === "undefined" ? Object : TenantTokenSource
1625
1643
  ])
1626
1644
  ], ProxyRunGateway);
1627
1645
 
@@ -2076,7 +2094,7 @@ var TenantEventRepublisher = class {
2076
2094
  };
2077
2095
 
2078
2096
  // src/timer-poller.ts
2079
- import { DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL5, WorkflowEngine as WorkflowEngine3, runSchedules } from "@dudousxd/nestjs-durable-core";
2097
+ import { DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL5, WorkflowEngine as WorkflowEngine3, runSchedules, workflowName as workflowName3 } from "@dudousxd/nestjs-durable-core";
2080
2098
  import { Inject as Inject6, Injectable as Injectable9 } from "@nestjs/common";
2081
2099
  function _ts_decorate9(decorators, target, key, desc) {
2082
2100
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -2120,6 +2138,7 @@ var TimerPoller = class {
2120
2138
  this.options = options;
2121
2139
  }
2122
2140
  async onApplicationBootstrap() {
2141
+ for (const s of this.options.schedules ?? []) workflowName3(s.workflow);
2123
2142
  if (!isDrivingOperator(this.options)) return;
2124
2143
  this.unsubscribeEnqueued = this.engine.onEnqueued((runId) => {
2125
2144
  void this.engine.runOne(runId).catch((error) => {
@@ -2221,7 +2240,7 @@ var CONTEXT_ACCESSOR = Symbol.for("@dudousxd/nestjs-context:accessor");
2221
2240
  var RUN_GATEWAY = RunGateway;
2222
2241
 
2223
2242
  // src/workflow.registrar.ts
2224
- import { DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL6, RemoteWorkflowExecutor, STATE_STORE_CANONICAL as STATE_STORE_CANONICAL3, WorkflowEngine as WorkflowEngine4, bindWorkflowClass, parseDuration as parseDuration2, sanitizeQueueToken, tenantGroup, workflowName as workflowName3 } from "@dudousxd/nestjs-durable-core";
2243
+ import { DURABLE_OPTIONS_CANONICAL as DURABLE_OPTIONS_CANONICAL6, RemoteWorkflowExecutor, STATE_STORE_CANONICAL as STATE_STORE_CANONICAL3, WorkflowEngine as WorkflowEngine4, bindWorkflowClass, parseDuration as parseDuration2, sanitizeQueueToken, tenantGroup, workflowName as workflowName4 } from "@dudousxd/nestjs-durable-core";
2225
2244
  import { Inject as Inject7, Injectable as Injectable10 } from "@nestjs/common";
2226
2245
  import { DiscoveryService as DiscoveryService4, MetadataScanner as MetadataScanner4 } from "@nestjs/core";
2227
2246
 
@@ -2388,7 +2407,7 @@ var WorkflowRegistrar = class {
2388
2407
  });
2389
2408
  deadLetterByWorkflow.set(meta.name, dlqName);
2390
2409
  } else if (meta.deadLetterWorkflow) {
2391
- deadLetterByWorkflow.set(meta.name, workflowName3(meta.deadLetterWorkflow));
2410
+ deadLetterByWorkflow.set(meta.name, workflowName4(meta.deadLetterWorkflow));
2392
2411
  }
2393
2412
  });
2394
2413
  this.reportUnattributed(unattributed);
@@ -2436,7 +2455,7 @@ var WorkflowRegistrar = class {
2436
2455
  * a `dlq:<runId>` id, so re-recovery never double-dispatches.
2437
2456
  */
2438
2457
  installDeadLetterRouting(byWorkflow) {
2439
- const fallback = this.options.deadLetterWorkflow ? workflowName3(this.options.deadLetterWorkflow) : void 0;
2458
+ const fallback = this.options.deadLetterWorkflow ? workflowName4(this.options.deadLetterWorkflow) : void 0;
2440
2459
  if (byWorkflow.size === 0 && !fallback) return;
2441
2460
  this.engine.onDead((run) => {
2442
2461
  const target = byWorkflow.get(run.workflow) ?? fallback;
@@ -2745,7 +2764,15 @@ var RunGatewayBootstrap = class RunGatewayBootstrap2 {
2745
2764
  onRunRequest: onRunRequest.bind(this.transport),
2746
2765
  publishRunReply: publishRunReply.bind(this.transport)
2747
2766
  };
2748
- new RunRequestResponder(runRequestTransport, this.gateway).start();
2767
+ new RunRequestResponder(runRequestTransport, this.gateway, {
2768
+ verifyTenant: this.options.verifyTenant,
2769
+ // Mirrors Agora's rule (`warnWithoutVerifier: role === 'control-plane'`): only a deployment
2770
+ // that EXPLICITLY names itself the control plane is told it runs without tenant auth. A plain
2771
+ // operator (role inferred from `store`) is Agora's `standalone`: anyone with broker access
2772
+ // can already enqueue steps and results there, so the warning would be noise on every boot
2773
+ // of an app that never serves tenants.
2774
+ warnWithoutVerifier: this.options.topology?.role === "control-plane"
2775
+ }).start();
2749
2776
  }
2750
2777
  if (typeof publishTenantEvent === "function") {
2751
2778
  const republisher = new TenantEventRepublisher(store, publishTenantEvent.bind(this.transport));
@@ -2897,6 +2924,7 @@ var DurableModule = class _DurableModule {
2897
2924
  context,
2898
2925
  rehydrate: rehydrate || void 0,
2899
2926
  compensationRetries: options.compensationRetries,
2927
+ verifyTenant: options.verifyTenant,
2900
2928
  // A non-driving (dashboard/API) operator must not run workflows: enqueue-only, leaving
2901
2929
  // each `pending` run in the store for a DRIVING instance's poll. A driving operator gets
2902
2930
  // the engine's default in-process dispatcher: for a body registered inline, it runs
@@ -2937,7 +2965,7 @@ var DurableModule = class _DurableModule {
2937
2965
  }
2938
2966
  return new StoreRunGateway(store, engine);
2939
2967
  }
2940
- return options.transport ? new ProxyRunGateway(options.transport, options.partition ?? "default", options.runGatewayTimeoutMs) : unavailableRunGateway();
2968
+ return options.transport ? new ProxyRunGateway(options.transport, options.partition ?? "default", options.runGatewayTimeoutMs, void 0, options.tenantToken) : unavailableRunGateway();
2941
2969
  }, "useFactory"),
2942
2970
  inject: [
2943
2971
  DURABLE_OPTIONS_CANONICAL7,
@@ -2972,7 +3000,7 @@ DurableModule = _ts_decorate12([
2972
3000
  ], DurableModule);
2973
3001
 
2974
3002
  // src/index.ts
2975
- import { readSearchAttributes as readSearchAttributes2, RunGateway as RunGateway3, WorkflowEngine as WorkflowEngine7 } from "@dudousxd/nestjs-durable-core";
3003
+ import { hmacTenantVerifier, prevCronFireMs, readSearchAttributes as readSearchAttributes2, RunGateway as RunGateway3, runSchedules as runSchedules2, scheduledRunId, scheduleRunIdAt, signTenantToken, WorkflowEngine as WorkflowEngine7 } from "@dudousxd/nestjs-durable-core";
2976
3004
  export {
2977
3005
  CONTEXT_ACCESSOR,
2978
3006
  DEAD_LETTER_METADATA,
@@ -3022,13 +3050,19 @@ export {
3022
3050
  getEntityMeta,
3023
3051
  getOnEvents,
3024
3052
  getWorkflowMeta,
3053
+ hmacTenantVerifier,
3025
3054
  inAppWorkerProviders,
3026
3055
  isDeadLetterHandler,
3027
3056
  isDrivingOperator,
3028
3057
  isOperatorRole,
3029
3058
  isStepInterceptor,
3030
3059
  onErrorCodesOf,
3060
+ prevCronFireMs,
3031
3061
  readSearchAttributes2 as readSearchAttributes,
3062
+ runSchedules2 as runSchedules,
3063
+ scheduleRunIdAt,
3064
+ scheduledRunId,
3065
+ signTenantToken,
3032
3066
  thinWorkerProviders,
3033
3067
  unavailableRunGateway
3034
3068
  };