@01.software/sdk 0.70.1 → 0.72.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.
Files changed (70) hide show
  1. package/CHANGELOG.md +143 -0
  2. package/MIGRATION.md +28 -0
  3. package/README.md +253 -11
  4. package/dist/client.cjs +396 -26
  5. package/dist/client.cjs.map +1 -1
  6. package/dist/client.d.cts +7 -6
  7. package/dist/client.d.ts +7 -6
  8. package/dist/client.js +396 -26
  9. package/dist/client.js.map +1 -1
  10. package/dist/{collection-client-BHLStm1K.d.cts → collection-client-B3CnqMDQ.d.cts} +14 -18
  11. package/dist/{collection-client-B1FSJ24_.d.ts → collection-client-uOgS_1bC.d.ts} +14 -18
  12. package/dist/{const-ty8u0TDI.d.ts → const-BJBK7jBl.d.ts} +1 -1
  13. package/dist/{const-BfQfV-rr.d.cts → const-_ZfJjRQG.d.cts} +1 -1
  14. package/dist/embedded-admin/server.cjs +117 -2
  15. package/dist/embedded-admin/server.cjs.map +1 -1
  16. package/dist/embedded-admin/server.d.cts +30 -2
  17. package/dist/embedded-admin/server.d.ts +30 -2
  18. package/dist/embedded-admin/server.js +117 -2
  19. package/dist/embedded-admin/server.js.map +1 -1
  20. package/dist/embedded-admin.cjs +135 -7
  21. package/dist/embedded-admin.cjs.map +1 -1
  22. package/dist/embedded-admin.d.cts +35 -2
  23. package/dist/embedded-admin.d.ts +35 -2
  24. package/dist/embedded-admin.js +135 -7
  25. package/dist/embedded-admin.js.map +1 -1
  26. package/dist/errors.cjs +2 -0
  27. package/dist/errors.cjs.map +1 -1
  28. package/dist/errors.d.cts +3 -3
  29. package/dist/errors.d.ts +3 -3
  30. package/dist/errors.js +2 -0
  31. package/dist/errors.js.map +1 -1
  32. package/dist/{index-DnKgjPGM.d.ts → index-CBaP4q8r.d.ts} +3 -3
  33. package/dist/{index-CX6si6YC.d.cts → index-CI_LFWiG.d.cts} +3 -3
  34. package/dist/index.cjs +396 -26
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +24 -9
  37. package/dist/index.d.ts +24 -9
  38. package/dist/index.js +396 -26
  39. package/dist/index.js.map +1 -1
  40. package/dist/{payload-types-DTAaWKrp.d.cts → payload-types-BRg8Yary.d.cts} +262 -177
  41. package/dist/{payload-types-DTAaWKrp.d.ts → payload-types-BRg8Yary.d.ts} +262 -177
  42. package/dist/query.cjs +20 -0
  43. package/dist/query.cjs.map +1 -1
  44. package/dist/query.d.cts +5 -5
  45. package/dist/query.d.ts +5 -5
  46. package/dist/query.js +20 -0
  47. package/dist/query.js.map +1 -1
  48. package/dist/realtime.d.cts +2 -2
  49. package/dist/realtime.d.ts +2 -2
  50. package/dist/server.cjs +459 -46
  51. package/dist/server.cjs.map +1 -1
  52. package/dist/server.d.cts +10 -8
  53. package/dist/server.d.ts +10 -8
  54. package/dist/server.js +459 -46
  55. package/dist/server.js.map +1 -1
  56. package/dist/storefront-cache.cjs +2 -0
  57. package/dist/storefront-cache.cjs.map +1 -1
  58. package/dist/storefront-cache.js +2 -0
  59. package/dist/storefront-cache.js.map +1 -1
  60. package/dist/{types-DdlhpNVv.d.ts → types-Cmnxxvuv.d.ts} +238 -21
  61. package/dist/{types-Bzgf4mTo.d.cts → types-CnkJQUez.d.cts} +238 -21
  62. package/dist/{types-DX8Z44yQ.d.ts → types-DLjSqL0P.d.ts} +2 -2
  63. package/dist/{types-CpSiyJud.d.cts → types-FyklqLAk.d.cts} +2 -2
  64. package/dist/ui/form.d.cts +1 -1
  65. package/dist/ui/form.d.ts +1 -1
  66. package/dist/ui/video.d.cts +1 -1
  67. package/dist/ui/video.d.ts +1 -1
  68. package/dist/webhook.d.cts +5 -5
  69. package/dist/webhook.d.ts +5 -5
  70. package/package.json +2 -4
