@dudousxd/nestjs-durable-core 0.83.0 → 0.84.1

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.cjs CHANGED
@@ -135,6 +135,7 @@ __export(index_exports, {
135
135
  handoffName: () => handoffName,
136
136
  hasDurableExecutionWrappers: () => hasDurableExecutionWrappers,
137
137
  heartbeatStatus: () => heartbeatStatus,
138
+ hmacTenantVerifier: () => hmacTenantVerifier,
138
139
  indexWaitersByRun: () => indexWaitersByRun,
139
140
  info: () => info,
140
141
  isEngineMintedTag: () => isEngineMintedTag,
@@ -172,6 +173,8 @@ __export(index_exports, {
172
173
  resolveConcurrency: () => resolveConcurrency,
173
174
  resolveRouting: () => resolveRouting,
174
175
  resolveRunWaiting: () => resolveRunWaiting,
176
+ resolveTenantToken: () => resolveTenantToken,
177
+ resolveWireTenant: () => resolveWireTenant,
175
178
  retiredHandoffName: () => retiredHandoffName,
176
179
  routeFor: () => routeFor,
177
180
  runDetailEtag: () => runDetailEtag,
@@ -186,6 +189,7 @@ __export(index_exports, {
186
189
  sanitizeQueueToken: () => sanitizeQueueToken,
187
190
  scheduleRunIdAt: () => scheduleRunIdAt,
188
191
  scheduledRunId: () => scheduledRunId,
192
+ signTenantToken: () => signTenantToken,
189
193
  singletonAdmissionDenialPatch: () => singletonAdmissionDenialPatch,
190
194
  singletonAdmissionTags: () => singletonAdmissionTags,
191
195
  sqlComparator: () => sqlComparator,
@@ -3146,6 +3150,73 @@ async function stalledInfo(store, run, now, thresholdMs, ageMs) {
3146
3150
  }
3147
3151
  __name(stalledInfo, "stalledInfo");
3148
3152
 
3153
+ // src/tenant-auth.ts
3154
+ var import_node_crypto = require("crypto");
3155
+ var TOKEN_SEP = ".";
3156
+ var EXP_SUFFIX = /\.exp(\d+)$/;
3157
+ function sign(claim, secret) {
3158
+ return (0, import_node_crypto.createHmac)("sha256", secret).update(claim).digest("base64url");
3159
+ }
3160
+ __name(sign, "sign");
3161
+ function signTenantToken(tenant, secret, opts) {
3162
+ const claim = opts?.ttlMs !== void 0 ? `${tenant}${TOKEN_SEP}exp${(opts.now ?? Date.now()) + opts.ttlMs}` : tenant;
3163
+ return `${claim}${TOKEN_SEP}${sign(claim, secret)}`;
3164
+ }
3165
+ __name(signTenantToken, "signTenantToken");
3166
+ function hmacTenantVerifier(secret, capabilities) {
3167
+ const secrets = Array.isArray(secret) ? secret : [
3168
+ secret
3169
+ ];
3170
+ return ({ token }) => {
3171
+ if (typeof token !== "string" || token.length === 0) return null;
3172
+ const sep = token.lastIndexOf(TOKEN_SEP);
3173
+ if (sep <= 0 || sep === token.length - 1) return null;
3174
+ const claim = token.slice(0, sep);
3175
+ const presented = token.slice(sep + 1);
3176
+ if (!secrets.some((s) => constantTimeEquals(presented, sign(claim, s)))) return null;
3177
+ const exp = EXP_SUFFIX.exec(claim);
3178
+ if (exp) {
3179
+ const expiresAt = Number(exp[1]);
3180
+ if (!Number.isFinite(expiresAt) || Date.now() > expiresAt) return null;
3181
+ const tenant = claim.slice(0, claim.length - (exp[0]?.length ?? 0));
3182
+ if (tenant.length === 0) return null;
3183
+ return capabilities !== void 0 ? {
3184
+ tenant,
3185
+ capabilities
3186
+ } : {
3187
+ tenant
3188
+ };
3189
+ }
3190
+ return capabilities !== void 0 ? {
3191
+ tenant: claim,
3192
+ capabilities
3193
+ } : {
3194
+ tenant: claim
3195
+ };
3196
+ };
3197
+ }
3198
+ __name(hmacTenantVerifier, "hmacTenantVerifier");
3199
+ async function resolveWireTenant(wireTenant, verifyTenant) {
3200
+ if (!verifyTenant) return wireTenant;
3201
+ const verified = await verifyTenant({
3202
+ token: wireTenant,
3203
+ tenant: wireTenant
3204
+ });
3205
+ return verified ? verified.tenant : null;
3206
+ }
3207
+ __name(resolveWireTenant, "resolveWireTenant");
3208
+ async function resolveTenantToken(source) {
3209
+ return typeof source === "function" ? source() : source;
3210
+ }
3211
+ __name(resolveTenantToken, "resolveTenantToken");
3212
+ function constantTimeEquals(a, b) {
3213
+ const ab = Buffer.from(a);
3214
+ const bb = Buffer.from(b);
3215
+ if (ab.length !== bb.length) return false;
3216
+ return (0, import_node_crypto.timingSafeEqual)(ab, bb);
3217
+ }
3218
+ __name(constantTimeEquals, "constantTimeEquals");
3219
+
3149
3220
  // src/transport-pool.ts
3150
3221
  var TransportPool = class {
3151
3222
  static {
@@ -4622,9 +4693,20 @@ var WorkflowEngine = class {
4622
4693
  await this.completeRemoteDecision(decision);
4623
4694
  }
4624
4695
  );
4696
+ const verifyTenant = deps.verifyTenant;
4625
4697
  this.pool.onStartRun(async (message) => {
4698
+ let tenant;
4699
+ try {
4700
+ tenant = await resolveWireTenant(message.tenant, verifyTenant);
4701
+ } catch {
4702
+ tenant = null;
4703
+ }
4704
+ if (tenant === null) {
4705
+ console.warn(`[nestjs-durable] dropped a start-run for "${message.workflow}": invalid or unauthorized tenant token`);
4706
+ return;
4707
+ }
4626
4708
  await this.start(message.workflow, message.input, message.runId ?? globalThis.crypto.randomUUID(), {
4627
- namespace: message.tenant,
4709
+ namespace: tenant,
4628
4710
  tags: message.tags,
4629
4711
  searchAttributes: message.searchAttributes
4630
4712
  });
@@ -11064,6 +11146,7 @@ var InMemoryTransport = class {
11064
11146
  handoffName,
11065
11147
  hasDurableExecutionWrappers,
11066
11148
  heartbeatStatus,
11149
+ hmacTenantVerifier,
11067
11150
  indexWaitersByRun,
11068
11151
  info,
11069
11152
  isEngineMintedTag,
@@ -11101,6 +11184,8 @@ var InMemoryTransport = class {
11101
11184
  resolveConcurrency,
11102
11185
  resolveRouting,
11103
11186
  resolveRunWaiting,
11187
+ resolveTenantToken,
11188
+ resolveWireTenant,
11104
11189
  retiredHandoffName,
11105
11190
  routeFor,
11106
11191
  runDetailEtag,
@@ -11115,6 +11200,7 @@ var InMemoryTransport = class {
11115
11200
  sanitizeQueueToken,
11116
11201
  scheduleRunIdAt,
11117
11202
  scheduledRunId,
11203
+ signTenantToken,
11118
11204
  singletonAdmissionDenialPatch,
11119
11205
  singletonAdmissionTags,
11120
11206
  sqlComparator,