Monorepo for wisp.place. A static site hosting service built on top of the AT Protocol.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

be more specific about keystore error

+66 -7
+66 -7
cli/lib/auth.ts
··· 30 30 31 31 type KeyringEntryConstructor = new (service: string, account: string) => KeyringEntryLike 32 32 33 + interface KeychainProbeResult { 34 + available: boolean 35 + detail?: string 36 + moduleAvailable: boolean 37 + } 38 + 33 39 let keyringEntryConstructor: KeyringEntryConstructor | null | undefined 34 40 35 41 async function getKeyringEntryConstructor(): Promise<KeyringEntryConstructor | null> { ··· 45 51 return keyringEntryConstructor 46 52 } 47 53 48 - async function probeKeychain(): Promise<boolean> { 54 + function formatProbeError(error: unknown): string | undefined { 55 + if (error instanceof Error) { 56 + return error.message 57 + } 58 + if (typeof error === 'string') { 59 + return error 60 + } 61 + return undefined 62 + } 63 + 64 + function describeUnavailableKeychain(result: KeychainProbeResult): string { 65 + if (process.platform === 'darwin') { 66 + if (!result.moduleAvailable) { 67 + return 'macOS Keychain support is unavailable in this build.' 68 + } 69 + if (result.detail?.toLowerCase().includes('authorization')) { 70 + return 'macOS Keychain access could not be authorized.' 71 + } 72 + return result.detail ? `macOS Keychain access failed: ${result.detail}` : 'macOS Keychain access is unavailable.' 73 + } 74 + 75 + if (process.platform === 'linux') { 76 + if (!result.moduleAvailable) { 77 + return 'System keychain support is unavailable in this build.' 78 + } 79 + if (result.detail?.toLowerCase().includes('secret service')) { 80 + return 'System keychain is unavailable (no Secret Service daemon or equivalent).' 81 + } 82 + return result.detail ? `System keychain access failed: ${result.detail}` : 'System keychain is unavailable.' 83 + } 84 + 85 + if (process.platform === 'win32') { 86 + if (!result.moduleAvailable) { 87 + return 'Windows Credential Manager support is unavailable in this build.' 88 + } 89 + return result.detail 90 + ? `Windows Credential Manager access failed: ${result.detail}` 91 + : 'Windows Credential Manager is unavailable.' 92 + } 93 + 94 + if (!result.moduleAvailable) { 95 + return 'Secure OS credential storage is unavailable in this build.' 96 + } 97 + return result.detail ? `Secure OS credential storage failed: ${result.detail}` : 'Secure OS credential storage is unavailable.' 98 + } 99 + 100 + async function probeKeychain(): Promise<KeychainProbeResult> { 49 101 const KeyringEntry = await getKeyringEntryConstructor() 50 - if (!KeyringEntry) return false 102 + if (!KeyringEntry) { 103 + return { available: false, moduleAvailable: false } 104 + } 51 105 52 106 const testKey = '__wispctl_probe__' 53 107 try { 54 108 const entry = new KeyringEntry(KEYCHAIN_SERVICE, testKey) 55 109 entry.setPassword('1') 56 110 entry.deletePassword() 57 - return true 58 - } catch { 59 - return false 111 + return { available: true, moduleAvailable: true } 112 + } catch (error) { 113 + return { 114 + available: false, 115 + detail: formatProbeError(error), 116 + moduleAvailable: true, 117 + } 60 118 } 61 119 } 62 120 ··· 324 382 ): Promise<{ agent: Agent; did: string }> { 325 383 const kv = await openKv(options.dbPath || DEFAULT_DB_PATH) 326 384 327 - const useKeychain = await probeKeychain() 385 + const keychainProbe = await probeKeychain() 386 + const useKeychain = keychainProbe.available 328 387 if (!useKeychain) { 329 - log.warn('System keychain is unavailable (no Secret Service daemon or equivalent).') 388 + log.warn(describeUnavailableKeychain(keychainProbe)) 330 389 const fallback = await confirm({ 331 390 message: 332 391 'Fall back to storing session tokens unencrypted in SQLite? (On headless systems, prefer --password instead.)',