@@ -1,8 +1,8 @@
1
- import { cU as DebugConfig, c_ as RetryConfig, cN as ApiQueryOptions, cX as PayloadFindResponse, cY as PayloadMutationResponse, dc as ApiDeleteOptions, dd as PublicReadQueryOptions } from './types-Bzgf4mTo.cjs';
2
- import './payload-types-DTAaWKrp.cjs';
1
+ import { dd as DebugConfig, dj as RetryConfig, d6 as ApiQueryOptions, dg as PayloadFindResponse, dh as PayloadMutationResponse, dy as ApiDocumentWriteOptions, dz as ApiWriteOptions, dA as ApiDeleteOptions, dB as PublicReadQueryOptions } from './types-CnkJQUez.cjs';
2
+ import './payload-types-BRg8Yary.cjs';
3
3
  import { GenerateMetadataOptions, Metadata } from './metadata.cjs';
4
- import { C as Collection, S as ServerCollection, P as PublicCollection } from './const-BfQfV-rr.cjs';
5
- import { C as CollectionType } from './types-CpSiyJud.cjs';
4
+ import { C as Collection, S as ServerCollection, P as PublicCollection } from './const-_ZfJjRQG.cjs';
5
+ import { C as CollectionType } from './types-FyklqLAk.cjs';
6
6
 
