@vess-id/status-list 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.
@@ -0,0 +1,1634 @@
1
+ import { KeyLike } from 'jose';
2
+
3
+ /**
4
+ * Number of bits used per status entry in the status list.
5
+ * Must be one of: 1, 2, 4, or 8 bits per status.
6
+ *
7
+ * - 1 bit: 2 possible states (e.g., valid/invalid)
8
+ * - 2 bits: 4 possible states (e.g., valid/invalid/suspended/custom)
9
+ * - 4 bits: 16 possible states
10
+ * - 8 bits: 256 possible states
11
+ */
12
+ type BitsPerStatus = 1 | 2 | 4 | 8;
13
+ /**
14
+ * Status value for a credential.
15
+ * Valid range: 0 to (2^bitsPerStatus - 1)
16
+ *
17
+ * For 1-bit: 0-1
18
+ * For 2-bit: 0-3
19
+ * For 4-bit: 0-15
20
+ * For 8-bit: 0-255
21
+ */
22
+ type StatusValue = number;
23
+ /**
24
+ * Standard status values defined by the IETF OAuth Status List specification.
25
+ *
26
+ * @see https://www.ietf.org/archive/id/draft-ietf-oauth-status-list-14.html#section-7
27
+ */
28
+ declare enum StandardStatusValues {
29
+ /**
30
+ * 0x00: The status of the Referenced Token is VALID, CORRECT, or NOT_REVOKED.
31
+ */
32
+ VALID = 0,
33
+ /**
34
+ * 0x01: The status of the Referenced Token is INVALID, REVOKED, ANNULLED, RECALLED, or CANCELLED.
35
+ */
36
+ INVALID = 1,
37
+ /**
38
+ * 0x02: The status of the Referenced Token is SUSPENDED.
39
+ * The Issuer may decide to set this status temporarily to investigate
40
+ * or respond to specific situations (e.g., fraud investigation).
41
+ */
42
+ SUSPENDED = 2,
43
+ /**
44
+ * 0x03: Application-specific status value.
45
+ */
46
+ APPLICATION_SPECIFIC = 3
47
+ }
48
+ /**
49
+ * Format of the status list token.
50
+ */
51
+ type StatusFormat = 'jwt' | 'cwt';
52
+ /**
53
+ * Configuration for creating a status list.
54
+ */
55
+ interface StatusListConfig {
56
+ /**
57
+ * Number of entries in the status list.
58
+ */
59
+ size: number;
60
+ /**
61
+ * Number of bits per status entry.
62
+ */
63
+ bitsPerStatus: BitsPerStatus;
64
+ /**
65
+ * Optional URI for status list aggregation.
66
+ */
67
+ aggregationUri?: string;
68
+ }
69
+
70
+ /**
71
+ * Represents a Status List containing credential statuses in a compressed bit array.
72
+ *
73
+ * The StatusList class manages a byte array where each status entry uses a configurable
74
+ * number of bits (1, 2, 4, or 8). This allows efficient storage of credential status
75
+ * information for thousands or millions of credentials.
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * // Create a status list with 1000 entries (all valid)
80
+ * const list = StatusList.fromArray(new Array(1000).fill(0), 1);
81
+ *
82
+ * // Revoke a credential at index 42
83
+ * list.setStatus(42, 1);
84
+ *
85
+ * // Compress for JWT
86
+ * const compressed = list.compressToBase64URL();
87
+ * ```
88
+ */
89
+ declare class StatusList {
90
+ private readonly statusArray;
91
+ private readonly bitsPerStatus;
92
+ /**
93
+ * Creates a StatusList from a byte array.
94
+ *
95
+ * @param statusArray - Byte array containing packed status values
96
+ * @param bitsPerStatus - Number of bits per status entry
97
+ *
98
+ * @private Use static factory methods instead: fromArray(), decompressFromBase64URL(), decompressFromBytes()
99
+ */
100
+ constructor(statusArray: Uint8Array, bitsPerStatus: BitsPerStatus);
101
+ /**
102
+ * Gets the status value at a specific index.
103
+ *
104
+ * @param index - Index of the status entry (0-based)
105
+ * @returns Status value at the given index
106
+ * @throws {IndexOutOfBoundsError} If index is out of bounds
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * const status = list.getStatus(42);
111
+ * if (status === StandardStatusValues.INVALID) {
112
+ * console.log('Credential is revoked');
113
+ * }
114
+ * ```
115
+ */
116
+ getStatus(index: number): StatusValue;
117
+ /**
118
+ * Sets the status value at a specific index.
119
+ *
120
+ * Note: This modifies the status list in place. After modifying statuses,
121
+ * you'll need to recompress and re-sign the status list token.
122
+ *
123
+ * @param index - Index of the status entry (0-based)
124
+ * @param value - New status value
125
+ * @throws {IndexOutOfBoundsError} If index is out of bounds
126
+ * @throws {InvalidStatusValueError} If value exceeds the maximum for the bit size
127
+ *
128
+ * @example
129
+ * ```typescript
130
+ * // Revoke credential at index 42
131
+ * list.setStatus(42, StandardStatusValues.INVALID);
132
+ *
133
+ * // Suspend credential at index 100
134
+ * list.setStatus(100, StandardStatusValues.SUSPENDED);
135
+ * ```
136
+ */
137
+ setStatus(index: number, value: StatusValue): void;
138
+ /**
139
+ * Gets the number of bits used per status entry.
140
+ *
141
+ * @returns Number of bits per status (1, 2, 4, or 8)
142
+ */
143
+ getBitsPerStatus(): BitsPerStatus;
144
+ /**
145
+ * Gets the total number of status entries in this list.
146
+ *
147
+ * @returns Total capacity of the status list
148
+ */
149
+ getSize(): number;
150
+ /**
151
+ * Gets the raw byte array (for internal use).
152
+ *
153
+ * @returns The underlying byte array
154
+ */
155
+ getBytes(): Uint8Array;
156
+ /**
157
+ * Compresses the status list to base64url format (for JWT).
158
+ *
159
+ * @returns Base64URL-encoded compressed status list
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * const lst = list.compressToBase64URL();
164
+ * // Use in JWT payload: { status_list: { bits: 1, lst } }
165
+ * ```
166
+ */
167
+ compressToBase64URL(): string;
168
+ /**
169
+ * Compresses the status list to raw bytes (for CWT).
170
+ *
171
+ * @returns Compressed status list as bytes
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * const lst = list.compressToBytes();
176
+ * // Use in CWT payload: { 65533: { bits: 1, lst } }
177
+ * ```
178
+ */
179
+ compressToBytes(): Uint8Array;
180
+ /**
181
+ * Creates a StatusList from an array of status values.
182
+ *
183
+ * @param statuses - Array of status values
184
+ * @param bitsPerStatus - Number of bits per status entry (1, 2, 4, or 8)
185
+ * @returns New StatusList instance
186
+ * @throws {InvalidBitSizeError} If bitsPerStatus is not 1, 2, 4, or 8
187
+ * @throws {InvalidStatusValueError} If any status value exceeds the maximum for the bit size
188
+ *
189
+ * @example
190
+ * ```typescript
191
+ * // Create list with 1-bit statuses (valid/invalid)
192
+ * const statuses = new Array(10000).fill(0); // All valid
193
+ * statuses[42] = 1; // Revoke one credential
194
+ * const list = StatusList.fromArray(statuses, 1);
195
+ *
196
+ * // Create list with 2-bit statuses (valid/invalid/suspended/custom)
197
+ * const statuses2 = [0, 1, 2, 0, 1, 3];
198
+ * const list2 = StatusList.fromArray(statuses2, 2);
199
+ * ```
200
+ */
201
+ static fromArray(statuses: StatusValue[], bitsPerStatus: BitsPerStatus): StatusList;
202
+ /**
203
+ * Creates a StatusList by decompressing a base64url-encoded string (from JWT).
204
+ *
205
+ * @param compressed - Base64URL-encoded compressed status list
206
+ * @param bitsPerStatus - Number of bits per status entry
207
+ * @returns New StatusList instance
208
+ * @throws {CompressionError} If decompression fails
209
+ *
210
+ * @example
211
+ * ```typescript
212
+ * // From JWT payload
213
+ * const payload = parseJWT(token);
214
+ * const list = StatusList.decompressFromBase64URL(
215
+ * payload.status_list.lst,
216
+ * payload.status_list.bits
217
+ * );
218
+ * ```
219
+ */
220
+ static decompressFromBase64URL(compressed: string, bitsPerStatus: BitsPerStatus): StatusList;
221
+ /**
222
+ * Creates a StatusList by decompressing raw bytes (from CWT).
223
+ *
224
+ * @param compressed - Compressed status list as bytes
225
+ * @param bitsPerStatus - Number of bits per status entry
226
+ * @returns New StatusList instance
227
+ * @throws {CompressionError} If decompression fails
228
+ *
229
+ * @example
230
+ * ```typescript
231
+ * // From CWT payload
232
+ * const payload = parseCWT(token);
233
+ * const statusListData = payload[65533]; // status_list claim
234
+ * const list = StatusList.decompressFromBytes(
235
+ * statusListData.lst,
236
+ * statusListData.bits
237
+ * );
238
+ * ```
239
+ */
240
+ static decompressFromBytes(compressed: Uint8Array, bitsPerStatus: BitsPerStatus): StatusList;
241
+ /**
242
+ * Creates an empty StatusList with a specified capacity.
243
+ *
244
+ * All status entries are initialized to 0 (VALID).
245
+ *
246
+ * @param capacity - Number of status entries
247
+ * @param bitsPerStatus - Number of bits per status entry (1, 2, 4, or 8)
248
+ * @returns New StatusList instance
249
+ *
250
+ * @example
251
+ * ```typescript
252
+ * // Create empty list for 100,000 credentials
253
+ * const list = StatusList.create(100000, 1);
254
+ * ```
255
+ */
256
+ static create(capacity: number, bitsPerStatus: BitsPerStatus): StatusList;
257
+ /**
258
+ * Converts the status list to an array of status values (for debugging/testing).
259
+ *
260
+ * Warning: For large status lists, this can be memory-intensive.
261
+ *
262
+ * @returns Array of all status values
263
+ */
264
+ toArray(): StatusValue[];
265
+ }
266
+
267
+ /**
268
+ * Compresses data using ZLIB/DEFLATE compression with maximum compression level.
269
+ *
270
+ * Uses the DEFLATE algorithm with ZLIB wrapper (as required by the IETF specification).
271
+ * Maximum compression level (9) is used as recommended by the spec for optimal size reduction.
272
+ *
273
+ * @param data - Uncompressed data to compress
274
+ * @returns Compressed data with ZLIB header
275
+ * @throws {CompressionError} If compression fails
276
+ *
277
+ * @see https://www.ietf.org/archive/id/draft-ietf-oauth-status-list-14.html#section-4.1
278
+ */
279
+ declare function compress(data: Uint8Array): Uint8Array;
280
+ /**
281
+ * Decompresses ZLIB/DEFLATE compressed data.
282
+ *
283
+ * @param compressed - Compressed data with ZLIB header
284
+ * @returns Decompressed data
285
+ * @throws {CompressionError} If decompression fails
286
+ */
287
+ declare function decompress(compressed: Uint8Array): Uint8Array;
288
+ /**
289
+ * Compresses data and returns it as a base64url-encoded string (for JWT format).
290
+ *
291
+ * @param data - Uncompressed data
292
+ * @returns Base64URL-encoded compressed data
293
+ * @throws {CompressionError} If compression fails
294
+ */
295
+ declare function compressToBase64URL(data: Uint8Array): string;
296
+ /**
297
+ * Decompresses base64url-encoded data (from JWT format).
298
+ *
299
+ * @param base64url - Base64URL-encoded compressed data
300
+ * @returns Decompressed data
301
+ * @throws {CompressionError} If decoding or decompression fails
302
+ */
303
+ declare function decompressFromBase64URL(base64url: string): Uint8Array;
304
+
305
+ /**
306
+ * Packs an array of status values into a byte array using the specified bits per status.
307
+ *
308
+ * Bits are packed LSB-first within each byte (Least Significant Bit first).
309
+ * Example for 1-bit status with values [1,0,0,1,1,1,0,1]:
310
+ * - Byte 0: bits 0-7 → 1101 1001 = 0xD9 (LSB first)
311
+ *
312
+ * @param statuses - Array of status values
313
+ * @param bitsPerStatus - Number of bits per status (1, 2, 4, or 8)
314
+ * @returns Byte array containing packed status values
315
+ *
316
+ * @example
317
+ * ```typescript
318
+ * // 1-bit status: [1, 0, 0, 1, 1, 1, 0, 1]
319
+ * const bytes = packBits([1, 0, 0, 1, 1, 1, 0, 1], 1);
320
+ * // bytes[0] === 0xD9 (binary: 11011001, LSB first)
321
+ * ```
322
+ */
323
+ declare function packBits(statuses: StatusValue[], bitsPerStatus: BitsPerStatus): Uint8Array;
324
+ /**
325
+ * Unpacks a byte array into an array of status values.
326
+ *
327
+ * @param bytes - Byte array containing packed status values
328
+ * @param bitsPerStatus - Number of bits per status (1, 2, 4, or 8)
329
+ * @returns Array of status values
330
+ *
331
+ * @example
332
+ * ```typescript
333
+ * const bytes = new Uint8Array([0xD9]); // binary: 11011001
334
+ * const statuses = unpackBits(bytes, 1); // [1, 0, 0, 1, 1, 1, 0, 1]
335
+ * ```
336
+ */
337
+ declare function unpackBits(bytes: Uint8Array, bitsPerStatus: BitsPerStatus): StatusValue[];
338
+ /**
339
+ * Gets the status value at a specific index in the byte array.
340
+ *
341
+ * Implementation based on Python reference:
342
+ * ```python
343
+ * jump = self.bits * position # Bit offset
344
+ * mask = (1 << self.bits) - 1 # n-bit mask
345
+ * status = (self.status_list[jump // 8] >> (jump % 8)) & mask
346
+ * ```
347
+ *
348
+ * @param bytes - Byte array containing packed status values
349
+ * @param index - Index of the status to retrieve
350
+ * @param bitsPerStatus - Number of bits per status
351
+ * @param mask - Optional pre-calculated mask (for performance)
352
+ * @returns Status value at the given index
353
+ * @throws {IndexOutOfBoundsError} If index is out of bounds
354
+ */
355
+ declare function getBitValue(bytes: Uint8Array, index: number, bitsPerStatus: BitsPerStatus, mask?: number): StatusValue;
356
+ /**
357
+ * Sets the status value at a specific index in the byte array.
358
+ *
359
+ * @param bytes - Byte array containing packed status values (modified in place)
360
+ * @param index - Index of the status to set
361
+ * @param value - New status value
362
+ * @param bitsPerStatus - Number of bits per status
363
+ * @throws {IndexOutOfBoundsError} If index is out of bounds
364
+ * @throws {InvalidStatusValueError} If value exceeds the maximum for the bit size
365
+ */
366
+ declare function setBitValue(bytes: Uint8Array, index: number, value: StatusValue, bitsPerStatus: BitsPerStatus): void;
367
+ /**
368
+ * Calculates the total number of status entries that can be stored in a byte array.
369
+ *
370
+ * @param byteLength - Length of the byte array
371
+ * @param bitsPerStatus - Number of bits per status
372
+ * @returns Total number of status entries
373
+ */
374
+ declare function calculateCapacity(byteLength: number, bitsPerStatus: BitsPerStatus): number;
375
+
376
+ /**
377
+ * Base error class for all status list errors.
378
+ */
379
+ declare class StatusListError extends Error {
380
+ constructor(message: string);
381
+ }
382
+ /**
383
+ * Error thrown when attempting to access a status at an index that is out of bounds.
384
+ */
385
+ declare class IndexOutOfBoundsError extends StatusListError {
386
+ constructor(index: number, maxIndex: number);
387
+ }
388
+ /**
389
+ * Error thrown when an invalid bit size is provided.
390
+ * Valid bit sizes are: 1, 2, 4, or 8.
391
+ */
392
+ declare class InvalidBitSizeError extends StatusListError {
393
+ constructor(bits: number);
394
+ }
395
+ /**
396
+ * Error thrown when a status value exceeds the maximum allowed for the given bit size.
397
+ */
398
+ declare class InvalidStatusValueError extends StatusListError {
399
+ constructor(value: number, maxValue: number, bitsPerStatus: number);
400
+ }
401
+ /**
402
+ * Error thrown when a token has an invalid format or cannot be parsed.
403
+ */
404
+ declare class InvalidTokenFormatError extends StatusListError {
405
+ constructor(message: string);
406
+ }
407
+ /**
408
+ * Error thrown when a status list token has expired.
409
+ */
410
+ declare class StatusListExpiredError extends StatusListError {
411
+ constructor(exp: number, currentTime: number);
412
+ }
413
+ /**
414
+ * Error thrown when fetching a status list from a remote URI fails.
415
+ */
416
+ declare class FetchError extends StatusListError {
417
+ constructor(message: string);
418
+ }
419
+ /**
420
+ * Error thrown when a status list URI is missing or invalid.
421
+ */
422
+ declare class MissingStatusListUriError extends StatusListError {
423
+ constructor(message?: string);
424
+ }
425
+ /**
426
+ * Error thrown when compression or decompression fails.
427
+ */
428
+ declare class CompressionError extends StatusListError {
429
+ constructor(message: string, cause?: Error);
430
+ }
431
+ /**
432
+ * Error thrown when validation of a status list token fails.
433
+ */
434
+ declare class ValidationError extends StatusListError {
435
+ readonly errors: string[];
436
+ constructor(errors: string[]);
437
+ }
438
+
439
+ /**
440
+ * JWT header for a Status List Token.
441
+ *
442
+ * @see https://www.ietf.org/archive/id/draft-ietf-oauth-status-list-14.html#section-5.1
443
+ */
444
+ interface StatusListJWTHeader {
445
+ /**
446
+ * REQUIRED: Type header parameter.
447
+ * Must be "statuslist+jwt" for Status List Tokens.
448
+ */
449
+ typ: 'statuslist+jwt';
450
+ /**
451
+ * REQUIRED: Algorithm used for signing.
452
+ * Common values: "ES256", "ES384", "ES512", "RS256", etc.
453
+ */
454
+ alg: string;
455
+ /**
456
+ * OPTIONAL: Key ID.
457
+ * Indicates which key was used to sign the JWT.
458
+ */
459
+ kid?: string;
460
+ /**
461
+ * Allow additional header parameters.
462
+ */
463
+ [key: string]: unknown;
464
+ }
465
+ /**
466
+ * Status List structure within the JWT payload.
467
+ */
468
+ interface StatusListClaim {
469
+ /**
470
+ * REQUIRED: Number of bits per status entry.
471
+ * Must be 1, 2, 4, or 8.
472
+ */
473
+ bits: BitsPerStatus;
474
+ /**
475
+ * REQUIRED: Base64URL-encoded compressed status list.
476
+ * The status list is compressed using DEFLATE/ZLIB before encoding.
477
+ */
478
+ lst: string;
479
+ /**
480
+ * OPTIONAL: URI for status list aggregation.
481
+ * Points to a resource that aggregates multiple status lists.
482
+ */
483
+ aggregation_uri?: string;
484
+ }
485
+ /**
486
+ * JWT payload for a Status List Token.
487
+ *
488
+ * @see https://www.ietf.org/archive/id/draft-ietf-oauth-status-list-14.html#section-5.1.1
489
+ */
490
+ interface StatusListJWTPayload {
491
+ /**
492
+ * REQUIRED: Issuer of the status list token.
493
+ * Identifies the principal that issued the JWT.
494
+ */
495
+ iss: string;
496
+ /**
497
+ * REQUIRED: Subject of the status list token.
498
+ * URI that identifies this specific status list.
499
+ * Must match the "uri" field in referenced tokens.
500
+ */
501
+ sub: string;
502
+ /**
503
+ * REQUIRED: Issued at time.
504
+ * Timestamp (seconds since epoch) when the status list was created.
505
+ */
506
+ iat: number;
507
+ /**
508
+ * RECOMMENDED: Expiration time.
509
+ * Timestamp (seconds since epoch) after which the status list is no longer valid.
510
+ */
511
+ exp?: number;
512
+ /**
513
+ * RECOMMENDED: Time to live (in seconds).
514
+ * Indicates how long the status list should be cached.
515
+ */
516
+ ttl?: number;
517
+ /**
518
+ * REQUIRED: The status list.
519
+ */
520
+ status_list: StatusListClaim;
521
+ /**
522
+ * Allow additional claims.
523
+ */
524
+ [key: string]: unknown;
525
+ }
526
+ /**
527
+ * Status list reference within a credential/token.
528
+ *
529
+ * This appears in the "status" claim of a referenced token (credential).
530
+ *
531
+ * @see https://www.ietf.org/archive/id/draft-ietf-oauth-status-list-14.html#section-6
532
+ */
533
+ interface StatusListReference {
534
+ /**
535
+ * REQUIRED: Index of this credential in the status list.
536
+ * Non-negative integer that identifies the position.
537
+ */
538
+ idx: number;
539
+ /**
540
+ * REQUIRED: URI of the Status List Token.
541
+ * Must match the "sub" claim of the Status List Token.
542
+ */
543
+ uri: string;
544
+ }
545
+ /**
546
+ * Status claim structure in a referenced token.
547
+ */
548
+ interface TokenStatusClaim {
549
+ /**
550
+ * Status list reference.
551
+ */
552
+ status_list: StatusListReference;
553
+ /**
554
+ * Allow additional status mechanisms.
555
+ */
556
+ [key: string]: unknown;
557
+ }
558
+ /**
559
+ * Options for creating a JWT Status List Token payload.
560
+ */
561
+ interface CreateJWTStatusListOptions {
562
+ /**
563
+ * REQUIRED: Issuer identifier.
564
+ */
565
+ iss: string;
566
+ /**
567
+ * REQUIRED: Status list identifier (URI).
568
+ */
569
+ sub: string;
570
+ /**
571
+ * REQUIRED: Compressed status list (base64url-encoded).
572
+ */
573
+ lst: string;
574
+ /**
575
+ * REQUIRED: Number of bits per status.
576
+ */
577
+ bits: BitsPerStatus;
578
+ /**
579
+ * OPTIONAL: Issued at timestamp.
580
+ * Defaults to current time if not provided.
581
+ */
582
+ iat?: number;
583
+ /**
584
+ * OPTIONAL: Expiration timestamp.
585
+ */
586
+ exp?: number;
587
+ /**
588
+ * OPTIONAL: Time to live in seconds.
589
+ */
590
+ ttl?: number;
591
+ /**
592
+ * OPTIONAL: Aggregation URI.
593
+ */
594
+ aggregation_uri?: string;
595
+ /**
596
+ * OPTIONAL: Additional claims to include in the payload.
597
+ */
598
+ additionalClaims?: Record<string, unknown>;
599
+ }
600
+ /**
601
+ * Options for signing a Status List JWT.
602
+ */
603
+ interface SignJWTOptions {
604
+ /**
605
+ * OPTIONAL: Algorithm to use for signing.
606
+ * Defaults to the algorithm specified in the key.
607
+ */
608
+ alg?: string;
609
+ /**
610
+ * OPTIONAL: Key ID to include in the header.
611
+ */
612
+ kid?: string;
613
+ /**
614
+ * OPTIONAL: Additional header parameters.
615
+ */
616
+ additionalHeaders?: Record<string, unknown>;
617
+ }
618
+ /**
619
+ * Result of parsing a JWT Status List Token.
620
+ */
621
+ interface ParsedJWTStatusList {
622
+ /**
623
+ * JWT header.
624
+ */
625
+ header: StatusListJWTHeader;
626
+ /**
627
+ * JWT payload.
628
+ */
629
+ payload: StatusListJWTPayload;
630
+ /**
631
+ * Raw JWT string.
632
+ */
633
+ jwt: string;
634
+ }
635
+
636
+ /**
637
+ * Creates a JWT Status List payload (without signing).
638
+ *
639
+ * This function creates the header and payload objects for a Status List JWT.
640
+ * The actual signing should be done using the `jose` library or similar.
641
+ *
642
+ * @param options - Configuration for creating the status list payload
643
+ * @returns Object containing header and payload ready for signing
644
+ *
645
+ * @example
646
+ * ```typescript
647
+ * import { StatusList } from '@vess-id/status-list';
648
+ * import { createJWTStatusListPayload } from '@vess-id/status-list/formats/jwt';
649
+ * import { SignJWT } from 'jose';
650
+ *
651
+ * const list = StatusList.create(1000, 1);
652
+ * const lst = list.compressToBase64URL();
653
+ *
654
+ * const { header, payload } = createJWTStatusListPayload({
655
+ * iss: 'https://issuer.example.com',
656
+ * sub: 'https://issuer.example.com/status/1',
657
+ * lst,
658
+ * bits: 1,
659
+ * iat: Math.floor(Date.now() / 1000),
660
+ * exp: Math.floor(Date.now() / 1000) + 86400,
661
+ * ttl: 3600,
662
+ * });
663
+ *
664
+ * // Sign with jose
665
+ * const jwt = await new SignJWT(payload)
666
+ * .setProtectedHeader(header)
667
+ * .sign(privateKey);
668
+ * ```
669
+ */
670
+ declare function createJWTStatusListPayload(options: CreateJWTStatusListOptions): {
671
+ header: StatusListJWTHeader;
672
+ payload: StatusListJWTPayload;
673
+ };
674
+ /**
675
+ * Parses a JWT Status List Token (without verifying the signature).
676
+ *
677
+ * This function decodes and validates the structure of a Status List JWT.
678
+ * Signature verification should be done separately using `jose` or similar.
679
+ *
680
+ * @param jwt - JWT string to parse
681
+ * @returns Parsed header, payload, and decompressed status list
682
+ * @throws {InvalidTokenFormatError} If the JWT format is invalid
683
+ *
684
+ * @example
685
+ * ```typescript
686
+ * import { parseJWTStatusList } from '@vess-id/status-list/formats/jwt';
687
+ * import { jwtVerify } from 'jose';
688
+ *
689
+ * // First verify the signature
690
+ * const { payload } = await jwtVerify(jwt, publicKey);
691
+ *
692
+ * // Then parse and decompress
693
+ * const { header, payload: parsed, statusList } = parseJWTStatusList(jwt);
694
+ *
695
+ * // Check credential status
696
+ * const status = statusList.getStatus(42);
697
+ * ```
698
+ */
699
+ declare function parseJWTStatusList(jwt: string): ParsedJWTStatusList & {
700
+ statusList: StatusList;
701
+ };
702
+ /**
703
+ * Extracts the status list reference from a credential JWT.
704
+ *
705
+ * @param credentialJWT - Credential JWT containing a status claim
706
+ * @returns Status list reference (idx and uri)
707
+ * @throws {InvalidTokenFormatError} If the status claim is missing or invalid
708
+ *
709
+ * @example
710
+ * ```typescript
711
+ * import { extractStatusListReference } from '@vess-id/status-list/formats/jwt';
712
+ *
713
+ * const credential = 'eyJ...'; // Credential JWT
714
+ * const { idx, uri } = extractStatusListReference(credential);
715
+ *
716
+ * // Fetch status list from uri and check status at idx
717
+ * ```
718
+ */
719
+ declare function extractStatusListReference(credentialJWT: string): StatusListReference;
720
+
721
+ /**
722
+ * Signs a Status List JWT using the provided private key.
723
+ *
724
+ * This function uses the `jose` library to create a signed JWT from a Status List payload.
725
+ *
726
+ * @param payload - Status List JWT payload
727
+ * @param privateKey - Private key for signing (KeyLike from jose)
728
+ * @param options - Optional signing options (algorithm, kid, additional headers)
729
+ * @returns Signed JWT string
730
+ *
731
+ * @example
732
+ * ```typescript
733
+ * import { signStatusListJWT } from '@vess-id/status-list/formats/jwt';
734
+ * import { StatusList } from '@vess-id/status-list';
735
+ * import { importPKCS8 } from 'jose';
736
+ *
737
+ * // Create status list
738
+ * const list = StatusList.create(1000, 1);
739
+ * const lst = list.compressToBase64URL();
740
+ *
741
+ * // Create payload
742
+ * const payload = {
743
+ * iss: 'https://issuer.example.com',
744
+ * sub: 'https://issuer.example.com/status/1',
745
+ * iat: Math.floor(Date.now() / 1000),
746
+ * exp: Math.floor(Date.now() / 1000) + 86400,
747
+ * ttl: 3600,
748
+ * status_list: { bits: 1, lst },
749
+ * };
750
+ *
751
+ * // Import private key
752
+ * const privateKey = await importPKCS8(pemPrivateKey, 'ES256');
753
+ *
754
+ * // Sign
755
+ * const jwt = await signStatusListJWT(payload, privateKey, {
756
+ * alg: 'ES256',
757
+ * kid: 'key-123',
758
+ * });
759
+ * ```
760
+ */
761
+ declare function signStatusListJWT(payload: StatusListJWTPayload, privateKey: KeyLike, options?: SignJWTOptions): Promise<string>;
762
+
763
+ /**
764
+ * Options for verifying a Status List JWT.
765
+ */
766
+ interface VerifyJWTOptions {
767
+ /**
768
+ * Expected issuer (iss claim).
769
+ * If provided, verification will fail if the token's iss doesn't match.
770
+ */
771
+ issuer?: string;
772
+ /**
773
+ * Expected subject (sub claim).
774
+ * If provided, verification will fail if the token's sub doesn't match.
775
+ */
776
+ subject?: string;
777
+ /**
778
+ * Current time for validation (in seconds since epoch).
779
+ * Defaults to current time if not provided.
780
+ */
781
+ currentTime?: number;
782
+ /**
783
+ * Clock tolerance in seconds.
784
+ * Allows for small clock differences between issuer and verifier.
785
+ * Default: 0
786
+ */
787
+ clockTolerance?: number;
788
+ }
789
+ /**
790
+ * Result of verifying a Status List JWT.
791
+ */
792
+ interface VerifiedStatusListJWT {
793
+ /**
794
+ * Verified JWT header.
795
+ */
796
+ header: StatusListJWTHeader;
797
+ /**
798
+ * Verified JWT payload.
799
+ */
800
+ payload: StatusListJWTPayload;
801
+ }
802
+ /**
803
+ * Verifies the signature and validates a Status List JWT.
804
+ *
805
+ * This function:
806
+ * 1. Verifies the JWT signature using the provided public key
807
+ * 2. Validates the JWT structure and claims
808
+ * 3. Checks expiration (if exp is present)
809
+ * 4. Optionally validates issuer and subject
810
+ *
811
+ * @param jwt - JWT string to verify
812
+ * @param publicKey - Public key for verification (KeyLike from jose)
813
+ * @param options - Optional verification options
814
+ * @returns Verified header and payload
815
+ * @throws {InvalidTokenFormatError} If verification fails
816
+ *
817
+ * @example
818
+ * ```typescript
819
+ * import { verifyStatusListJWT } from '@vess-id/status-list/formats/jwt';
820
+ * import { importSPKI } from 'jose';
821
+ *
822
+ * // Import public key
823
+ * const publicKey = await importSPKI(pemPublicKey, 'ES256');
824
+ *
825
+ * try {
826
+ * const { header, payload } = await verifyStatusListJWT(jwt, publicKey, {
827
+ * issuer: 'https://issuer.example.com',
828
+ * subject: 'https://issuer.example.com/status/1',
829
+ * });
830
+ *
831
+ * console.log('JWT is valid');
832
+ * console.log('Issued at:', new Date(payload.iat * 1000));
833
+ * console.log('Expires at:', payload.exp ? new Date(payload.exp * 1000) : 'Never');
834
+ * } catch (error) {
835
+ * console.error('Verification failed:', error.message);
836
+ * }
837
+ * ```
838
+ */
839
+ declare function verifyStatusListJWT(jwt: string, publicKey: KeyLike, options?: VerifyJWTOptions): Promise<VerifiedStatusListJWT>;
840
+ /**
841
+ * Verifies only the signature of a Status List JWT without validating claims.
842
+ *
843
+ * Useful when you want to verify the signature but handle claim validation separately.
844
+ *
845
+ * @param jwt - JWT string to verify
846
+ * @param publicKey - Public key for verification
847
+ * @returns Verified header and payload
848
+ * @throws {InvalidTokenFormatError} If signature verification fails
849
+ */
850
+ declare function verifySignatureOnly(jwt: string, publicKey: KeyLike): Promise<VerifiedStatusListJWT>;
851
+
852
+ /**
853
+ * CBOR Web Token (CWT) claim keys as defined in RFC 8392.
854
+ *
855
+ * @see https://www.rfc-editor.org/rfc/rfc8392.html#section-3.1
856
+ * @see https://www.ietf.org/archive/id/draft-ietf-oauth-status-list-14.html#section-5.2
857
+ */
858
+ declare const CWT_CLAIMS: {
859
+ /** Issuer (iss) - Claim key 1 */
860
+ readonly ISS: 1;
861
+ /** Subject (sub) - Claim key 2 */
862
+ readonly SUB: 2;
863
+ /** Expiration Time (exp) - Claim key 4 */
864
+ readonly EXP: 4;
865
+ /** Issued At (iat) - Claim key 6 */
866
+ readonly IAT: 6;
867
+ /** Time to Live (ttl) - Claim key 65534 (custom) */
868
+ readonly TTL: 65534;
869
+ /** Status List - Claim key 65533 (custom) */
870
+ readonly STATUS_LIST: 65533;
871
+ };
872
+ /**
873
+ * COSE header parameters.
874
+ *
875
+ * @see https://www.rfc-editor.org/rfc/rfc8152.html#section-3.1
876
+ */
877
+ declare const COSE_HEADERS: {
878
+ /** Algorithm - Header parameter 1 */
879
+ readonly ALG: 1;
880
+ /** Content Type - Header parameter 16 */
881
+ readonly CONTENT_TYPE: 16;
882
+ /** Key ID - Header parameter 4 */
883
+ readonly KID: 4;
884
+ };
885
+ /**
886
+ * COSE algorithms.
887
+ *
888
+ * @see https://www.iana.org/assignments/cose/cose.xhtml#algorithms
889
+ */
890
+ declare const COSE_ALGORITHMS: {
891
+ /** ES256 - ECDSA with SHA-256 */
892
+ readonly ES256: -7;
893
+ /** ES384 - ECDSA with SHA-384 */
894
+ readonly ES384: -35;
895
+ /** ES512 - ECDSA with SHA-512 */
896
+ readonly ES512: -36;
897
+ /** EdDSA */
898
+ readonly EdDSA: -8;
899
+ };
900
+ /**
901
+ * Status List structure in CBOR format.
902
+ */
903
+ interface StatusListCWTClaim {
904
+ /**
905
+ * REQUIRED: Number of bits per status entry.
906
+ * Must be 1, 2, 4, or 8.
907
+ */
908
+ bits: BitsPerStatus;
909
+ /**
910
+ * REQUIRED: Compressed status list as raw bytes.
911
+ * Unlike JWT, this is NOT base64url-encoded.
912
+ */
913
+ lst: Uint8Array;
914
+ /**
915
+ * OPTIONAL: URI for status list aggregation.
916
+ */
917
+ aggregation_uri?: string;
918
+ }
919
+ /**
920
+ * CWT payload for a Status List Token.
921
+ *
922
+ * Uses numeric claim keys as defined in RFC 8392 and the IETF spec.
923
+ *
924
+ * @see https://www.ietf.org/archive/id/draft-ietf-oauth-status-list-14.html#section-5.2
925
+ */
926
+ interface StatusListCWTPayload {
927
+ /**
928
+ * OPTIONAL: Issuer (claim key 1).
929
+ */
930
+ [CWT_CLAIMS.ISS]?: string;
931
+ /**
932
+ * REQUIRED: Subject (claim key 2).
933
+ * URI that identifies this specific status list.
934
+ */
935
+ [CWT_CLAIMS.SUB]?: string;
936
+ /**
937
+ * OPTIONAL: Expiration time (claim key 4).
938
+ * Timestamp (seconds since epoch).
939
+ */
940
+ [CWT_CLAIMS.EXP]?: number;
941
+ /**
942
+ * REQUIRED: Issued at time (claim key 6).
943
+ * Timestamp (seconds since epoch).
944
+ */
945
+ [CWT_CLAIMS.IAT]?: number;
946
+ /**
947
+ * OPTIONAL: Time to live in seconds (claim key 65534).
948
+ */
949
+ [CWT_CLAIMS.TTL]?: number;
950
+ /**
951
+ * REQUIRED: The status list (claim key 65533).
952
+ */
953
+ [CWT_CLAIMS.STATUS_LIST]: StatusListCWTClaim;
954
+ /**
955
+ * Allow additional claims.
956
+ */
957
+ [key: number]: unknown;
958
+ }
959
+ /**
960
+ * COSE key in JWK-like format for elliptic curve keys.
961
+ */
962
+ interface EC2Key {
963
+ /**
964
+ * Key type: EC2 for Elliptic Curve keys with x and y coordinates.
965
+ */
966
+ kty: 'EC2';
967
+ /**
968
+ * Curve: P-256, P-384, or P-521.
969
+ */
970
+ crv: 'P-256' | 'P-384' | 'P-521';
971
+ /**
972
+ * X coordinate (public key component).
973
+ */
974
+ x: Uint8Array;
975
+ /**
976
+ * Y coordinate (public key component).
977
+ */
978
+ y: Uint8Array;
979
+ /**
980
+ * Private key (d parameter).
981
+ * Only present for private keys.
982
+ */
983
+ d?: Uint8Array;
984
+ /**
985
+ * Key ID.
986
+ */
987
+ kid?: Uint8Array;
988
+ }
989
+ /**
990
+ * COSE key for OKP (Octet Key Pair) keys like Ed25519.
991
+ */
992
+ interface OKPKey {
993
+ /**
994
+ * Key type: OKP for Octet Key Pair.
995
+ */
996
+ kty: 'OKP';
997
+ /**
998
+ * Curve: Ed25519 or Ed448.
999
+ */
1000
+ crv: 'Ed25519' | 'Ed448';
1001
+ /**
1002
+ * Public key.
1003
+ */
1004
+ x: Uint8Array;
1005
+ /**
1006
+ * Private key.
1007
+ * Only present for private keys.
1008
+ */
1009
+ d?: Uint8Array;
1010
+ /**
1011
+ * Key ID.
1012
+ */
1013
+ kid?: Uint8Array;
1014
+ }
1015
+ /**
1016
+ * COSE key (either EC2 or OKP).
1017
+ */
1018
+ type COSEKey = EC2Key | OKPKey;
1019
+ /**
1020
+ * Options for creating a CWT Status List.
1021
+ */
1022
+ interface CreateCWTStatusListOptions {
1023
+ /**
1024
+ * OPTIONAL: Issuer identifier.
1025
+ */
1026
+ iss?: string;
1027
+ /**
1028
+ * OPTIONAL: Status list identifier (URI).
1029
+ */
1030
+ sub?: string;
1031
+ /**
1032
+ * REQUIRED: Compressed status list (raw bytes).
1033
+ */
1034
+ lst: Uint8Array;
1035
+ /**
1036
+ * REQUIRED: Number of bits per status.
1037
+ */
1038
+ bits: BitsPerStatus;
1039
+ /**
1040
+ * OPTIONAL: Issued at timestamp.
1041
+ * Defaults to current time if not provided.
1042
+ */
1043
+ iat?: number;
1044
+ /**
1045
+ * OPTIONAL: Expiration timestamp.
1046
+ */
1047
+ exp?: number;
1048
+ /**
1049
+ * OPTIONAL: Time to live in seconds.
1050
+ */
1051
+ ttl?: number;
1052
+ /**
1053
+ * OPTIONAL: Aggregation URI.
1054
+ */
1055
+ aggregation_uri?: string;
1056
+ /**
1057
+ * OPTIONAL: Additional claims (with numeric keys).
1058
+ */
1059
+ additionalClaims?: Record<number, unknown>;
1060
+ }
1061
+ /**
1062
+ * Options for signing a CWT with COSE Sign1.
1063
+ */
1064
+ interface SignCWTOptions {
1065
+ /**
1066
+ * OPTIONAL: Algorithm to use for signing.
1067
+ * Defaults to ES256 (-7).
1068
+ */
1069
+ alg?: number;
1070
+ /**
1071
+ * OPTIONAL: Key ID to include in the protected header.
1072
+ */
1073
+ kid?: Uint8Array;
1074
+ /**
1075
+ * OPTIONAL: Additional protected header parameters.
1076
+ */
1077
+ additionalHeaders?: Map<number, unknown>;
1078
+ }
1079
+ /**
1080
+ * Result of parsing a CWT Status List Token.
1081
+ */
1082
+ interface ParsedCWTStatusList {
1083
+ /**
1084
+ * Protected header.
1085
+ */
1086
+ protectedHeader: Map<number, unknown>;
1087
+ /**
1088
+ * Unprotected header.
1089
+ */
1090
+ unprotectedHeader: Map<number, unknown>;
1091
+ /**
1092
+ * CWT payload.
1093
+ */
1094
+ payload: StatusListCWTPayload;
1095
+ /**
1096
+ * Raw CWT bytes.
1097
+ */
1098
+ cwt: Uint8Array;
1099
+ }
1100
+ /**
1101
+ * Status list reference in CBOR format (for mdoc).
1102
+ */
1103
+ interface StatusListReferenceCBOR {
1104
+ /**
1105
+ * Index of this credential in the status list.
1106
+ */
1107
+ idx: number;
1108
+ /**
1109
+ * URI of the Status List Token.
1110
+ */
1111
+ uri: string;
1112
+ }
1113
+
1114
+ /**
1115
+ * Creates a CWT Status List payload (CBOR map).
1116
+ *
1117
+ * This function creates the payload for a Status List CWT using numeric claim keys.
1118
+ * The payload can be signed separately using COSE Sign1.
1119
+ *
1120
+ * @param options - Configuration for creating the status list payload
1121
+ * @returns CBOR-encodable payload object
1122
+ *
1123
+ * @example
1124
+ * ```typescript
1125
+ * import { StatusList } from '@vess-id/status-list';
1126
+ * import { createCWTStatusListPayload } from '@vess-id/status-list/formats/cwt';
1127
+ *
1128
+ * const list = StatusList.create(1000, 1);
1129
+ * const lst = list.compressToBytes();
1130
+ *
1131
+ * const payload = createCWTStatusListPayload({
1132
+ * sub: 'https://issuer.example.com/status/1',
1133
+ * lst,
1134
+ * bits: 1,
1135
+ * iat: Math.floor(Date.now() / 1000),
1136
+ * exp: Math.floor(Date.now() / 1000) + 86400,
1137
+ * ttl: 3600,
1138
+ * });
1139
+ * ```
1140
+ */
1141
+ declare function createCWTStatusListPayload(options: CreateCWTStatusListOptions): StatusListCWTPayload;
1142
+ /**
1143
+ * Encodes a CWT Status List payload to CBOR format (without signing).
1144
+ *
1145
+ * @param payload - CWT payload
1146
+ * @returns CBOR-encoded payload
1147
+ *
1148
+ * @example
1149
+ * ```typescript
1150
+ * const payload = createCWTStatusListPayload({ ... });
1151
+ * const cbor = encodeCWTPayload(payload);
1152
+ * ```
1153
+ */
1154
+ declare function encodeCWTPayload(payload: StatusListCWTPayload): Uint8Array;
1155
+ /**
1156
+ * Parses a CWT Status List (CBOR-encoded, unsigned).
1157
+ *
1158
+ * This function decodes and validates the structure of an unsigned Status List CWT.
1159
+ * For signed CWTs (COSE Sign1), use `parseCWTStatusListSigned()` instead.
1160
+ *
1161
+ * @param cwtBytes - CBOR-encoded CWT bytes
1162
+ * @returns Parsed payload and decompressed status list
1163
+ * @throws {InvalidTokenFormatError} If the CWT format is invalid
1164
+ *
1165
+ * @example
1166
+ * ```typescript
1167
+ * import { parseCWTStatusList } from '@vess-id/status-list/formats/cwt';
1168
+ *
1169
+ * const { payload, statusList } = parseCWTStatusList(cwtBytes);
1170
+ *
1171
+ * // Check credential status
1172
+ * const status = statusList.getStatus(42);
1173
+ * ```
1174
+ */
1175
+ declare function parseCWTStatusList(cwtBytes: Uint8Array): ParsedCWTStatusList & {
1176
+ statusList: StatusList;
1177
+ };
1178
+ /**
1179
+ * Parses a signed CWT Status List (COSE Sign1).
1180
+ *
1181
+ * This function verifies the COSE Sign1 signature and extracts the payload.
1182
+ *
1183
+ * @param cwtBytes - CBOR-encoded COSE Sign1 structure
1184
+ * @param publicKey - Public key for verification
1185
+ * @returns Parsed payload and decompressed status list
1186
+ * @throws {InvalidTokenFormatError} If verification fails
1187
+ *
1188
+ * @example
1189
+ * ```typescript
1190
+ * const publicKey = { kty: 'EC2', crv: 'P-256', x: ..., y: ... };
1191
+ * const { payload, statusList } = parseCWTStatusListSigned(cwtBytes, publicKey);
1192
+ * ```
1193
+ */
1194
+ declare function parseCWTStatusListSigned(cwtBytes: Uint8Array, publicKey: COSEKey): ParsedCWTStatusList & {
1195
+ statusList: StatusList;
1196
+ };
1197
+ /**
1198
+ * Signs a CWT Status List using COSE Sign1.
1199
+ *
1200
+ * Note: This is a basic implementation. For production use with real cryptographic
1201
+ * keys, consider using a dedicated COSE library like `@transmute/cose`.
1202
+ *
1203
+ * @param payload - CWT payload
1204
+ * @param privateKey - COSE private key
1205
+ * @param options - Signing options
1206
+ * @returns CBOR-encoded COSE Sign1 structure
1207
+ *
1208
+ * @example
1209
+ * ```typescript
1210
+ * const payload = createCWTStatusListPayload({ ... });
1211
+ * const privateKey = { kty: 'EC2', crv: 'P-256', x: ..., y: ..., d: ... };
1212
+ *
1213
+ * const cwt = signCWTStatusList(payload, privateKey, {
1214
+ * alg: -7, // ES256
1215
+ * kid: new TextEncoder().encode('key-123'),
1216
+ * });
1217
+ * ```
1218
+ */
1219
+ declare function signCWTStatusList(payload: StatusListCWTPayload, privateKey: COSEKey, options?: SignCWTOptions): Uint8Array;
1220
+ /**
1221
+ * Extracts the status list reference from an mdoc or CBOR-encoded credential.
1222
+ *
1223
+ * @param credentialCBOR - CBOR-encoded credential containing a status claim
1224
+ * @returns Status list reference (idx and uri)
1225
+ * @throws {InvalidTokenFormatError} If the status claim is missing or invalid
1226
+ */
1227
+ declare function extractStatusListReferenceCBOR(credentialCBOR: Uint8Array): StatusListReferenceCBOR;
1228
+
1229
+ /**
1230
+ * Creates a COSE Sign1 signature structure.
1231
+ *
1232
+ * COSE_Sign1 = [
1233
+ * protected: bstr, // Serialized protected header
1234
+ * unprotected: {}, // Unprotected header map
1235
+ * payload: bstr, // The payload
1236
+ * signature: bstr // The signature
1237
+ * ]
1238
+ *
1239
+ * @param payload - Payload to sign (CBOR-encoded)
1240
+ * @param protectedHeader - Protected header parameters
1241
+ * @param privateKey - COSE private key
1242
+ * @returns CBOR-encoded COSE Sign1 structure with tag
1243
+ */
1244
+ declare function signCOSE(payload: Uint8Array, protectedHeader: Map<number, unknown>, privateKey: COSEKey): Uint8Array;
1245
+ /**
1246
+ * Verifies a COSE Sign1 signature.
1247
+ *
1248
+ * @param coseSign1 - CBOR-encoded COSE Sign1 structure
1249
+ * @param publicKey - COSE public key
1250
+ * @returns Verified payload
1251
+ * @throws {InvalidTokenFormatError} If verification fails
1252
+ */
1253
+ declare function verifyCOSE(coseSign1: Uint8Array, publicKey: COSEKey): Uint8Array;
1254
+
1255
+ /**
1256
+ * Options for fetching a Status List Token.
1257
+ */
1258
+ interface FetchOptions {
1259
+ /**
1260
+ * Request timeout in milliseconds.
1261
+ * Default: 10000 (10 seconds)
1262
+ */
1263
+ timeout?: number;
1264
+ /**
1265
+ * Additional HTTP headers to include in the request.
1266
+ */
1267
+ headers?: Record<string, string>;
1268
+ /**
1269
+ * Maximum number of redirects to follow.
1270
+ * Per IETF spec Section 11.4, limit redirects to prevent DoS attacks.
1271
+ * Default: 3
1272
+ */
1273
+ maxRedirects?: number;
1274
+ /**
1275
+ * Custom fetch implementation.
1276
+ * Useful for testing or custom environments.
1277
+ * Default: global fetch
1278
+ */
1279
+ fetchImpl?: typeof fetch;
1280
+ }
1281
+ /**
1282
+ * Fetches a Status List Token from a URI via HTTP GET.
1283
+ *
1284
+ * Automatically detects JWT vs CWT format based on Content-Type header.
1285
+ * Follows IETF spec security recommendations:
1286
+ * - Enforces timeout to prevent DoS
1287
+ * - Limits redirects (default: 3)
1288
+ * - Validates Content-Type header
1289
+ *
1290
+ * @param uri - URI of the Status List Token
1291
+ * @param options - Fetch options
1292
+ * @returns JWT as string or CWT as Uint8Array
1293
+ * @throws {MissingStatusListUriError} If URI is missing or invalid
1294
+ * @throws {FetchError} If HTTP request fails
1295
+ *
1296
+ * @example
1297
+ * ```typescript
1298
+ * // Fetch JWT Status List
1299
+ * const jwt = await fetchStatusListToken('https://issuer.example.com/status/1');
1300
+ * console.log(typeof jwt); // 'string'
1301
+ *
1302
+ * // Fetch CWT Status List
1303
+ * const cwt = await fetchStatusListToken('https://issuer.example.com/status/2');
1304
+ * console.log(cwt instanceof Uint8Array); // true
1305
+ * ```
1306
+ */
1307
+ declare function fetchStatusListToken(uri: string, options?: FetchOptions): Promise<string | Uint8Array>;
1308
+ /**
1309
+ * Validates a status list URI.
1310
+ *
1311
+ * Checks:
1312
+ * - URI is not empty
1313
+ * - URI is a valid URL
1314
+ * - Protocol is HTTP or HTTPS
1315
+ *
1316
+ * @param uri - URI to validate
1317
+ * @returns True if valid
1318
+ *
1319
+ * @example
1320
+ * ```typescript
1321
+ * if (!isValidStatusListUri(uri)) {
1322
+ * throw new Error('Invalid status list URI');
1323
+ * }
1324
+ * ```
1325
+ */
1326
+ declare function isValidStatusListUri(uri: string): boolean;
1327
+
1328
+ /**
1329
+ * High-level helper for working with Status List Tokens.
1330
+ *
1331
+ * Provides a unified interface for both JWT and CWT formats.
1332
+ * Similar to the Python implementation's StatusListTokenHelper.
1333
+ *
1334
+ * @example
1335
+ * ```typescript
1336
+ * // From a credential's status reference
1337
+ * const reference = { idx: 42, uri: 'https://issuer.example.com/status/1' };
1338
+ * const helper = await StatusListTokenHelper.fromStatusReference(reference);
1339
+ *
1340
+ * // Check credential status
1341
+ * if (helper.isExpired()) {
1342
+ * throw new Error('Status list expired');
1343
+ * }
1344
+ *
1345
+ * const status = helper.getStatus(reference.idx);
1346
+ * if (status === StandardStatusValues.INVALID) {
1347
+ * console.log('Credential is revoked');
1348
+ * }
1349
+ * ```
1350
+ */
1351
+ declare class StatusListTokenHelper {
1352
+ private readonly header;
1353
+ private readonly payload;
1354
+ private readonly statusList;
1355
+ private readonly format;
1356
+ private constructor();
1357
+ /**
1358
+ * Creates a helper from a Status List Token (JWT or CWT).
1359
+ *
1360
+ * Automatically detects the format:
1361
+ * - JWT: starts with "eyJ" (base64url-encoded header)
1362
+ * - CWT: CBOR binary format
1363
+ *
1364
+ * @param token - JWT string or CWT Uint8Array
1365
+ * @returns StatusListTokenHelper instance
1366
+ * @throws {InvalidTokenFormatError} If token format is invalid
1367
+ *
1368
+ * @example
1369
+ * ```typescript
1370
+ * // From JWT
1371
+ * const helper = StatusListTokenHelper.fromToken(jwtString);
1372
+ *
1373
+ * // From CWT
1374
+ * const helper = StatusListTokenHelper.fromToken(cwtBytes);
1375
+ * ```
1376
+ */
1377
+ static fromToken(token: string | Uint8Array): StatusListTokenHelper;
1378
+ /**
1379
+ * Creates a helper by fetching a Status List Token from a URI.
1380
+ *
1381
+ * Fetches the token via HTTP GET and automatically detects the format.
1382
+ *
1383
+ * @param reference - Status reference containing idx and uri
1384
+ * @param options - Fetch options
1385
+ * @returns StatusListTokenHelper instance
1386
+ * @throws {FetchError} If HTTP request fails
1387
+ * @throws {InvalidTokenFormatError} If token format is invalid
1388
+ *
1389
+ * @example
1390
+ * ```typescript
1391
+ * const reference = {
1392
+ * idx: 42,
1393
+ * uri: 'https://issuer.example.com/status/1'
1394
+ * };
1395
+ *
1396
+ * const helper = await StatusListTokenHelper.fromStatusReference(reference);
1397
+ * const status = helper.getStatus(reference.idx);
1398
+ * ```
1399
+ */
1400
+ static fromStatusReference(reference: StatusListReference, options?: FetchOptions): Promise<StatusListTokenHelper>;
1401
+ /**
1402
+ * Gets the status value at a specific index.
1403
+ *
1404
+ * @param index - Index in the status list
1405
+ * @returns Status value (0-255 depending on bits per status)
1406
+ * @throws {IndexOutOfBoundsError} If index is out of bounds
1407
+ *
1408
+ * @example
1409
+ * ```typescript
1410
+ * const status = helper.getStatus(42);
1411
+ * if (status === StandardStatusValues.INVALID) {
1412
+ * console.log('Credential 42 is revoked');
1413
+ * }
1414
+ * ```
1415
+ */
1416
+ getStatus(index: number): StatusValue;
1417
+ /**
1418
+ * Checks if the status list token is expired.
1419
+ *
1420
+ * A token is expired if:
1421
+ * - exp is set and is in the past, OR
1422
+ * - ttl is set and iat + ttl is in the past
1423
+ *
1424
+ * @param currentTime - Current time (seconds since epoch). Defaults to now.
1425
+ * @returns True if expired
1426
+ *
1427
+ * @example
1428
+ * ```typescript
1429
+ * if (helper.isExpired()) {
1430
+ * throw new Error('Status list expired - fetch a new one');
1431
+ * }
1432
+ * ```
1433
+ */
1434
+ isExpired(currentTime?: number): boolean;
1435
+ /**
1436
+ * Gets the issuer identifier (iss claim).
1437
+ *
1438
+ * @returns Issuer string or undefined if not set
1439
+ */
1440
+ get iss(): string | undefined;
1441
+ /**
1442
+ * Gets the subject identifier (sub claim).
1443
+ *
1444
+ * @returns Subject string or undefined if not set
1445
+ */
1446
+ get sub(): string | undefined;
1447
+ /**
1448
+ * Gets the issued at time (iat claim).
1449
+ *
1450
+ * @returns Timestamp in seconds since epoch, or undefined if not set
1451
+ */
1452
+ get iat(): number | undefined;
1453
+ /**
1454
+ * Gets the expiration time (exp claim).
1455
+ *
1456
+ * @returns Timestamp in seconds since epoch, or undefined if not set
1457
+ */
1458
+ get exp(): number | undefined;
1459
+ /**
1460
+ * Gets the time to live (ttl claim).
1461
+ *
1462
+ * @returns TTL in seconds, or undefined if not set
1463
+ */
1464
+ get ttl(): number | undefined;
1465
+ /**
1466
+ * Gets the number of bits per status entry.
1467
+ *
1468
+ * @returns Bits per status (1, 2, 4, or 8)
1469
+ */
1470
+ get bits(): BitsPerStatus;
1471
+ /**
1472
+ * Gets the aggregation URI if set.
1473
+ *
1474
+ * @returns Aggregation URI or undefined if not set
1475
+ */
1476
+ get aggregationUri(): string | undefined;
1477
+ /**
1478
+ * Gets the format of the token.
1479
+ *
1480
+ * @returns 'jwt' or 'cwt'
1481
+ */
1482
+ get tokenFormat(): 'jwt' | 'cwt';
1483
+ /**
1484
+ * Gets the size of the status list.
1485
+ *
1486
+ * @returns Number of status entries
1487
+ */
1488
+ get size(): number;
1489
+ /**
1490
+ * Gets the raw header.
1491
+ *
1492
+ * @returns Header as object (JWT) or Map (CWT)
1493
+ */
1494
+ getHeader(): Record<string, unknown> | Map<number, unknown>;
1495
+ /**
1496
+ * Gets the raw payload.
1497
+ *
1498
+ * @returns Payload object
1499
+ */
1500
+ getPayload(): StatusListJWTPayload | StatusListCWTPayload;
1501
+ /**
1502
+ * Gets the underlying StatusList instance.
1503
+ *
1504
+ * @returns StatusList instance
1505
+ */
1506
+ getStatusList(): StatusList;
1507
+ }
1508
+
1509
+ /**
1510
+ * Validation result with detailed error messages.
1511
+ */
1512
+ interface ValidationResult {
1513
+ /**
1514
+ * Whether the validation passed.
1515
+ */
1516
+ valid: boolean;
1517
+ /**
1518
+ * List of validation error messages.
1519
+ * Empty if valid is true.
1520
+ */
1521
+ errors: string[];
1522
+ }
1523
+ /**
1524
+ * Validates a JWT Status List payload.
1525
+ *
1526
+ * Checks:
1527
+ * - Required claims (iss, sub, iat, status_list)
1528
+ * - status_list structure (bits, lst)
1529
+ * - bits value (must be 1, 2, 4, or 8)
1530
+ * - lst format (must be a non-empty string)
1531
+ * - Optional claims format (exp, ttl)
1532
+ *
1533
+ * @param payload - JWT payload to validate
1534
+ * @returns Validation result
1535
+ *
1536
+ * @example
1537
+ * ```typescript
1538
+ * const result = validateJWTPayload(payload);
1539
+ * if (!result.valid) {
1540
+ * console.error('Validation errors:', result.errors);
1541
+ * }
1542
+ * ```
1543
+ */
1544
+ declare function validateJWTPayload(payload: StatusListJWTPayload): ValidationResult;
1545
+ /**
1546
+ * Validates a CWT Status List payload.
1547
+ *
1548
+ * Checks:
1549
+ * - Required claims (status_list with numeric key 65533)
1550
+ * - status_list structure (bits, lst)
1551
+ * - bits value (must be 1, 2, 4, or 8)
1552
+ * - lst format (must be a Uint8Array)
1553
+ * - Optional claims format (iss, sub, iat, exp, ttl)
1554
+ *
1555
+ * @param payload - CWT payload to validate
1556
+ * @returns Validation result
1557
+ *
1558
+ * @example
1559
+ * ```typescript
1560
+ * const result = validateCWTPayload(payload);
1561
+ * if (!result.valid) {
1562
+ * console.error('Validation errors:', result.errors);
1563
+ * }
1564
+ * ```
1565
+ */
1566
+ declare function validateCWTPayload(payload: StatusListCWTPayload): ValidationResult;
1567
+ /**
1568
+ * Validates expiration and freshness of a status list token.
1569
+ *
1570
+ * Checks:
1571
+ * - If exp is set, validates it's not in the past
1572
+ * - If ttl is set, validates freshness based on iat + ttl
1573
+ * - Ensures iat is not in the future
1574
+ *
1575
+ * @param exp - Expiration time (seconds since epoch)
1576
+ * @param iat - Issued at time (seconds since epoch)
1577
+ * @param ttl - Time to live in seconds
1578
+ * @param currentTime - Current time (seconds since epoch). Defaults to now.
1579
+ * @returns Validation result
1580
+ *
1581
+ * @example
1582
+ * ```typescript
1583
+ * const result = validateExpiry(payload.exp, payload.iat, payload.ttl);
1584
+ * if (!result.valid) {
1585
+ * console.error('Token expired or not yet valid');
1586
+ * }
1587
+ * ```
1588
+ */
1589
+ declare function validateExpiry(exp?: number, iat?: number, ttl?: number, currentTime?: number): ValidationResult;
1590
+ /**
1591
+ * Validates TTL value is within recommended bounds.
1592
+ *
1593
+ * Per IETF spec Section 11.5, excessively large TTL values can be used
1594
+ * for DoS attacks by causing verifiers to cache stale status lists.
1595
+ *
1596
+ * Recommended bounds:
1597
+ * - Minimum: 60 seconds (1 minute)
1598
+ * - Maximum: 31536000 seconds (1 year)
1599
+ *
1600
+ * @param ttl - Time to live in seconds
1601
+ * @returns Validation result
1602
+ *
1603
+ * @example
1604
+ * ```typescript
1605
+ * const result = validateTTLBounds(payload.ttl);
1606
+ * if (!result.valid) {
1607
+ * console.warn('TTL outside recommended bounds:', result.errors);
1608
+ * }
1609
+ * ```
1610
+ */
1611
+ declare function validateTTLBounds(ttl?: number): ValidationResult;
1612
+ /**
1613
+ * Checks if a status list token is expired.
1614
+ *
1615
+ * A token is considered expired if:
1616
+ * - exp is set and is in the past, OR
1617
+ * - ttl is set and iat + ttl is in the past
1618
+ *
1619
+ * @param exp - Expiration time (seconds since epoch)
1620
+ * @param iat - Issued at time (seconds since epoch)
1621
+ * @param ttl - Time to live in seconds
1622
+ * @param currentTime - Current time (seconds since epoch). Defaults to now.
1623
+ * @returns True if expired
1624
+ *
1625
+ * @example
1626
+ * ```typescript
1627
+ * if (isExpired(payload.exp, payload.iat, payload.ttl)) {
1628
+ * throw new Error('Status list expired');
1629
+ * }
1630
+ * ```
1631
+ */
1632
+ declare function isExpired(exp?: number, iat?: number, ttl?: number, currentTime?: number): boolean;
1633
+
1634
+ export { type BitsPerStatus, type COSEKey, COSE_ALGORITHMS, COSE_HEADERS, CWT_CLAIMS, CompressionError, type CreateCWTStatusListOptions, type CreateJWTStatusListOptions, type EC2Key, FetchError, type FetchOptions, IndexOutOfBoundsError, InvalidBitSizeError, InvalidStatusValueError, InvalidTokenFormatError, MissingStatusListUriError, type OKPKey, type ParsedCWTStatusList, type ParsedJWTStatusList, type SignCWTOptions, type SignJWTOptions, StandardStatusValues, type StatusFormat, StatusList, type StatusListCWTClaim, type StatusListCWTPayload, type StatusListClaim, type StatusListConfig, StatusListError, StatusListExpiredError, type StatusListJWTHeader, type StatusListJWTPayload, type StatusListReference, type StatusListReferenceCBOR, StatusListTokenHelper, type StatusValue, type TokenStatusClaim, ValidationError, type ValidationResult, type VerifiedStatusListJWT, type VerifyJWTOptions, calculateCapacity, compress, compressToBase64URL, createCWTStatusListPayload, createJWTStatusListPayload, decompress, decompressFromBase64URL, encodeCWTPayload, extractStatusListReference, extractStatusListReferenceCBOR, fetchStatusListToken, getBitValue, isExpired, isValidStatusListUri, packBits, parseCWTStatusList, parseCWTStatusListSigned, parseJWTStatusList, setBitValue, signCOSE, signCWTStatusList, signStatusListJWT, unpackBits, validateCWTPayload, validateExpiry, validateJWTPayload, validateTTLBounds, verifyCOSE, verifySignatureOnly, verifyStatusListJWT };