@learncard/types 5.21.0 → 5.22.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/auth.d.ts +216 -5
- package/dist/auth.d.ts.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/lcn.d.ts +6 -6
- package/dist/share-links.d.ts +1846 -0
- package/dist/share-links.d.ts.map +1 -0
- package/dist/types.cjs.development.cjs +523 -0
- package/dist/types.cjs.development.cjs.map +4 -4
- package/dist/types.cjs.production.min.cjs +22 -22
- package/dist/types.cjs.production.min.cjs.map +4 -4
- package/dist/types.esm.js +591 -66
- package/dist/types.esm.js.map +4 -4
- package/package.json +1 -1
- package/src/auth.ts +225 -4
- package/src/index.ts +1 -0
- package/src/share-links.ts +856 -0
package/package.json
CHANGED
package/src/auth.ts
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* coupling consumers to any specific implementation.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
|
|
9
11
|
// ---------------------------------------------------------------------------
|
|
10
12
|
// Auth Session Error
|
|
11
13
|
// ---------------------------------------------------------------------------
|
|
@@ -242,6 +244,8 @@ export interface RecoveryMethodInfo {
|
|
|
242
244
|
type: string;
|
|
243
245
|
createdAt: Date;
|
|
244
246
|
credentialId?: string;
|
|
247
|
+
shareVersion?: number;
|
|
248
|
+
confirmedAt?: Date;
|
|
245
249
|
}
|
|
246
250
|
|
|
247
251
|
/**
|
|
@@ -253,10 +257,43 @@ export interface RecoveryResult {
|
|
|
253
257
|
did: string;
|
|
254
258
|
}
|
|
255
259
|
|
|
260
|
+
export interface IdentityRecoverySession {
|
|
261
|
+
recoverySessionToken: string;
|
|
262
|
+
recoveryMethods: RecoveryMethodInfo[];
|
|
263
|
+
}
|
|
264
|
+
|
|
256
265
|
// ---------------------------------------------------------------------------
|
|
257
266
|
// Server Key Status
|
|
258
267
|
// ---------------------------------------------------------------------------
|
|
259
268
|
|
|
269
|
+
export type SssActivationState = 'provisional' | 'active';
|
|
270
|
+
|
|
271
|
+
/** Optional PIN enrollment requires rotating the existing escrow share. */
|
|
272
|
+
export type EscrowEnrollmentOptions = { pin?: string };
|
|
273
|
+
|
|
274
|
+
/** Stable error-message contract shared by PIN recovery clients and servers. */
|
|
275
|
+
export const ESCROW_PIN_LOCKED_MESSAGE =
|
|
276
|
+
'Too many incorrect PIN attempts. You can still recover by waiting.';
|
|
277
|
+
export const ESCROW_PIN_UNAVAILABLE_MESSAGE = 'PIN recovery is not available for this account.';
|
|
278
|
+
export const ESCROW_PIN_MISMATCH_PATTERN = /^Incorrect PIN\. (\d+) attempts left\.$/;
|
|
279
|
+
export const escrowPinMismatchMessage = (attemptsRemaining: number): string =>
|
|
280
|
+
`Incorrect PIN. ${attemptsRemaining} attempts left.`;
|
|
281
|
+
|
|
282
|
+
/** Public PIN availability and remaining lifetime attempts; never includes the verifier. */
|
|
283
|
+
export const EscrowPinStatusValidator = z.object({
|
|
284
|
+
state: z.enum(['none', 'enabled', 'locked', 'stale']),
|
|
285
|
+
enabled: z.boolean(),
|
|
286
|
+
attemptsRemaining: z.number().int().nonnegative(),
|
|
287
|
+
salt: z.string().optional(),
|
|
288
|
+
});
|
|
289
|
+
export type EscrowPinStatus = z.infer<typeof EscrowPinStatusValidator>;
|
|
290
|
+
|
|
291
|
+
/** Enrollment details for PIN-aware strategies. Legacy strategies may still return a string. */
|
|
292
|
+
export interface EscrowEnrollmentState {
|
|
293
|
+
state: 'enrolled' | 'not-enrolled' | 'opted-out' | 'disabled';
|
|
294
|
+
escrowPin?: EscrowPinStatus;
|
|
295
|
+
}
|
|
296
|
+
|
|
260
297
|
/**
|
|
261
298
|
* Server key status returned by the strategy's fetchServerKeyStatus.
|
|
262
299
|
* The strategy owns the server shape — different strategies may
|
|
@@ -270,8 +307,14 @@ export interface ServerKeyStatus {
|
|
|
270
307
|
authShare: string | null;
|
|
271
308
|
shareVersion: number | null;
|
|
272
309
|
maskedRecoveryEmail?: string | null;
|
|
310
|
+
escrowOptedOut?: boolean;
|
|
311
|
+
escrowPin?: EscrowPinStatus;
|
|
312
|
+
sssActivationState?: SssActivationState | null;
|
|
273
313
|
}
|
|
274
314
|
|
|
315
|
+
/** Signs a DID-Auth VP. A supplied challenge must be embedded as the VP nonce. */
|
|
316
|
+
export type DidAuthVpSigner = (privateKey: string, challenge?: string) => Promise<string>;
|
|
317
|
+
|
|
275
318
|
// ---------------------------------------------------------------------------
|
|
276
319
|
// Key Derivation Capabilities
|
|
277
320
|
// ---------------------------------------------------------------------------
|
|
@@ -348,6 +391,7 @@ export interface KeyDerivationStrategy<
|
|
|
348
391
|
TRecoveryInput = unknown,
|
|
349
392
|
TRecoverySetupInput = unknown,
|
|
350
393
|
TRecoverySetupResult = unknown,
|
|
394
|
+
TRecoveryConfirmationInput = unknown,
|
|
351
395
|
> {
|
|
352
396
|
readonly name: string;
|
|
353
397
|
|
|
@@ -365,8 +409,8 @@ export interface KeyDerivationStrategy<
|
|
|
365
409
|
/** Store a local key component */
|
|
366
410
|
storeLocalKey(key: string): Promise<void>;
|
|
367
411
|
|
|
368
|
-
/** Clear
|
|
369
|
-
clearLocalKeys(): Promise<void>;
|
|
412
|
+
/** Clear local key data; automatic stale-key cleanup may retain unresolved writes. */
|
|
413
|
+
clearLocalKeys(options?: { preservePending?: boolean }): Promise<void>;
|
|
370
414
|
|
|
371
415
|
/** Split a private key into shares/components */
|
|
372
416
|
splitKey(privateKey: string): Promise<{ localKey: string; remoteKey: string }>;
|
|
@@ -382,6 +426,38 @@ export interface KeyDerivationStrategy<
|
|
|
382
426
|
didFromPrivateKey: (pk: string) => Promise<string>
|
|
383
427
|
): Promise<boolean>;
|
|
384
428
|
|
|
429
|
+
/**
|
|
430
|
+
* Atomically split and persist a private key's local and remote components.
|
|
431
|
+
* Strategies that implement this use it for initial setup and rotations so
|
|
432
|
+
* callers never have to coordinate device/server writes themselves.
|
|
433
|
+
*/
|
|
434
|
+
atomicUpdateShares?(params: {
|
|
435
|
+
token: string;
|
|
436
|
+
providerType: AuthProviderType;
|
|
437
|
+
privateKey: string;
|
|
438
|
+
did: string;
|
|
439
|
+
signDidAuthVp?: DidAuthVpSigner;
|
|
440
|
+
}): Promise<void>;
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Repair local/server share-version skew after an ambiguous write. Returns
|
|
444
|
+
* the recovered key when reconciliation was needed, otherwise null.
|
|
445
|
+
*/
|
|
446
|
+
reconcileShares?(params: {
|
|
447
|
+
token: string;
|
|
448
|
+
providerType: AuthProviderType;
|
|
449
|
+
expectedDid: string;
|
|
450
|
+
didFromPrivateKey: (privateKey: string) => Promise<string>;
|
|
451
|
+
signDidAuthVp?: DidAuthVpSigner;
|
|
452
|
+
}): Promise<RecoveryResult | null>;
|
|
453
|
+
|
|
454
|
+
/** Obtain a short-lived, single-use challenged DID-Auth VP for a write. */
|
|
455
|
+
getFreshDidAuthVp?(
|
|
456
|
+
privateKey: string,
|
|
457
|
+
did: string,
|
|
458
|
+
signDidAuthVp: DidAuthVpSigner
|
|
459
|
+
): Promise<string>;
|
|
460
|
+
|
|
385
461
|
// --- Server communication ---
|
|
386
462
|
|
|
387
463
|
/** Fetch the server-side key status for the authenticated user */
|
|
@@ -399,8 +475,113 @@ export interface KeyDerivationStrategy<
|
|
|
399
475
|
/** Mark migration complete on the server (optional — only needed for migration-capable strategies) */
|
|
400
476
|
markMigrated?(token: string, providerType: AuthProviderType, didAuthVp?: string): Promise<void>;
|
|
401
477
|
|
|
478
|
+
/** Commit a provisioned key after the server verifies recovery enrollment. */
|
|
479
|
+
activate?(token: string, providerType: AuthProviderType, didAuthVp?: string): Promise<void>;
|
|
480
|
+
|
|
402
481
|
// --- Recovery ---
|
|
403
482
|
|
|
483
|
+
/** Read the current automatic recovery enrollment status. */
|
|
484
|
+
getEscrowEnrollmentState?(params: {
|
|
485
|
+
token: string;
|
|
486
|
+
providerType: AuthProviderType;
|
|
487
|
+
}): Promise<EscrowEnrollmentState['state'] | EscrowEnrollmentState>;
|
|
488
|
+
|
|
489
|
+
/** Opt out with an owner proof; requires another confirmed recovery method. */
|
|
490
|
+
disableEscrowRecovery?(params: {
|
|
491
|
+
token: string;
|
|
492
|
+
providerType: AuthProviderType;
|
|
493
|
+
privateKey: string;
|
|
494
|
+
signDidAuthVp: DidAuthVpSigner;
|
|
495
|
+
}): Promise<void>;
|
|
496
|
+
|
|
497
|
+
/** Opt back in and enroll automatic recovery material. */
|
|
498
|
+
enableEscrowRecovery?(params: {
|
|
499
|
+
token: string;
|
|
500
|
+
providerType: AuthProviderType;
|
|
501
|
+
privateKey: string;
|
|
502
|
+
signDidAuthVp: DidAuthVpSigner;
|
|
503
|
+
options?: EscrowEnrollmentOptions;
|
|
504
|
+
}): Promise<
|
|
505
|
+
| { enrolled: false; reason: 'disabled' | 'opted-out' }
|
|
506
|
+
| { enrolled: true; changed: false }
|
|
507
|
+
| { enrolled: true; changed: true; shareVersion: number }
|
|
508
|
+
>;
|
|
509
|
+
|
|
510
|
+
/** Repair escrow enrollment, rotating shares only when no current confirmed enrollment exists. */
|
|
511
|
+
ensureEscrowEnrollment?(params: {
|
|
512
|
+
token: string;
|
|
513
|
+
providerType: AuthProviderType;
|
|
514
|
+
privateKey: string;
|
|
515
|
+
signDidAuthVp: DidAuthVpSigner;
|
|
516
|
+
options?: EscrowEnrollmentOptions;
|
|
517
|
+
}): Promise<
|
|
518
|
+
| { enrolled: false; reason: 'disabled' | 'opted-out' }
|
|
519
|
+
| { enrolled: true; changed: false }
|
|
520
|
+
| { enrolled: true; changed: true; shareVersion: number }
|
|
521
|
+
>;
|
|
522
|
+
|
|
523
|
+
/** Set or change a PIN by rotating escrow material with an owner proof. */
|
|
524
|
+
setEscrowPin?(params: {
|
|
525
|
+
token: string;
|
|
526
|
+
providerType: AuthProviderType;
|
|
527
|
+
privateKey: string;
|
|
528
|
+
signDidAuthVp: DidAuthVpSigner;
|
|
529
|
+
pin: string;
|
|
530
|
+
}): Promise<void>;
|
|
531
|
+
|
|
532
|
+
/** Remove a PIN by rotating escrow material with an owner proof. */
|
|
533
|
+
clearEscrowPin?(params: {
|
|
534
|
+
token: string;
|
|
535
|
+
providerType: AuthProviderType;
|
|
536
|
+
privateKey: string;
|
|
537
|
+
signDidAuthVp: DidAuthVpSigner;
|
|
538
|
+
}): Promise<void>;
|
|
539
|
+
|
|
540
|
+
/** Start an escrow hold. Securely persist the returned secrets; null means an existing hold. */
|
|
541
|
+
startEscrowRecovery?(params: {
|
|
542
|
+
token?: string;
|
|
543
|
+
providerType?: AuthProviderType;
|
|
544
|
+
recoverySessionToken?: string;
|
|
545
|
+
tenantId?: string;
|
|
546
|
+
options?: { releasePolicy?: 'hold' | 'pin'; restart?: boolean };
|
|
547
|
+
}): Promise<{
|
|
548
|
+
holdId: string;
|
|
549
|
+
status: 'pending' | 'cancelled' | 'completed' | 'expired';
|
|
550
|
+
requestedAt: string;
|
|
551
|
+
releaseAfter: string;
|
|
552
|
+
cancelledAt?: string;
|
|
553
|
+
completedAt?: string;
|
|
554
|
+
resumeToken: string | null;
|
|
555
|
+
clientEphemeralPrivateKey: string;
|
|
556
|
+
pinSalt?: string;
|
|
557
|
+
/** Absent on legacy hold-only strategies. */
|
|
558
|
+
releasePolicy?: 'hold' | 'pin';
|
|
559
|
+
}>;
|
|
560
|
+
|
|
561
|
+
/** Read a hold using its resume proof or the active device's provider session. */
|
|
562
|
+
getEscrowRecoveryStatus?(
|
|
563
|
+
params:
|
|
564
|
+
| { holdId: string; resumeToken: string }
|
|
565
|
+
| { token: string; providerType: AuthProviderType }
|
|
566
|
+
): Promise<{
|
|
567
|
+
holdId: string;
|
|
568
|
+
status: 'pending' | 'cancelled' | 'completed' | 'expired';
|
|
569
|
+
requestedAt: string;
|
|
570
|
+
releaseAfter: string;
|
|
571
|
+
/** Absent on legacy hold-only strategies. */
|
|
572
|
+
releasePolicy?: 'hold' | 'pin';
|
|
573
|
+
cancelledAt?: string;
|
|
574
|
+
completedAt?: string;
|
|
575
|
+
} | null>;
|
|
576
|
+
|
|
577
|
+
/** Cancel a pending hold with a fresh, owner-signed DID challenge. */
|
|
578
|
+
cancelEscrowRecovery?(params: {
|
|
579
|
+
token: string;
|
|
580
|
+
providerType: AuthProviderType;
|
|
581
|
+
privateKey: string;
|
|
582
|
+
signDidAuthVp: DidAuthVpSigner;
|
|
583
|
+
}): Promise<{ cancelled: boolean }>;
|
|
584
|
+
|
|
404
585
|
/** Execute a recovery flow and return the recovered private key + DID */
|
|
405
586
|
executeRecovery(params: {
|
|
406
587
|
token: string;
|
|
@@ -408,6 +589,8 @@ export interface KeyDerivationStrategy<
|
|
|
408
589
|
input: TRecoveryInput;
|
|
409
590
|
/** Optional: validate the reconstructed key's DID before rotating shares */
|
|
410
591
|
didFromPrivateKey?: (privateKey: string) => Promise<string>;
|
|
592
|
+
/** Optional: sign the fresh challenge required to persist rotated shares */
|
|
593
|
+
signDidAuthVp?: DidAuthVpSigner;
|
|
411
594
|
}): Promise<RecoveryResult>;
|
|
412
595
|
|
|
413
596
|
/** Set up a new recovery method */
|
|
@@ -418,15 +601,52 @@ export interface KeyDerivationStrategy<
|
|
|
418
601
|
input: TRecoverySetupInput;
|
|
419
602
|
authUser?: AuthUser;
|
|
420
603
|
/** Optional: sign a DID-Auth VP JWT for server write operations */
|
|
421
|
-
signDidAuthVp?:
|
|
604
|
+
signDidAuthVp?: DidAuthVpSigner;
|
|
422
605
|
}): Promise<TRecoverySetupResult>;
|
|
423
606
|
|
|
607
|
+
/** Confirm a pending method after the strategy verifies proof of receipt locally. */
|
|
608
|
+
confirmRecoveryMethod?(params: {
|
|
609
|
+
token: string;
|
|
610
|
+
providerType: AuthProviderType;
|
|
611
|
+
privateKey: string;
|
|
612
|
+
input: TRecoveryConfirmationInput;
|
|
613
|
+
signDidAuthVp?: DidAuthVpSigner;
|
|
614
|
+
}): Promise<void>;
|
|
615
|
+
|
|
424
616
|
/** Get configured recovery methods for the authenticated user */
|
|
425
617
|
getAvailableRecoveryMethods?(
|
|
426
618
|
token: string,
|
|
427
619
|
providerType: AuthProviderType
|
|
428
620
|
): Promise<RecoveryMethodInfo[]>;
|
|
429
621
|
|
|
622
|
+
// --- Lost login identity recovery ---
|
|
623
|
+
|
|
624
|
+
/** Send an OTP to the verified recovery email without requiring provider auth. */
|
|
625
|
+
startIdentityRecovery?(email: string): Promise<void>;
|
|
626
|
+
|
|
627
|
+
/** Verify the OTP and receive a one-use, recovery-scoped session. */
|
|
628
|
+
verifyIdentityRecovery?(email: string, code: string): Promise<IdentityRecoverySession>;
|
|
629
|
+
|
|
630
|
+
/** Reconstruct and hard-validate the key before the replacement login is bound. */
|
|
631
|
+
prepareIdentityRecovery?(params: {
|
|
632
|
+
recoverySessionToken: string;
|
|
633
|
+
input: TRecoveryInput;
|
|
634
|
+
didFromPrivateKey: (privateKey: string) => Promise<string>;
|
|
635
|
+
}): Promise<RecoveryResult>;
|
|
636
|
+
|
|
637
|
+
/** Whether reconstructed identity recovery is waiting for a replacement login. */
|
|
638
|
+
hasPendingIdentityRecovery?(): boolean;
|
|
639
|
+
|
|
640
|
+
/** Discard any reconstructed identity recovery that has not been rebound. */
|
|
641
|
+
cancelIdentityRecovery?(): void;
|
|
642
|
+
|
|
643
|
+
/** Bind the current provider identity and commit a full share rotation. */
|
|
644
|
+
completeIdentityRecovery?(params: {
|
|
645
|
+
token: string;
|
|
646
|
+
providerType: AuthProviderType;
|
|
647
|
+
signDidAuthVp?: DidAuthVpSigner;
|
|
648
|
+
}): Promise<RecoveryResult>;
|
|
649
|
+
|
|
430
650
|
// --- Contact method management ---
|
|
431
651
|
|
|
432
652
|
/**
|
|
@@ -467,7 +687,8 @@ export interface KeyDerivationStrategy<
|
|
|
467
687
|
token: string,
|
|
468
688
|
providerType: AuthProviderType,
|
|
469
689
|
privateKey: string,
|
|
470
|
-
email: string
|
|
690
|
+
email: string,
|
|
691
|
+
didAuthVp?: string
|
|
471
692
|
): Promise<void>;
|
|
472
693
|
|
|
473
694
|
// --- Share versioning ---
|
package/src/index.ts
CHANGED