@sd-jwt/sd-jwt-vc 0.1.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.mjs ADDED
@@ -0,0 +1,734 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
+ var __reflectGet = Reflect.get;
9
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
+ var __spreadValues = (a, b) => {
11
+ for (var prop in b || (b = {}))
12
+ if (__hasOwnProp.call(b, prop))
13
+ __defNormalProp(a, prop, b[prop]);
14
+ if (__getOwnPropSymbols)
15
+ for (var prop of __getOwnPropSymbols(b)) {
16
+ if (__propIsEnum.call(b, prop))
17
+ __defNormalProp(a, prop, b[prop]);
18
+ }
19
+ return a;
20
+ };
21
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
22
+ var __objRest = (source, exclude) => {
23
+ var target = {};
24
+ for (var prop in source)
25
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
26
+ target[prop] = source[prop];
27
+ if (source != null && __getOwnPropSymbols)
28
+ for (var prop of __getOwnPropSymbols(source)) {
29
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
30
+ target[prop] = source[prop];
31
+ }
32
+ return target;
33
+ };
34
+ var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj);
35
+ var __async = (__this, __arguments, generator) => {
36
+ return new Promise((resolve, reject) => {
37
+ var fulfilled = (value) => {
38
+ try {
39
+ step(generator.next(value));
40
+ } catch (e) {
41
+ reject(e);
42
+ }
43
+ };
44
+ var rejected = (value) => {
45
+ try {
46
+ step(generator.throw(value));
47
+ } catch (e) {
48
+ reject(e);
49
+ }
50
+ };
51
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
52
+ step((generator = generator.apply(__this, __arguments)).next());
53
+ });
54
+ };
55
+
56
+ // src/sd-jwt-vc-instance.ts
57
+ import {
58
+ getListFromStatusListJWT,
59
+ SLException
60
+ } from "@owf/token-status-list";
61
+ import {
62
+ ensureError,
63
+ Jwt,
64
+ SDJWTException,
65
+ SDJwt,
66
+ SDJwtInstance
67
+ } from "@sd-jwt/core";
68
+ import z2 from "zod";
69
+
70
+ // src/sd-jwt-vc-type-metadata-format.ts
71
+ import { z } from "zod";
72
+ var BackgroundImageSchema = z.looseObject({
73
+ /** REQUIRED. A URI pointing to the background image. */
74
+ uri: z.string(),
75
+ /** OPTIONAL. An "integrity metadata" string as described in Section 7. */
76
+ "uri#integrity": z.string().optional()
77
+ });
78
+ var LogoSchema = z.looseObject({
79
+ /** REQUIRED. A URI pointing to the logo image. */
80
+ uri: z.string(),
81
+ /** OPTIONAL. An "integrity metadata" string as described in Section 7. */
82
+ "uri#integrity": z.string().optional(),
83
+ /** OPTIONAL. A string containing alternative text for the logo image. */
84
+ alt_text: z.string().optional()
85
+ });
86
+ var SimpleRenderingSchema = z.looseObject({
87
+ /** OPTIONAL. Logo metadata to display for the credential. */
88
+ logo: LogoSchema.optional(),
89
+ /** OPTIONAL. RGB color value for the credential background (e.g., "#FFFFFF"). */
90
+ background_color: z.string().optional(),
91
+ /** OPTIONAL. RGB color value for the credential text (e.g., "#000000"). */
92
+ text_color: z.string().optional(),
93
+ /** OPTIONAL. An object containing information about the background image to be displayed for the type. */
94
+ background_image: BackgroundImageSchema.optional()
95
+ });
96
+ var OrientationSchema = z.enum(["portrait", "landscape"]);
97
+ var ColorSchemeSchema = z.enum(["light", "dark"]);
98
+ var ContrastSchema = z.enum(["normal", "high"]);
99
+ var SvgTemplatePropertiesSchema = z.looseObject({
100
+ /** OPTIONAL. Orientation optimized for the template. */
101
+ orientation: OrientationSchema.optional(),
102
+ /** OPTIONAL. Color scheme optimized for the template. */
103
+ color_scheme: ColorSchemeSchema.optional(),
104
+ /** OPTIONAL. Contrast level optimized for the template. */
105
+ contrast: ContrastSchema.optional()
106
+ });
107
+ var SvgTemplateRenderingSchema = z.looseObject({
108
+ /** REQUIRED. A URI pointing to the SVG template. */
109
+ uri: z.string(),
110
+ /** OPTIONAL. An "integrity metadata" string as described in Section 7. */
111
+ "uri#integrity": z.string().optional(),
112
+ /** REQUIRED if more than one SVG template is present. */
113
+ properties: SvgTemplatePropertiesSchema.optional()
114
+ });
115
+ var RenderingSchema = z.looseObject({
116
+ /** OPTIONAL. Simple rendering metadata. */
117
+ simple: SimpleRenderingSchema.optional(),
118
+ /** OPTIONAL. Array of SVG template rendering objects. */
119
+ svg_templates: z.array(SvgTemplateRenderingSchema).optional(),
120
+ /**
121
+ * OPTIONAL. Array of SVG template rendering objects.
122
+ * @deprecated use `svg_templates` (plural) instead.
123
+ */
124
+ svg_template: z.array(SvgTemplateRenderingSchema).optional()
125
+ }).transform((_a) => {
126
+ var _b = _a, { svg_template, svg_templates } = _b, rest = __objRest(_b, ["svg_template", "svg_templates"]);
127
+ return __spreadProps(__spreadValues({}, rest), {
128
+ svg_templates: svg_templates != null ? svg_templates : svg_template
129
+ });
130
+ });
131
+ var DisplaySchema = z.looseObject({
132
+ /**
133
+ * Language tag according to RFC 5646 (e.g., "en", "de").
134
+ * @deprecated - use `locale` instead
135
+ */
136
+ lang: z.string().optional(),
137
+ /**
138
+ * REQUIRED (preferred). Language tag according to RFC 5646.
139
+ * Alias for `lang` - either `lang` or `locale` must be provided.
140
+ */
141
+ locale: z.string().optional(),
142
+ /** REQUIRED. Human-readable name for the credential type. */
143
+ name: z.string(),
144
+ /** OPTIONAL. Description of the credential type for end users. */
145
+ description: z.string().optional(),
146
+ /** OPTIONAL. Rendering information (simple or SVG) for the credential. */
147
+ rendering: RenderingSchema.optional()
148
+ }).transform((_a) => {
149
+ var _b = _a, { lang, locale } = _b, rest = __objRest(_b, ["lang", "locale"]);
150
+ return __spreadProps(__spreadValues({}, rest), {
151
+ locale: locale != null ? locale : lang
152
+ });
153
+ }).refine(({ locale }) => locale !== void 0, {
154
+ message: "Either locale (preferred) or lang (spec name, deprecated) MUST be defined on claim display entry."
155
+ });
156
+ var ClaimPathSchema = z.array(z.string().nullable());
157
+ var ClaimDisplaySchema = z.looseObject({
158
+ /**
159
+ * Language tag according to RFC 5646.
160
+ * @deprecated - use `locale` instead
161
+ */
162
+ lang: z.string().optional(),
163
+ /**
164
+ * REQUIRED (preferred). Language tag according to RFC 5646.
165
+ * Alias for `lang` - either `lang` or `locale` must be provided.
166
+ */
167
+ locale: z.string().optional(),
168
+ /** REQUIRED. Human-readable label for the claim. */
169
+ label: z.string().optional(),
170
+ /**
171
+ * Human-readable label for the claim.
172
+ * @deprecated - use `label` instead
173
+ */
174
+ name: z.string().optional(),
175
+ /** OPTIONAL. Description of the claim for end users. */
176
+ description: z.string().optional()
177
+ }).transform((_a) => {
178
+ var _b = _a, { lang, name, label, locale } = _b, rest = __objRest(_b, ["lang", "name", "label", "locale"]);
179
+ return __spreadProps(__spreadValues({}, rest), {
180
+ locale: locale != null ? locale : lang,
181
+ label: label != null ? label : name
182
+ });
183
+ }).refine(({ locale }) => locale !== void 0, {
184
+ message: "Either locale (preferred) or lang (deprecated) MUST be defined on claim display entry."
185
+ }).refine(({ label }) => label !== void 0, {
186
+ message: "Either label (preferred) or name (deprecated) MUST be defined on claim display entry."
187
+ });
188
+ var ClaimSelectiveDisclosureSchema = z.enum([
189
+ "always",
190
+ "allowed",
191
+ "never"
192
+ ]);
193
+ var ClaimSchema = z.looseObject({
194
+ /**
195
+ * REQUIRED. Array of one or more paths to the claim in the credential subject.
196
+ * Each path is an array of strings (or null for array elements).
197
+ */
198
+ path: ClaimPathSchema,
199
+ /** OPTIONAL. Display metadata in multiple languages. */
200
+ display: z.array(ClaimDisplaySchema).optional(),
201
+ /** OPTIONAL. Controls whether the claim must, may, or must not be selectively disclosed. */
202
+ sd: ClaimSelectiveDisclosureSchema.optional(),
203
+ /**
204
+ * OPTIONAL. A boolean indicating whether the claim must be present in the Unsecured Payload
205
+ * of the SD-JWT VC. Default is false if not specified.
206
+ */
207
+ mandatory: z.boolean().optional(),
208
+ /**
209
+ * OPTIONAL. Unique string identifier for referencing the claim in an SVG template.
210
+ * Must consist of alphanumeric characters or underscores and must not start with a digit.
211
+ */
212
+ svg_id: z.string().optional()
213
+ });
214
+ var TypeMetadataFormatSchema = z.looseObject({
215
+ /** REQUIRED. A URI uniquely identifying the credential type. */
216
+ vct: z.string(),
217
+ /** OPTIONAL. Human-readable name for developers. */
218
+ name: z.string().optional(),
219
+ /** OPTIONAL. Human-readable description for developers. */
220
+ description: z.string().optional(),
221
+ /** OPTIONAL. URI of another type that this one extends. */
222
+ extends: z.string().optional(),
223
+ /** OPTIONAL. Integrity metadata for the 'extends' field. */
224
+ "extends#integrity": z.string().optional(),
225
+ /** OPTIONAL. Array of localized display metadata for the type. */
226
+ display: z.array(DisplaySchema).optional(),
227
+ /** OPTIONAL. Array of claim metadata. */
228
+ claims: z.array(ClaimSchema).optional()
229
+ });
230
+
231
+ // src/sd-jwt-vc-instance.ts
232
+ var SDJwtVcInstance = class _SDJwtVcInstance extends SDJwtInstance {
233
+ constructor(userConfig) {
234
+ super(userConfig);
235
+ /**
236
+ * The type of the SD-JWT-VC set in the header.typ field.
237
+ */
238
+ this.type = "dc+sd-jwt";
239
+ this.userConfig = {};
240
+ if (userConfig) {
241
+ this.userConfig = userConfig;
242
+ }
243
+ }
244
+ /**
245
+ * Validates if the disclosure frame attempts to selectively disclose protected SD-JWT-VC claims.
246
+ * @param disclosureFrame
247
+ */
248
+ validateDisclosureFrame(disclosureFrame) {
249
+ if ((disclosureFrame == null ? void 0 : disclosureFrame._sd) && Array.isArray(disclosureFrame._sd) && disclosureFrame._sd.length > 0) {
250
+ const reservedNames = ["iss", "nbf", "exp", "cnf", "vct", "status"];
251
+ const reservedNamesInDisclosureFrame = disclosureFrame._sd.filter(
252
+ (key) => reservedNames.includes(String(key))
253
+ );
254
+ if (reservedNamesInDisclosureFrame.length > 0) {
255
+ throw new SDJWTException("Cannot disclose protected field");
256
+ }
257
+ }
258
+ }
259
+ /**
260
+ * Fetches the status list from the uri with a timeout of 10 seconds.
261
+ * @param uri The URI to fetch from.
262
+ * @returns A promise that resolves to a compact JWT.
263
+ */
264
+ statusListFetcher(uri) {
265
+ return __async(this, null, function* () {
266
+ var _a;
267
+ const controller = new AbortController();
268
+ const timeoutId = setTimeout(() => controller.abort(), 1e4);
269
+ try {
270
+ const response = yield fetch(uri, {
271
+ signal: controller.signal,
272
+ headers: { Accept: "application/statuslist+jwt" }
273
+ });
274
+ if (!response.ok) {
275
+ throw new Error(
276
+ `Error fetching status list: ${response.status} ${yield response.text()}`
277
+ );
278
+ }
279
+ if (!((_a = response.headers.get("content-type")) == null ? void 0 : _a.includes("application/statuslist+jwt"))) {
280
+ throw new Error("Invalid content type");
281
+ }
282
+ return response.text();
283
+ } finally {
284
+ clearTimeout(timeoutId);
285
+ }
286
+ });
287
+ }
288
+ /**
289
+ * Validates the status, throws an error if the status is not 0.
290
+ * @param status
291
+ * @returns
292
+ */
293
+ statusValidator(status) {
294
+ return __async(this, null, function* () {
295
+ if (status !== 0) throw new SDJWTException("Status is not valid");
296
+ return Promise.resolve();
297
+ });
298
+ }
299
+ /**
300
+ * Verifies the SD-JWT-VC. It will validate the signature, the keybindings when required, the status, and the VCT.
301
+ * @param currentDate current time in seconds
302
+ */
303
+ verify(encodedSDJwt, options) {
304
+ return __async(this, null, function* () {
305
+ const result = yield __superGet(_SDJwtVcInstance.prototype, this, "verify").call(this, encodedSDJwt, options).then((res) => {
306
+ return {
307
+ payload: res.payload,
308
+ header: res.header,
309
+ kb: res.kb
310
+ };
311
+ });
312
+ yield this.verifyStatus(result, options);
313
+ if (this.userConfig.loadTypeMetadataFormat) {
314
+ const resolvedTypeMetadata = yield this.fetchVct(result);
315
+ result.typeMetadata = resolvedTypeMetadata;
316
+ }
317
+ return result;
318
+ });
319
+ }
320
+ /**
321
+ * Safe verification that collects all errors instead of failing fast.
322
+ * Returns a result object with either the verified data or an array of all errors.
323
+ * This includes SD-JWT-VC specific validations like status and VCT metadata.
324
+ *
325
+ * @param encodedSDJwt - The encoded SD-JWT-VC to verify
326
+ * @param options - Verification options
327
+ * @returns A SafeVerifyResult containing either success data or collected errors
328
+ */
329
+ safeVerify(encodedSDJwt, options) {
330
+ return __async(this, null, function* () {
331
+ const errors = [];
332
+ const addError = (code, message, details) => {
333
+ errors.push({ code, message, details });
334
+ };
335
+ const baseResult = yield __superGet(_SDJwtVcInstance.prototype, this, "safeVerify").call(this, encodedSDJwt, options);
336
+ if (!baseResult.success) {
337
+ errors.push(...baseResult.errors);
338
+ }
339
+ let result;
340
+ if (baseResult.success) {
341
+ result = {
342
+ payload: baseResult.data.payload,
343
+ header: baseResult.data.header,
344
+ kb: baseResult.data.kb
345
+ };
346
+ } else {
347
+ try {
348
+ const { payload, header } = yield SDJwt.extractJwt(encodedSDJwt);
349
+ if (payload) {
350
+ result = {
351
+ payload,
352
+ header,
353
+ kb: void 0
354
+ };
355
+ }
356
+ } catch (e) {
357
+ }
358
+ }
359
+ if (result) {
360
+ try {
361
+ yield this.verifyStatus(result, options);
362
+ } catch (e) {
363
+ const error = ensureError(e);
364
+ const errorMessage = error.message;
365
+ if (errorMessage.includes("Status is not valid")) {
366
+ addError("STATUS_INVALID", errorMessage, error);
367
+ } else {
368
+ addError(
369
+ "STATUS_VERIFICATION_FAILED",
370
+ `Status verification failed: ${errorMessage}`,
371
+ error
372
+ );
373
+ }
374
+ }
375
+ if (this.userConfig.loadTypeMetadataFormat) {
376
+ try {
377
+ const resolvedTypeMetadata = yield this.fetchVct(result);
378
+ if (result) {
379
+ result.typeMetadata = resolvedTypeMetadata;
380
+ }
381
+ } catch (e) {
382
+ addError(
383
+ "VCT_VERIFICATION_FAILED",
384
+ `VCT verification failed: ${ensureError(e).message}`,
385
+ e
386
+ );
387
+ }
388
+ }
389
+ }
390
+ if (errors.length > 0) {
391
+ return { success: false, errors };
392
+ }
393
+ if (!result) {
394
+ return {
395
+ success: false,
396
+ errors: [
397
+ {
398
+ code: "INVALID_SD_JWT",
399
+ message: "Failed to construct verification result"
400
+ }
401
+ ]
402
+ };
403
+ }
404
+ return {
405
+ success: true,
406
+ data: result
407
+ };
408
+ });
409
+ }
410
+ /**
411
+ * Gets VCT Metadata of the raw SD-JWT-VC. Returns the type metadata format. If the SD-JWT-VC is invalid or does not contain a vct claim, an error is thrown.
412
+ *
413
+ * It may return `undefined` if the fetcher returned an undefined value (instead of throwing an error).
414
+ *
415
+ * @param encodedSDJwt
416
+ * @returns
417
+ */
418
+ getVct(encodedSDJwt) {
419
+ return __async(this, null, function* () {
420
+ const { payload, header } = yield SDJwt.extractJwt(encodedSDJwt);
421
+ if (!payload) {
422
+ throw new SDJWTException("JWT payload is missing");
423
+ }
424
+ const result = {
425
+ payload,
426
+ header,
427
+ kb: void 0
428
+ };
429
+ return this.fetchVct(result);
430
+ });
431
+ }
432
+ /**
433
+ * Validates the integrity of the response if the integrity is passed. If the integrity does not match, an error is thrown.
434
+ * @param integrity
435
+ * @param response
436
+ */
437
+ validateIntegrity(response, url, integrity) {
438
+ return __async(this, null, function* () {
439
+ if (!integrity) return;
440
+ const arrayBuffer = yield response.arrayBuffer();
441
+ const alg = integrity.split("-")[0];
442
+ if (!this.userConfig.hasher) {
443
+ throw new SDJWTException("Hasher not found");
444
+ }
445
+ const hashBuffer = yield this.userConfig.hasher(arrayBuffer, alg);
446
+ const integrityHash = integrity.split("-")[1];
447
+ const hash = Array.from(new Uint8Array(hashBuffer)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
448
+ if (hash !== integrityHash) {
449
+ throw new Error(
450
+ `Integrity check for ${url} failed: is ${hash}, but expected ${integrityHash}`
451
+ );
452
+ }
453
+ });
454
+ }
455
+ /**
456
+ * Fetches the content from the url with a timeout of 10 seconds.
457
+ * @param url
458
+ * @returns
459
+ */
460
+ fetchWithIntegrity(url, integrity) {
461
+ return __async(this, null, function* () {
462
+ var _a;
463
+ try {
464
+ const response = yield fetch(url, {
465
+ signal: AbortSignal.timeout((_a = this.userConfig.timeout) != null ? _a : 1e4)
466
+ });
467
+ if (!response.ok) {
468
+ const errorText = yield response.text();
469
+ throw new Error(
470
+ `Error fetching ${url}: ${response.status} ${response.statusText} - ${errorText}`
471
+ );
472
+ }
473
+ yield this.validateIntegrity(response.clone(), url, integrity);
474
+ const data = yield response.json();
475
+ return data;
476
+ } catch (e) {
477
+ const error = ensureError(e);
478
+ if (error.name === "TimeoutError") {
479
+ throw new Error(`Request to ${url} timed out`);
480
+ }
481
+ throw error;
482
+ }
483
+ });
484
+ }
485
+ /**
486
+ * Verifies the VCT of the SD-JWT-VC. Returns the type metadata format.
487
+ * Resolves the full extends chain according to spec sections 6.4, 8.2, and 9.5.
488
+ * @param result
489
+ * @returns
490
+ */
491
+ fetchVct(result) {
492
+ return __async(this, null, function* () {
493
+ const typeMetadataFormat = yield this.fetchSingleVct(
494
+ result.payload.vct,
495
+ result.payload["vct#integrity"]
496
+ );
497
+ if (!typeMetadataFormat) return void 0;
498
+ if (!typeMetadataFormat.extends) {
499
+ return {
500
+ mergedTypeMetadata: typeMetadataFormat,
501
+ typeMetadataChain: [typeMetadataFormat],
502
+ vctValues: [typeMetadataFormat.vct]
503
+ };
504
+ }
505
+ return this.resolveVctExtendsChain(typeMetadataFormat);
506
+ });
507
+ }
508
+ /**
509
+ * Checks if two claim paths are equal by comparing each element.
510
+ * @param path1 First claim path
511
+ * @param path2 Second claim path
512
+ * @returns True if paths are equal, false otherwise
513
+ */
514
+ claimPathsEqual(path1, path2) {
515
+ if (path1.length !== path2.length) return false;
516
+ return path1.every((element, index) => element === path2[index]);
517
+ }
518
+ /**
519
+ * Validates that extending claim metadata respects the constraints from spec section 9.5.1.
520
+ * @param baseClaim The base claim metadata
521
+ * @param extendingClaim The extending claim metadata
522
+ * @throws SDJWTException if validation fails
523
+ */
524
+ validateClaimExtension(baseClaim, extendingClaim) {
525
+ if (baseClaim.sd && extendingClaim.sd) {
526
+ if ((baseClaim.sd === "always" || baseClaim.sd === "never") && baseClaim.sd !== extendingClaim.sd) {
527
+ const pathStr = JSON.stringify(extendingClaim.path);
528
+ throw new SDJWTException(
529
+ `Cannot change 'sd' property from '${baseClaim.sd}' to '${extendingClaim.sd}' for claim at path ${pathStr}`
530
+ );
531
+ }
532
+ }
533
+ }
534
+ /**
535
+ * Merges two type metadata formats, with the extending metadata overriding the base metadata.
536
+ * According to spec section 9.5:
537
+ * - All claim metadata from the extended type are inherited
538
+ * - The child type can add new claims or properties
539
+ * - If the child type defines claim metadata with the same path as the extended type,
540
+ * the child type's object will override the corresponding object from the extended type
541
+ * According to spec section 9.5.1:
542
+ * - sd property can only be changed from 'allowed' (or omitted) to 'always' or 'never'
543
+ * - sd property cannot be changed from 'always' or 'never' to a different value
544
+ * According to spec section 8.2:
545
+ * - If the extending type defines its own display property, the original display metadata is ignored
546
+ * Note: The spec also mentions 'mandatory' property constraints, but this is not currently
547
+ * defined in the Claim type and will be validated when that property is added to the type.
548
+ * @param base The base type metadata format
549
+ * @param extending The extending type metadata format
550
+ * @returns The merged type metadata format
551
+ */
552
+ mergeTypeMetadata(base, extending) {
553
+ var _a, _b;
554
+ const merged = __spreadValues({}, extending);
555
+ if (base.claims || extending.claims) {
556
+ const baseClaims = (_a = base.claims) != null ? _a : [];
557
+ const extendingClaims = (_b = extending.claims) != null ? _b : [];
558
+ for (const extendingClaim of extendingClaims) {
559
+ const matchingBaseClaim = baseClaims.find(
560
+ (baseClaim) => this.claimPathsEqual(baseClaim.path, extendingClaim.path)
561
+ );
562
+ if (matchingBaseClaim) {
563
+ this.validateClaimExtension(matchingBaseClaim, extendingClaim);
564
+ }
565
+ }
566
+ const mergedClaims = [];
567
+ const extendedClaimsWithoutBase = [...extendingClaims];
568
+ for (const baseClaim of baseClaims) {
569
+ const extendingClaimIndex = extendedClaimsWithoutBase.findIndex(
570
+ (extendingClaim2) => this.claimPathsEqual(baseClaim.path, extendingClaim2.path)
571
+ );
572
+ const extendingClaim = extendingClaimIndex !== -1 ? extendedClaimsWithoutBase[extendingClaimIndex] : void 0;
573
+ if (extendingClaim) {
574
+ extendedClaimsWithoutBase.splice(extendingClaimIndex, 1);
575
+ }
576
+ mergedClaims.push(extendingClaim != null ? extendingClaim : baseClaim);
577
+ }
578
+ mergedClaims.push(...extendedClaimsWithoutBase);
579
+ merged.claims = mergedClaims;
580
+ }
581
+ if (!extending.display && base.display) {
582
+ merged.display = base.display;
583
+ }
584
+ return merged;
585
+ }
586
+ /**
587
+ * Resolves the full VCT chain by recursively fetching extended type metadata.
588
+ * Implements security considerations from spec section 10.3 for circular dependencies.
589
+ * @param vct The VCT URI to resolve
590
+ * @param integrity Optional integrity metadata for the VCT
591
+ * @param depth Current depth in the chain
592
+ * @param visitedVcts Set of already visited VCT URIs to detect circular dependencies
593
+ * @returns The fully resolved and merged type metadata format
594
+ */
595
+ resolveVctExtendsChain(_0) {
596
+ return __async(this, arguments, function* (parentTypeMetadata, depth = 1, visitedVcts = new Set(parentTypeMetadata.vct)) {
597
+ var _a;
598
+ const maxDepth = (_a = this.userConfig.maxVctExtendsDepth) != null ? _a : 5;
599
+ if (maxDepth !== -1 && depth > maxDepth) {
600
+ throw new SDJWTException(
601
+ `Maximum VCT extends depth of ${maxDepth} exceeded`
602
+ );
603
+ }
604
+ if (!parentTypeMetadata.extends) {
605
+ throw new SDJWTException(
606
+ `Type metadata for vct '${parentTypeMetadata.vct}' has no 'extends' field. Unable to resolve extended type metadata document.`
607
+ );
608
+ }
609
+ if (visitedVcts.has(parentTypeMetadata.extends)) {
610
+ throw new SDJWTException(
611
+ `Circular dependency detected in VCT extends chain: ${parentTypeMetadata.extends}`
612
+ );
613
+ }
614
+ visitedVcts.add(parentTypeMetadata.extends);
615
+ const extendedTypeMetadata = yield this.fetchSingleVct(
616
+ parentTypeMetadata.extends,
617
+ parentTypeMetadata["extends#integrity"]
618
+ );
619
+ if (!extendedTypeMetadata) {
620
+ throw new SDJWTException(
621
+ `Resolving VCT extends value '${parentTypeMetadata.extends}' resulted in an undefined result.`
622
+ );
623
+ }
624
+ let resolvedTypeMetadata;
625
+ if (extendedTypeMetadata.extends) {
626
+ resolvedTypeMetadata = yield this.resolveVctExtendsChain(
627
+ extendedTypeMetadata,
628
+ depth + 1,
629
+ visitedVcts
630
+ );
631
+ } else {
632
+ resolvedTypeMetadata = {
633
+ mergedTypeMetadata: extendedTypeMetadata,
634
+ typeMetadataChain: [extendedTypeMetadata],
635
+ vctValues: [extendedTypeMetadata.vct]
636
+ };
637
+ }
638
+ const mergedTypeMetadata = this.mergeTypeMetadata(
639
+ resolvedTypeMetadata.mergedTypeMetadata,
640
+ parentTypeMetadata
641
+ );
642
+ return {
643
+ mergedTypeMetadata,
644
+ typeMetadataChain: [
645
+ parentTypeMetadata,
646
+ ...resolvedTypeMetadata.typeMetadataChain
647
+ ],
648
+ vctValues: [parentTypeMetadata.vct, ...resolvedTypeMetadata.vctValues]
649
+ };
650
+ });
651
+ }
652
+ /**
653
+ * Fetches and verifies the VCT Metadata for a VCT value.
654
+ * @param result
655
+ * @returns
656
+ */
657
+ fetchSingleVct(vct, integrity) {
658
+ return __async(this, null, function* () {
659
+ var _a;
660
+ const fetcher = (_a = this.userConfig.vctFetcher) != null ? _a : ((uri, integrity2) => this.fetchWithIntegrity(uri, integrity2));
661
+ const data = yield fetcher(vct, integrity);
662
+ if (!data) return void 0;
663
+ const validated = TypeMetadataFormatSchema.safeParse(data);
664
+ if (!validated.success) {
665
+ throw new SDJWTException(
666
+ `Invalid VCT type metadata for vct '${vct}':
667
+ ${z2.prettifyError(validated.error)}`
668
+ );
669
+ }
670
+ return validated.data;
671
+ });
672
+ }
673
+ /**
674
+ * Verifies the status of the SD-JWT-VC.
675
+ * @param result
676
+ * @param options
677
+ */
678
+ verifyStatus(result, options) {
679
+ return __async(this, null, function* () {
680
+ var _a, _b, _c;
681
+ if (options == null ? void 0 : options.disableStatusVerification) {
682
+ return;
683
+ }
684
+ if (result.payload.status) {
685
+ if (result.payload.status.status_list) {
686
+ const fetcher = (_a = this.userConfig.statusListFetcher) != null ? _a : this.statusListFetcher.bind(this);
687
+ const statusListJWT = yield fetcher(
688
+ result.payload.status.status_list.uri
689
+ );
690
+ const slJWT = Jwt.fromEncode(statusListJWT);
691
+ if (!this.userConfig.verifier || !this.userConfig.statusVerifier) {
692
+ throw new SDJWTException("Verifier not found for status list JWT");
693
+ }
694
+ yield slJWT.verify(
695
+ (_b = this.userConfig.statusVerifier) != null ? _b : this.userConfig.verifier,
696
+ options
697
+ ).catch((err) => {
698
+ throw new SLException(
699
+ `Status List JWT verification failed: ${err.message}`,
700
+ err.details
701
+ );
702
+ });
703
+ const statusList = getListFromStatusListJWT(statusListJWT);
704
+ const status = statusList.getStatus(
705
+ result.payload.status.status_list.idx
706
+ );
707
+ const statusValidator = (_c = this.userConfig.statusValidator) != null ? _c : this.statusValidator.bind(this);
708
+ yield statusValidator(status);
709
+ }
710
+ }
711
+ });
712
+ }
713
+ config(newConfig) {
714
+ super.config(newConfig);
715
+ }
716
+ };
717
+ export {
718
+ BackgroundImageSchema,
719
+ ClaimDisplaySchema,
720
+ ClaimPathSchema,
721
+ ClaimSchema,
722
+ ClaimSelectiveDisclosureSchema,
723
+ ColorSchemeSchema,
724
+ ContrastSchema,
725
+ DisplaySchema,
726
+ LogoSchema,
727
+ OrientationSchema,
728
+ RenderingSchema,
729
+ SDJwtVcInstance,
730
+ SimpleRenderingSchema,
731
+ SvgTemplatePropertiesSchema,
732
+ SvgTemplateRenderingSchema,
733
+ TypeMetadataFormatSchema
734
+ };