* Keyring has no native "list all" — we maintain our own index in a * dedicated account named __index__. * * A3 fix: a corrupt index throws KeychainUnavailableError so the caller * can fall back to the file vault rather than silently returning [] and * stranding existing keys (they be
()
| 93 | * an exclusive file lock for cross-process safety. |
| 94 | */ |
| 95 | async list(): Promise<string[]> { |
| 96 | const mod = await loadModule() |
| 97 | const indexEntry = new mod.Entry(SERVICE_NAME, '__index__') |
| 98 | const raw = indexEntry.getPassword() |
| 99 | if (!raw) return [] |
| 100 | let parsed: unknown |
| 101 | try { |
| 102 | parsed = JSON.parse(raw) |
| 103 | } catch { |
| 104 | // A3: corrupt index — throw so caller can fall back, not silently lose key references |
| 105 | throw new KeychainUnavailableError( |
| 106 | 'keychain index is corrupt (invalid JSON). Reset via: /local-vault list (will regenerate index on next set).', |
| 107 | ) |
| 108 | } |
| 109 | if (Array.isArray(parsed)) { |
| 110 | return (parsed as unknown[]).filter( |
| 111 | (x): x is string => typeof x === 'string', |
| 112 | ) |
| 113 | } |
| 114 | return [] |
| 115 | }, |
| 116 | |
| 117 | async _addToIndex(account: string): Promise<void> { |
| 118 | const mod = await loadModule() |
nothing calls this directly
no test coverage detected