7
7
  interface FetchOptions extends RequestInit {
8
8
  apiUrl?: string;
@@ -90,21 +90,17 @@ declare class CollectionQueryBuilder<T extends Collection> {
90
90
  /**
91
91
  * Create a new document
92
92
  * POST /api/{collection}
93
+ * Pass `locale` to write localized fields in a tenant-enabled locale.
93
94
  * @returns Payload CMS mutation response with doc and message
94
95
  */
95
- create(data: Partial<CollectionType<T>>, options?: {
96
- file?: File | Blob;
97
- filename?: string;
98
- }): Promise<PayloadMutationResponse<CollectionType<T>>>;
96
+ create(data: Partial<CollectionType<T>>, options?: ApiDocumentWriteOptions): Promise<PayloadMutationResponse<CollectionType<T>>>;
99
97
  /**
100
98
  * Update a document by ID
101
99
  * PATCH /api/{collection}/{id}
100
+ * Pass `locale` to write localized fields in a tenant-enabled locale.
102
101
  * @returns Payload CMS mutation response with doc and message
103
102
  */
104
- update(id: string, data: Partial<CollectionType<T>>, options?: {
105
- file?: File | Blob;
106
- filename?: string;
107
- }): Promise<PayloadMutationResponse<CollectionType<T>>>;
103
+ update(id: string, data: Partial<CollectionType<T>>, options?: ApiDocumentWriteOptions): Promise<PayloadMutationResponse<CollectionType<T>>>;
108
104
  /**
109
105
  * Count documents
110
106
  * GET /api/{collection}/count
@@ -130,7 +126,7 @@ declare class CollectionQueryBuilder<T extends Collection> {
130
126
  * PATCH /api/{collection}
131
127
  * @returns Payload CMS find response with updated docs
132
128
  */
133
- updateMany(where: ApiQueryOptions['where'], data: Partial<CollectionType<T>>): Promise<PayloadFindResponse<CollectionType<T>>>;
129
+ updateMany(where: ApiQueryOptions['where'], data: Partial<CollectionType<T>>, options?: ApiWriteOptions): Promise<PayloadFindResponse<CollectionType<T>>>;
134
130
  /**
135
131
  * Delete a document by ID
136
132
  * DELETE /api/{collection}/{id}
@@ -172,12 +168,12 @@ declare class CollectionClient<TCollection extends Collection = PublicCollection
172
168
  * Create document
173
169
  * POST /api/{collection}
174
170
  */
175
- requestCreate<T = unknown>(endpoint: string, data?: unknown): Promise<PayloadMutationResponse<T>>;
171
+ requestCreate<T = unknown>(endpoint: string, data?: unknown, options?: ApiWriteOptions): Promise<PayloadMutationResponse<T>>;
176
172
  /**
177
173
  * Update document
178
174
  * PATCH /api/{collection}/{id}
179
175
  */
180
- requestUpdate<T = unknown>(endpoint: string, data?: unknown): Promise<PayloadMutationResponse<T>>;
176
+ requestUpdate<T = unknown>(endpoint: string, data?: unknown, options?: ApiWriteOptions): Promise<PayloadMutationResponse<T>>;
181
177
  /**
182
178
  * Count documents
183
179
  * GET /api/{collection}/count
@@ -192,7 +188,7 @@ declare class CollectionClient<TCollection extends Collection = PublicCollection
192
188
  requestUpdateMany<T = unknown>(endpoint: string, data: {
193
189
  where?: ApiQueryOptions['where'];
194
190
  data: unknown;
195
- }): Promise<PayloadFindResponse<T>>;
191
+ }, options?: ApiWriteOptions): Promise<PayloadFindResponse<T>>;
196
192
  /**
197
193
  * Delete document
198
194
  * DELETE /api/{collection}/{id}
@@ -209,12 +205,12 @@ declare class CollectionClient<TCollection extends Collection = PublicCollection
209
205
  * Create document with file upload
210
206
  * POST /api/{collection} (multipart/form-data)
211
207
  */
212
- requestCreateWithFile<T = unknown>(endpoint: string, data: unknown, file: File | Blob, filename?: string): Promise<PayloadMutationResponse<T>>;
208
+ requestCreateWithFile<T = unknown>(endpoint: string, data: unknown, file: File | Blob, filename?: string, options?: ApiWriteOptions): Promise<PayloadMutationResponse<T>>;
213
209
  /**
214
210
  * Update document with file upload
215
211
  * PATCH /api/{collection}/{id} (multipart/form-data)
216
212
  */
217
- requestUpdateWithFile<T = unknown>(endpoint: string, data: unknown, file: File | Blob, filename?: string): Promise<PayloadMutationResponse<T>>;
213
+ requestUpdateWithFile<T = unknown>(endpoint: string, data: unknown, file: File | Blob, filename?: string, options?: ApiWriteOptions): Promise<PayloadMutationResponse<T>>;
218
214
  }
219
215
  declare class ServerCollectionClient extends CollectionClient<ServerCollection> {
220
216
  from<T extends ServerCollection>(collection: T): ServerCollectionQueryBuilder<T>;
@@ -1,8 +1,8 @@
1
- import { cU as DebugConfig, c_ as RetryConfig, cN as ApiQueryOptions, cX as PayloadFindResponse, cY as PayloadMutationResponse, dc as ApiDeleteOptions, dd as PublicReadQueryOptions } from './types-DdlhpNVv.js';
2
- import './payload-types-DTAaWKrp.js';
1
+ import { dd as DebugConfig, dj as RetryConfig, d6 as ApiQueryOptions, dg as PayloadFindResponse, dh as PayloadMutationResponse, dy as ApiDocumentWriteOptions, dz as ApiWriteOptions, dA as ApiDeleteOptions, dB as PublicReadQueryOptions } from './types-Cmnxxvuv.js';
2
+ import './payload-types-BRg8Yary.js';
3
3
  import { GenerateMetadataOptions, Metadata } from './metadata.js';
4
- import { C as Collection, S as ServerCollection, P as PublicCollection } from './const-ty8u0TDI.js';
5
- import { C as CollectionType } from './types-DX8Z44yQ.js';
4
+ import { C as Collection, S as ServerCollection, P as PublicCollection } from './const-BJBK7jBl.js';
5
+ import { C as CollectionType } from './types-DLjSqL0P.js';
6
6
 
7
7
  interface FetchOptions extends RequestInit {
8
8
  apiUrl?: string;
@@ -90,21 +90,17 @@ declare class CollectionQueryBuilder<T extends Collection> {
90
90
  /**
91
91
  * Create a new document
92
92
  * POST /api/{collection}
93
+ * Pass `locale` to write localized fields in a tenant-enabled locale.
93
94
  * @returns Payload CMS mutation response with doc and message
94
95
  */
95
- create(data: Partial<CollectionType<T>>, options?: {
96
- file?: File | Blob;
97
- filename?: string;
98
- }): Promise<PayloadMutationResponse<CollectionType<T>>>;
96
+ create(data: Partial<CollectionType<T>>, options?: ApiDocumentWriteOptions): Promise<PayloadMutationResponse<CollectionType<T>>>;
99
97
  /**
100
98
  * Update a document by ID
101
99
  * PATCH /api/{collection}/{id}
100
+ * Pass `locale` to write localized fields in a tenant-enabled locale.
102
101
  * @returns Payload CMS mutation response with doc and message
103
102
  */
104
- update(id: string, data: Partial<CollectionType<T>>, options?: {
105
- file?: File | Blob;
106
- filename?: string;
107
- }): Promise<PayloadMutationResponse<CollectionType<T>>>;
103
+ update(id: string, data: Partial<CollectionType<T>>, options?: ApiDocumentWriteOptions): Promise<PayloadMutationResponse<CollectionType<T>>>;
108
104
  /**
109
105
  * Count documents
110
106
  * GET /api/{collection}/count
@@ -130,7 +126,7 @@ declare class CollectionQueryBuilder<T extends Collection> {
130
126
  * PATCH /api/{collection}
131
127
  * @returns Payload CMS find response with updated docs
132
128
  */
133
- updateMany(where: ApiQueryOptions['where'], data: Partial<CollectionType<T>>): Promise<PayloadFindResponse<CollectionType<T>>>;
129
+ updateMany(where: ApiQueryOptions['where'], data: Partial<CollectionType<T>>, options?: ApiWriteOptions): Promise<PayloadFindResponse<CollectionType<T>>>;
134
130
  /**
135
131
  * Delete a document by ID
136
132
  * DELETE /api/{collection}/{id}
@@ -172,12 +168,12 @@ declare class CollectionClient<TCollection extends Collection = PublicCollection
172
168
  * Create document
173
169
  * POST /api/{collection}
174
170
  */
175
- requestCreate<T = unknown>(endpoint: string, data?: unknown): Promise<PayloadMutationResponse<T>>;
171
+ requestCreate<T = unknown>(endpoint: string, data?: unknown, options?: ApiWriteOptions): Promise<PayloadMutationResponse<T>>;
176
172
  /**
177
173
  * Update document
178
174
  * PATCH /api/{collection}/{id}
179
175
  */
180
- requestUpdate<T = unknown>(endpoint: string, data?: unknown): Promise<PayloadMutationResponse<T>>;
176
+ requestUpdate<T = unknown>(endpoint: string, data?: unknown, options?: ApiWriteOptions): Promise<PayloadMutationResponse<T>>;
181
177
  /**
182
178
  * Count documents
183
179
  * GET /api/{collection}/count
@@ -192,7 +188,7 @@ declare class CollectionClient<TCollection extends Collection = PublicCollection
192
188
  requestUpdateMany<T = unknown>(endpoint: string, data: {
193
189
  where?: ApiQueryOptions['where'];
194
190
  data: unknown;
195
- }): Promise<PayloadFindResponse<T>>;
191
+ }, options?: ApiWriteOptions): Promise<PayloadFindResponse<T>>;
196
192
  /**
197
193
  * Delete document
198
194
  * DELETE /api/{collection}/{id}
@@ -209,12 +205,12 @@ declare class CollectionClient<TCollection extends Collection = PublicCollection
209
205
  * Create document with file upload
210
206
  * POST /api/{collection} (multipart/form-data)
211
207
  */
212
- requestCreateWithFile<T = unknown>(endpoint: string, data: unknown, file: File | Blob, filename?: string): Promise<PayloadMutationResponse<T>>;
208
+ requestCreateWithFile<T = unknown>(endpoint: string, data: unknown, file: File | Blob, filename?: string, options?: ApiWriteOptions): Promise<PayloadMutationResponse<T>>;
213
209
  /**
214
210
  * Update document with file upload
215
211
  * PATCH /api/{collection}/{id} (multipart/form-data)
216
212
  */
217
- requestUpdateWithFile<T = unknown>(endpoint: string, data: unknown, file: File | Blob, filename?: string): Promise<PayloadMutationResponse<T>>;
213
+ requestUpdateWithFile<T = unknown>(endpoint: string, data: unknown, file: File | Blob, filename?: string, options?: ApiWriteOptions): Promise<PayloadMutationResponse<T>>;
218
214
  }
219
215
  declare class ServerCollectionClient extends CollectionClient<ServerCollection> {
220
216
  from<T extends ServerCollection>(collection: T): ServerCollectionQueryBuilder<T>;
@@ -1,4 +1,4 @@
1
- import './payload-types-DTAaWKrp.js';
1
+ import './payload-types-BRg8Yary.js';
2
2
 
3
3
  /**
4
4
  * Internal collections that should not be exposed via SDK.
@@ -1,4 +1,4 @@
1
- import './payload-types-DTAaWKrp.cjs';
1
+ import './payload-types-BRg8Yary.cjs';
2
2
 
3
3
  /**
4
4
  * Internal collections that should not be exposed via SDK.
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var server_exports = {};
22
22
  __export(server_exports, {
23
23
  fetchEmbeddedAdminJwks: () => fetchEmbeddedAdminJwks,
24
+ verifyEmbeddedAdminExecution: () => verifyEmbeddedAdminExecution,
24
25
  verifyEmbeddedAdminSession: () => verifyEmbeddedAdminSession
25
26
  });
26
27
  module.exports = __toCommonJS(server_exports);
@@ -113,6 +114,7 @@ var COMMERCE_ERROR_CODES = [
113
114
  "cart_not_active",
114
115
  "cart_locked",
115
116
  "cart_empty",
117
+ "shipping_address_required",
116
118
  "cart_market_unavailable",
117
119
  "cart_market_mismatch",
118
120
  "checkout_not_open",
@@ -129,6 +131,7 @@ var COMMERCE_ERROR_CODES = [
129
131
  "price_changed",
130
132
  "pricing_fact_in_use",
131
133
  "insufficient_stock",
134
+ "credit_insufficient",
132
135
  "reservation_conflict",
133
136
  "stock_lock_unavailable",
134
137
  "variant_not_found",
@@ -207,9 +210,56 @@ var ValidationError = class extends SDKError {
207
210
  };
208
211
  var createValidationError = (message, details, userMessage, suggestion, status) => new ValidationError(message, details, userMessage, suggestion, status);
209
212
 
213
+ // src/embedded-admin/actions.ts
214
+ var EMBEDDED_ADMIN_EXECUTION_AUDIENCE_PREFIX = "urn:01-software:embedded-admin-execution:";
215
+ var EMBEDDED_ADMIN_MAX_SELECTED_IDS = 100;
216
+ var ACTION_ID = /^[a-z][a-z0-9_-]{0,63}$/;
217
+ var COLLECTION = /^[a-z][a-z0-9-]{0,63}$/;
218
+ var EXECUTION_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
219
+ function recordWithKeys(value, keys) {
220
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
221
+ throw createValidationError("Invalid embedded admin action context.");
222
+ }
223
+ const record = value;
224
+ if (Object.keys(record).some((key) => !keys.includes(key))) {
225
+ throw createValidationError("Invalid embedded admin action context.");
226
+ }
227
+ return record;
228
+ }
229
+ function normalizeEmbeddedAdminExecutionContext(value) {
230
+ const input = recordWithKeys(value, [
231
+ "executionId",
232
+ "expiresAt",
233
+ "actionId",
234
+ "collection",
235
+ "selectedIds"
236
+ ]);
237
+ if (typeof input.executionId !== "string" || !EXECUTION_ID.test(input.executionId) || typeof input.expiresAt !== "number" || !Number.isSafeInteger(input.expiresAt) || input.expiresAt <= 0 || typeof input.actionId !== "string" || !ACTION_ID.test(input.actionId) || typeof input.collection !== "string" || !COLLECTION.test(input.collection) || !Array.isArray(input.selectedIds) || input.selectedIds.length > EMBEDDED_ADMIN_MAX_SELECTED_IDS || input.selectedIds.some(
238
+ (id) => typeof id !== "string" || !id || id.length > 128 || id.trim() !== id || Array.from(id).some(
239
+ (character) => character.charCodeAt(0) <= 32 || character.charCodeAt(0) === 127
240
+ )
241
+ ) || new Set(input.selectedIds).size !== input.selectedIds.length)
242
+ throw createValidationError("Invalid embedded admin execution context.");
243
+ return {
244
+ executionId: input.executionId,
245
+ expiresAt: input.expiresAt,
246
+ actionId: input.actionId,
247
+ collection: input.collection,
248
+ selectedIds: [...input.selectedIds].sort()
249
+ };
250
+ }
251
+ function embeddedAdminExecutionContextsEqual(left, right) {
252
+ try {
253
+ return JSON.stringify(normalizeEmbeddedAdminExecutionContext(left)) === JSON.stringify(normalizeEmbeddedAdminExecutionContext(right));
254
+ } catch {
255
+ return false;
256
+ }
257
+ }
258
+
210
259
  // src/embedded-admin/index.ts
211
260
  var EMBEDDED_ADMIN_SESSION_TTL_SECONDS = 60;
212
261
  var EMBEDDED_ADMIN_APP_KEY = "primary";
262
+ var MAX_PATH_LENGTH = 512;
213
263
  var EMBEDDED_ADMIN_TENANT_ROLES = [
214
264
  "tenant-admin",
215
265
  "tenant-editor",
@@ -236,6 +286,23 @@ function normalizeEmbeddedAdminExactOrigin(value, options = {}) {
236
286
  if (parsed.pathname !== "/" || trimmed.endsWith("/")) return null;
237
287
  return parsed.origin;
238
288
  }
289
+ function normalizeEmbeddedAdminRelativePath(value) {
290
+ if (typeof value !== "string") return null;
291
+ const trimmed = value.trim();
292
+ if (!trimmed.startsWith("/") || trimmed.startsWith("//") || trimmed.length > MAX_PATH_LENGTH) {
293
+ return null;
294
+ }
295
+ let parsed;
296
+ try {
297
+ parsed = new URL(trimmed, "https://embedded.invalid");
298
+ } catch {
299
+ return null;
300
+ }
301
+ if (parsed.origin !== "https://embedded.invalid" || parsed.pathname.startsWith("//") || parsed.search || parsed.hash || parsed.username || parsed.password) {
302
+ return null;
303
+ }
304
+ return parsed.pathname;
305
+ }
239
306
 
240
307
  // src/embedded-admin/server.ts
241
308
  var ALGORITHMS = ["RS256", "ES256"];
@@ -279,6 +346,53 @@ async function fetchEmbeddedAdminJwks(consoleOrigin, options = {}) {
279
346
  return parseJwks(JSON.parse(text));
280
347
  }
281
348
  async function verifyEmbeddedAdminSession(options) {
349
+ const claims = await verifySession(options);
350
+ if ("protocol_version" in claims || "execution_context" in claims || "token_use" in claims) {
351
+ throw new Error("An action assertion requires execution verification.");
352
+ }
353
+ return claims;
354
+ }
355
+ async function verifyEmbeddedAdminExecution(options) {
356
+ if (typeof options.consumeExecution !== "function") {
357
+ throw createValidationError("A durable execution consumer is required.");
358
+ }
359
+ const clock = options.clock ?? (() => Math.floor(Date.now() / 1e3));
360
+ const currentSecond = () => {
361
+ const now = clock();
362
+ if (!Number.isSafeInteger(now) || now < 0)
363
+ throw createValidationError("A trusted Unix-second clock is required.");
364
+ return now;
365
+ };
366
+ const claims = await verifySession({ ...options, now: currentSecond() }, true);
367
+ const execution = normalizeEmbeddedAdminExecutionContext(
368
+ claims.execution_context
369
+ );
370
+ const frame = new URL(options.frameUrl);
371
+ const path = normalizeEmbeddedAdminRelativePath(frame.pathname);
372
+ if (claims.protocol_version !== 2 || !["super-admin", "tenant-admin"].includes(claims.tenant_role) || "token_use" in claims || !path || frame.origin !== claims.dest || `${frame.origin}${path}` !== options.frameUrl || claims.frame_url !== options.frameUrl || claims.exp !== execution.expiresAt || currentSecond() >= execution.expiresAt || !embeddedAdminExecutionContextsEqual(execution, options.execution))
373
+ throw new Error(
374
+ "Embedded admin execution context does not match its assertion."
375
+ );
376
+ const consumed = await options.consumeExecution({
377
+ issuer: claims.iss,
378
+ tenantId: claims.tenant_id,
379
+ operatorId: claims.operator_id,
380
+ appKey: claims.app_key,
381
+ executionId: execution.executionId,
382
+ expiresAt: execution.expiresAt
383
+ });
384
+ if (consumed !== true)
385
+ throw new Error("Embedded admin execution was already consumed.");
386
+ if (currentSecond() >= execution.expiresAt)
387
+ throw new Error("Embedded admin execution expired during consumption.");
388
+ return {
389
+ ...claims,
390
+ protocol_version: 2,
391
+ frame_url: options.frameUrl,
392
+ execution_context: execution
393
+ };
394
+ }
395
+ async function verifySession(options, executionPurpose = false) {
282
396
  const allowedRoles = options.allowedRoles ?? ["super-admin", "tenant-admin"];
283
397
  if (!Array.isArray(allowedRoles) || allowedRoles.some(
284
398
  (role) => !["super-admin", ...EMBEDDED_ADMIN_TENANT_ROLES].includes(role)
@@ -298,6 +412,7 @@ async function verifyEmbeddedAdminSession(options) {
298
412
  "consoleOrigin and destination must be exact origins."
299
413
  );
300
414
  }
415
+ const audience = executionPurpose ? `${EMBEDDED_ADMIN_EXECUTION_AUDIENCE_PREFIX}${destination}` : destination;
301
416
  if (typeof options.channelId !== "string" || options.channelId.length < 16 || options.channelId.length > 128 || typeof options.token !== "string" || options.token.length === 0) {
302
417
  throw createValidationError("Embedded admin session input is invalid.");
303
418
  }
@@ -311,7 +426,7 @@ async function verifyEmbeddedAdminSession(options) {
311
426
  (0, import_jose.createLocalJWKSet)(jwks),
312
427
  {
313
428
  algorithms: [...ALGORITHMS],
314
- audience: destination,
429
+ audience,
315
430
  clockTolerance: 0,
316
431
  currentDate: new Date(currentSecond * 1e3),
317
432
  issuer,
@@ -319,7 +434,7 @@ async function verifyEmbeddedAdminSession(options) {
319
434
  }
320
435
  );
321
436
  const lifetime = typeof payload.exp === "number" && typeof payload.iat === "number" ? payload.exp - payload.iat : Number.POSITIVE_INFINITY;
322
- if (typeof protectedHeader.kid !== "string" || protectedHeader.kid.length === 0 || !Number.isInteger(payload.iat) || !Number.isInteger(payload.nbf) || !Number.isInteger(payload.exp) || payload.iat > currentSecond || lifetime <= 0 || lifetime > EMBEDDED_ADMIN_SESSION_TTL_SECONDS || payload.nbf !== payload.iat || payload.aud !== destination || typeof payload.jti !== "string" || payload.jti.length === 0 || payload.app_key !== EMBEDDED_ADMIN_APP_KEY || payload.channel_id !== options.channelId || payload.dest !== destination || typeof payload.operator_id !== "string" || payload.operator_id.length === 0 || payload.sub !== payload.operator_id || typeof payload.tenant_id !== "string" || payload.tenant_id.length === 0 || !["super-admin", ...EMBEDDED_ADMIN_TENANT_ROLES].includes(
437
+ if (typeof protectedHeader.kid !== "string" || protectedHeader.kid.length === 0 || !Number.isInteger(payload.iat) || !Number.isInteger(payload.nbf) || !Number.isInteger(payload.exp) || payload.iat > currentSecond || lifetime <= 0 || lifetime > EMBEDDED_ADMIN_SESSION_TTL_SECONDS || payload.nbf !== payload.iat || payload.aud !== audience || typeof payload.jti !== "string" || payload.jti.length === 0 || payload.app_key !== EMBEDDED_ADMIN_APP_KEY || payload.channel_id !== options.channelId || payload.dest !== destination || typeof payload.operator_id !== "string" || payload.operator_id.length === 0 || payload.sub !== payload.operator_id || typeof payload.tenant_id !== "string" || payload.tenant_id.length === 0 || !["super-admin", ...EMBEDDED_ADMIN_TENANT_ROLES].includes(
323
438
  payload.tenant_role
324
439
  ) || !allowedRoles.includes(payload.tenant_role)) {
325
440
  throw new Error("Embedded admin session claims are invalid.");