w3pk 0.10.1 → 0.10.3

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/README.md CHANGED
@@ -257,6 +257,8 @@ await w3pk.clearSession()
257
257
 
258
258
  **Note:** STRICT mode never allows persistent sessions.
259
259
 
260
+ **PRF-keyed persistence:** persistent sessions are encrypted under a key derived from the WebAuthn PRF extension (an authenticator-held secret, released only during a biometric/PIN-verified assertion) and re-keyed at every real login. Authenticators without PRF support get in-memory sessions only — there is no weaker at-rest fallback. See [Security Architecture](./docs/SECURITY.md) for details.
261
+
260
262
  ### RPC Endpoints
261
263
 
262
264
  ```typescript
package/dist/index.d.mts CHANGED
@@ -379,6 +379,23 @@ declare class ApiError extends Web3PasskeyError {
379
379
  statusCode?: number | undefined;
380
380
  constructor(message: string, statusCode?: number | undefined, originalError?: unknown);
381
381
  }
382
+ /**
383
+ * The passkey authenticated, but this device has no credential metadata.
384
+ * The app should start a sync or restore flow.
385
+ */
386
+ declare class SyncRequiredError extends Web3PasskeyError {
387
+ credentialId: string;
388
+ constructor(credentialId: string);
389
+ }
390
+ /**
391
+ * The credential metadata is on this device, but the wallet record is gone.
392
+ * The app should offer a restore from backup.
393
+ */
394
+ declare class WalletMissingError extends Web3PasskeyError {
395
+ credentialId: string;
396
+ ethereumAddress: string;
397
+ constructor(credentialId: string, ethereumAddress: string);
398
+ }
382
399
 
383
400
  /**
384
401
  * Persistent Session Storage
@@ -386,11 +403,22 @@ declare class ApiError extends Web3PasskeyError {
386
403
  * Enables "Remember Me" functionality for STANDARD and YOLO mode wallets.
387
404
  *
388
405
  * SECURITY:
389
- * - Sessions encrypted with WebAuthn-derived keys
406
+ * - The mnemonic blob is encrypted with a key derived from the WebAuthn PRF
407
+ * extension: a secret the authenticator releases only during a
408
+ * user-verified assertion. Nothing stored on disk can re-derive it.
409
+ * - requireReauth: true → the key is NOT stored; every restore re-evaluates
410
+ * the PRF on a live assertion. The blob is hardware-bound at rest.
411
+ * - requireReauth: false → the raw key is stored next to the blob so silent
412
+ * restore works without a prompt, and re-imported as non-extractable. Any
413
+ * script on the origin can read it, which adds little: it could already
414
+ * use a stored key to decrypt. It is refreshed at every real (prompted)
415
+ * login.
416
+ * - Authenticators without PRF get no persistent sessions (in-memory only) —
417
+ * there is deliberately no weaker fallback encryption.
390
418
  * - Only enabled for STANDARD and YOLO modes (STRICT mode excluded)
391
- * - Time-limited expiration
392
- * - Origin-isolated via IndexedDB
393
- * - Requires valid WebAuthn credential to decrypt
419
+ * - Time-limited expiration; the expiry IS the renewal boundary: when the
420
+ * blob expires, the next login prompts, and that assertion's PRF output
421
+ * re-keys a fresh blob.
394
422
  */
395
423
 
396
424
  /**
@@ -453,6 +481,89 @@ interface Web3PasskeyConfig {
453
481
  zkProofs?: ZKProofConfig;
454
482
  }
455
483
 
484
+ /**
485
+ * Backup and Recovery Type Definitions
486
+ */
487
+ type BackupMethod = 'file' | 'qr' | 'phrase';
488
+ interface BackupStatus {
489
+ hasBackup: boolean;
490
+ lastBackupAt?: string;
491
+ methods: BackupMethod[];
492
+ passkeySync: PasskeySyncStatus;
493
+ recoveryPhrase: RecoveryPhraseStatus;
494
+ socialRecovery?: SocialRecoveryStatus;
495
+ securityScore: SecurityScore;
496
+ }
497
+ interface PasskeySyncStatus {
498
+ enabled: boolean;
499
+ deviceCount: number;
500
+ lastSyncTime?: string;
501
+ platform: 'apple' | 'google' | 'microsoft' | 'unknown';
502
+ }
503
+ interface RecoveryPhraseStatus {
504
+ verified: boolean;
505
+ verificationCount: number;
506
+ lastVerified?: string;
507
+ encryptedBackups: EncryptedBackupInfo[];
508
+ }
509
+ interface EncryptedBackupInfo {
510
+ id: string;
511
+ method: 'qr' | 'file';
512
+ location: string;
513
+ createdAt: string;
514
+ deviceFingerprint?: string;
515
+ }
516
+ interface SocialRecoveryStatus {
517
+ enabled: boolean;
518
+ guardians: Guardian$1[];
519
+ threshold: number;
520
+ sharesDistributed: number;
521
+ verifiedGuardians: number;
522
+ }
523
+ interface Guardian$1 {
524
+ id: string;
525
+ name: string;
526
+ email?: string;
527
+ publicKey?: string;
528
+ shareEncrypted: string;
529
+ status: 'pending' | 'active' | 'revoked';
530
+ addedAt: string;
531
+ lastVerified?: string;
532
+ }
533
+ interface SecurityScore {
534
+ total: number;
535
+ breakdown: {
536
+ passkeyActive: number;
537
+ passkeyMultiDevice: number;
538
+ phraseVerified: number;
539
+ encryptedBackup: number;
540
+ socialRecovery: number;
541
+ };
542
+ level: 'vulnerable' | 'protected' | 'secured' | 'fort-knox';
543
+ nextMilestone: string;
544
+ }
545
+ interface QRBackupOptions {
546
+ password?: string;
547
+ errorCorrection?: 'L' | 'M' | 'Q' | 'H';
548
+ }
549
+ interface RecoveryScenario {
550
+ type: 'lost-device' | 'lost-phrase' | 'lost-both' | 'switch-platform';
551
+ description: string;
552
+ }
553
+ interface SimulationResult {
554
+ scenario: RecoveryScenario;
555
+ success: boolean;
556
+ availableMethods: RecoveryMethod[];
557
+ timeEstimate: string;
558
+ educationalNote: string;
559
+ }
560
+ interface RecoveryMethod {
561
+ method: string;
562
+ success: boolean;
563
+ time: string;
564
+ requirements: string[];
565
+ }
566
+
456
567
  /**
457
568
  * Main Web3Passkey SDK
458
569
  *
@@ -486,6 +597,7 @@ declare class Web3Passkey {
486
597
  private walletStorage;
487
598
  private currentUser;
488
599
  private currentWallet;
600
+ private persisted;
489
601
  private sessionManager;
490
602
  stealth?: StealthAddressModule;
491
603
  private zkModule?;
@@ -509,6 +621,7 @@ declare class Web3Passkey {
509
621
  }): Promise<{
510
622
  address: string;
511
623
  username: string;
624
+ hasBackup: boolean;
512
625
  }>;
513
626
  /**
514
627
  * Login with WebAuthn using resident credentials
@@ -521,10 +634,24 @@ declare class Web3Passkey {
521
634
  login(): Promise<UserInfo>;
522
635
  /**
523
636
  * Logout current user and clear session
637
+ *
638
+ * The user is always logged out in memory, even if clearing persistent
639
+ * storage fails — in that case a StorageError is thrown so the app knows
640
+ * a persistent session may still exist on the device
641
+ *
642
+ * @throws {StorageError} if persistent sessions could not be cleared
524
643
  */
525
644
  logout(): Promise<void>;
526
645
  get isAuthenticated(): boolean;
527
646
  get user(): UserInfo | null;
647
+ /**
648
+ * Whether the browser granted persistent storage (`navigator.storage.persist()`),
649
+ * requested after each register, login and restore: true means the origin's
650
+ * storage is exempt from storage-pressure eviction. null until the browser
651
+ * answers (Firefox asks the user), or where the API is missing.
652
+ */
653
+ get storagePersisted(): boolean | null;
654
+ private requestPersistentStorage;
528
655
  /**
529
656
  * List existing credentials (usernames and addresses)
530
657
  * Useful for allowing users to select which wallet to login to
@@ -859,7 +986,12 @@ declare class Web3Passkey {
859
986
  /**
860
987
  * Get backup status
861
988
  */
862
- getBackupStatus(): Promise<any>;
989
+ getBackupStatus(): Promise<BackupStatus>;
990
+ /**
991
+ * Record that the user wrote down their recovery phrase
992
+ * Call it once the user confirms, so getBackupStatus() reports a backup
993
+ */
994
+ confirmRecoveryPhraseBackup(): Promise<void>;
863
995
  /**
864
996
  * Create simplified backup file
865
997
  * This backup can be used to:
@@ -1008,7 +1140,9 @@ declare class Web3Passkey {
1008
1140
  extendSession(): void;
1009
1141
  /**
1010
1142
  * Clear active session
1011
- * Also clears ALL persistent sessions from IndexedDB
1143
+ * Also clears ALL persistent sessions from localStorage
1144
+ *
1145
+ * @throws {StorageError} if persistent sessions could not be cleared
1012
1146
  */
1013
1147
  clearSession(): Promise<void>;
1014
1148
  /**
@@ -1016,6 +1150,14 @@ declare class Web3Passkey {
1016
1150
  * @param hours - Duration in hours
1017
1151
  */
1018
1152
  setSessionDuration(hours: number): void;
1153
+ /**
1154
+ * Update the persistent-session duration (the "Remember Me" window).
1155
+ * Takes effect the next time a session is persisted — i.e. at the next
1156
+ * real (prompted) login, which is also when the blob is re-keyed with a
1157
+ * fresh PRF-derived key. The duration is therefore the renewal interval.
1158
+ * @param hours - Duration in hours
1159
+ */
1160
+ setPersistentSessionDuration(hours: number): void;
1019
1161
  /**
1020
1162
  * Derive ML-KEM-1024 public key from the current wallet
1021
1163
  *
@@ -1301,6 +1443,15 @@ declare function verifyEIP7702Authorization(chainId: bigint, contractAddress: st
1301
1443
  s: string;
1302
1444
  } | string, expectedSigner: string): boolean;
1303
1445
 
1446
+ /** Client extension results consumed by w3pk (subset of the WebAuthn spec) */
1447
+ interface PrfExtensionResults {
1448
+ prf?: {
1449
+ enabled?: boolean;
1450
+ results?: {
1451
+ first?: ArrayBuffer;
1452
+ };
1453
+ };
1454
+ }
1304
1455
  /**
1305
1456
  * Native WebAuthn credential response (authentication)
1306
1457
  */
@@ -1314,14 +1465,7 @@ interface AuthenticationCredential {
1314
1465
  signature: ArrayBuffer;
1315
1466
  userHandle?: ArrayBuffer;
1316
1467
  };
1317
- getClientExtensionResults(): {
1318
- prf?: {
1319
- results?: {
1320
- first?: ArrayBuffer;
1321
- second?: ArrayBuffer;
1322
- };
1323
- };
1324
- };
1468
+ getClientExtensionResults(): PrfExtensionResults;
1325
1469
  }
1326
1470
 
1327
1471
  /**
@@ -1390,85 +1534,6 @@ declare function getCurrentOrigin(): string;
1390
1534
  */
1391
1535
  declare function deriveAddressFromP256PublicKey(publicKeySpki: string): Promise<string>;
1392
1536
 
1393
- /**
1394
- * Backup and Recovery Type Definitions
1395
- */
1396
- interface BackupStatus {
1397
- passkeySync: PasskeySyncStatus;
1398
- recoveryPhrase: RecoveryPhraseStatus;
1399
- socialRecovery?: SocialRecoveryStatus;
1400
- securityScore: SecurityScore;
1401
- }
1402
- interface PasskeySyncStatus {
1403
- enabled: boolean;
1404
- deviceCount: number;
1405
- lastSyncTime?: string;
1406
- platform: 'apple' | 'google' | 'microsoft' | 'unknown';
1407
- }
1408
- interface RecoveryPhraseStatus {
1409
- verified: boolean;
1410
- verificationCount: number;
1411
- lastVerified?: string;
1412
- encryptedBackups: EncryptedBackupInfo[];
1413
- }
1414
- interface EncryptedBackupInfo {
1415
- id: string;
1416
- method: 'qr' | 'file';
1417
- location: string;
1418
- createdAt: string;
1419
- deviceFingerprint?: string;
1420
- }
1421
- interface SocialRecoveryStatus {
1422
- enabled: boolean;
1423
- guardians: Guardian$1[];
1424
- threshold: number;
1425
- sharesDistributed: number;
1426
- verifiedGuardians: number;
1427
- }
1428
- interface Guardian$1 {
1429
- id: string;
1430
- name: string;
1431
- email?: string;
1432
- publicKey?: string;
1433
- shareEncrypted: string;
1434
- status: 'pending' | 'active' | 'revoked';
1435
- addedAt: string;
1436
- lastVerified?: string;
1437
- }
1438
- interface SecurityScore {
1439
- total: number;
1440
- breakdown: {
1441
- passkeyActive: number;
1442
- passkeyMultiDevice: number;
1443
- phraseVerified: number;
1444
- encryptedBackup: number;
1445
- socialRecovery: number;
1446
- };
1447
- level: 'vulnerable' | 'protected' | 'secured' | 'fort-knox';
1448
- nextMilestone: string;
1449
- }
1450
- interface QRBackupOptions {
1451
- password?: string;
1452
- errorCorrection?: 'L' | 'M' | 'Q' | 'H';
1453
- }
1454
- interface RecoveryScenario {
1455
- type: 'lost-device' | 'lost-phrase' | 'lost-both' | 'switch-platform';
1456
- description: string;
1457
- }
1458
- interface SimulationResult {
1459
- scenario: RecoveryScenario;
1460
- success: boolean;
1461
- availableMethods: RecoveryMethod[];
1462
- timeEstimate: string;
1463
- educationalNote: string;
1464
- }
1465
- interface RecoveryMethod {
1466
- method: string;
1467
- success: boolean;
1468
- time: string;
1469
- requirements: string[];
1470
- }
1471
-
1472
1537
  /**
1473
1538
  * Recovery Scenario Simulator
1474
1539
  * Educational tool to help users understand recovery options
@@ -2190,6 +2255,7 @@ interface MLKemKeypair {
2190
2255
  privateKey: Uint8Array;
2191
2256
  }
2192
2257
  interface EncryptedPayload {
2258
+ version?: 2;
2193
2259
  recipients: Array<{
2194
2260
  publicKey: string;
2195
2261
  ciphertext: string;
@@ -2286,4 +2352,4 @@ declare function mlkemDecryptWithKey(payload: EncryptedPayload, privateKey: stri
2286
2352
 
2287
2353
  declare function createWeb3Passkey(config?: Web3PasskeyConfig): Web3Passkey;
2288
2354
 
2289
- export { ApiError, AuthenticationError, type BackupStatus, type BrowserInspectOptions, type BrowserInspectResult, CryptoError, DEFAULT_MODE, DEFAULT_TAG, type DeviceInfo, type EIP1193Provider, type EIP7702Authorization, type EncryptedBackupInfo, type EncryptedPayload, type Guardian, type GuardianInvite, type MLKemKeypair, type PasskeySelectionResult, type QRBackupOptions, type RecoveryProgress, type RecoveryScenario, type RecoveryShare, RecoverySimulator, RegistrationError, type SecurityScore, type SignAuthorizationParams, type SimulationResult, type SiweMessage, type SocialRecoveryConfig, SocialRecoveryManager, type StealthAddressConfig, StealthAddressModule, type StealthAddressResult, type StealthKeys, StorageError, type SyncCapabilities, type SyncStatus, type SyncVault, type UserInfo, WalletError, type WalletInfo, Web3Passkey, type Web3PasskeyConfig, Web3PasskeyError, arrayBufferToBase64Url, assertEthereumAddress, assertMnemonic, assertUsername, authenticateWithPasskey, base64ToArrayBuffer, base64UrlDecode, base64UrlToArrayBuffer, canControlStealthAddress, checkStealthAddress, clearCache, computeStealthPrivateKey, createSiweMessage, createWalletFromMnemonic, createWeb3Passkey, createWeb3Passkey as default, deriveAddressFromP256PublicKey, deriveIndexFromOriginModeAndTag, deriveMLKemKeypair, deriveStealthKeys, deriveWalletFromMnemonic, detectWalletProvider, encodeEIP7702AuthorizationMessage, extractRS, generateBIP39Wallet, generateSiweNonce, generateStealthAddress, getAllChains, getAllTopics, getChainById, getCurrentBuildHash, getCurrentOrigin, getDefaultProvider, getEndpoints, getExplainer, getOriginSpecificAddress, getPackageVersion, getW3pkBuildHash, hashEIP7702AuthorizationMessage, inspect, inspectNow, isStrongPassword, mlkemDecrypt, mlkemDecryptWithKey, mlkemEncrypt, mlkemEncryptWithKey, normalizeOrigin, parseSiweMessage, promptPasskeySelection, requestExternalWalletAuthorization, safeAtob, safeBtoa, searchExplainers, supportsEIP7702Authorization, validateEthereumAddress, validateMnemonic, validateSiweMessage, validateUsername, verifyBuildHash, verifyEIP7702Authorization, verifySiweSignature };
2355
+ export { ApiError, AuthenticationError, type BackupMethod, type BackupStatus, type BrowserInspectOptions, type BrowserInspectResult, CryptoError, DEFAULT_MODE, DEFAULT_TAG, type DeviceInfo, type EIP1193Provider, type EIP7702Authorization, type EncryptedBackupInfo, type EncryptedPayload, type Guardian, type GuardianInvite, type MLKemKeypair, type PasskeySelectionResult, type QRBackupOptions, type RecoveryProgress, type RecoveryScenario, type RecoveryShare, RecoverySimulator, RegistrationError, type SecurityScore, type SignAuthorizationParams, type SimulationResult, type SiweMessage, type SocialRecoveryConfig, SocialRecoveryManager, type StealthAddressConfig, StealthAddressModule, type StealthAddressResult, type StealthKeys, StorageError, type SyncCapabilities, SyncRequiredError, type SyncStatus, type SyncVault, type UserInfo, WalletError, type WalletInfo, WalletMissingError, Web3Passkey, type Web3PasskeyConfig, Web3PasskeyError, arrayBufferToBase64Url, assertEthereumAddress, assertMnemonic, assertUsername, authenticateWithPasskey, base64ToArrayBuffer, base64UrlDecode, base64UrlToArrayBuffer, canControlStealthAddress, checkStealthAddress, clearCache, computeStealthPrivateKey, createSiweMessage, createWalletFromMnemonic, createWeb3Passkey, createWeb3Passkey as default, deriveAddressFromP256PublicKey, deriveIndexFromOriginModeAndTag, deriveMLKemKeypair, deriveStealthKeys, deriveWalletFromMnemonic, detectWalletProvider, encodeEIP7702AuthorizationMessage, extractRS, generateBIP39Wallet, generateSiweNonce, generateStealthAddress, getAllChains, getAllTopics, getChainById, getCurrentBuildHash, getCurrentOrigin, getDefaultProvider, getEndpoints, getExplainer, getOriginSpecificAddress, getPackageVersion, getW3pkBuildHash, hashEIP7702AuthorizationMessage, inspect, inspectNow, isStrongPassword, mlkemDecrypt, mlkemDecryptWithKey, mlkemEncrypt, mlkemEncryptWithKey, normalizeOrigin, parseSiweMessage, promptPasskeySelection, requestExternalWalletAuthorization, safeAtob, safeBtoa, searchExplainers, supportsEIP7702Authorization, validateEthereumAddress, validateMnemonic, validateSiweMessage, validateUsername, verifyBuildHash, verifyEIP7702Authorization, verifySiweSignature };