fix: isolate cleanup from key retrieval, add deleteSetting test

This commit is contained in:
2026-03-01 13:14:15 +01:00
parent 089ed70a62
commit 226c9193d6
3 changed files with 28 additions and 3 deletions

View File

@@ -62,11 +62,15 @@ async function getOpenCodeManager(): Promise<OpenCodeManager> {
// Load API key from encrypted storage
const keyStore = getSecureKeyStore();
openCodeManagerInitPromise = (async () => {
// Clean up old plain-text key from settings (pre-keychain storage)
try {
// Clean up old plain-text key from settings (pre-keychain storage)
await keyStore.cleanupPlainTextKey('opencode_api_key');
} catch {
// Best-effort cleanup; not critical
}
// Load API key from encrypted storage
// Load API key from encrypted storage
try {
const key = await keyStore.retrieve('opencode_api_key');
if (key) {
openCodeManager!.setApiKey(key);

View File

@@ -776,6 +776,23 @@ describe('ChatEngine', () => {
});
});
describe('deleteSetting', () => {
it('should delete a setting by key', async () => {
let capturedPredicate: any;
vi.mocked(mockLocalDb.delete).mockImplementation(() => ({
where: vi.fn((predicate) => {
capturedPredicate = predicate;
return Promise.resolve();
}),
} as any));
await chatEngine.deleteSetting('opencode_api_key');
expect(mockLocalDb.delete).toHaveBeenCalled();
expect(capturedPredicate).toBeDefined();
});
});
describe('setSelectedModel', () => {
it('should save selected model', async () => {
let capturedValues: any;

View File

@@ -240,7 +240,7 @@ describe('chatHandlers keychain integration', () => {
expect(manager.setApiKey).not.toHaveBeenCalled();
});
it('still initializes when cleanupPlainTextKey() throws on init', async () => {
it('still initializes and loads key when cleanupPlainTextKey() throws on init', async () => {
secureKeyStoreCleanupError = new Error('delete failed');
const mod = await import('../../src/main/ipc/chatHandlers');
@@ -252,6 +252,10 @@ describe('chatHandlers keychain integration', () => {
const result = await handler!(undefined);
// Init should complete even if cleanup fails
expect(result.ready).toBe(true);
// The encrypted key should still be loaded despite cleanup failure
const manager = openCodeManagerInstances[0];
expect(manager.setApiKey).toHaveBeenCalledWith('encrypted-stored-key');
});
it('returns error when store() throws on chat:setApiKey', async () => {