From a9f237915da0d607d0303eb58a07856b4e4413ae Mon Sep 17 00:00:00 2001 From: iceteaSA <171169159+iceteaSA@users.noreply.github.com> Date: Fri, 26 Jun 2026 20:52:08 +0200 Subject: [PATCH] test(accounts): assert removed account secrets are pruned from the state file The removal test verified the config file no longer lists the deleted id, but not that the per-account state file is scrubbed of the removed account's access/refresh tokens. A regression that rebuilt config authoritatively while leaving stale state entries would leave a deleted account's credentials at rest and pass the existing assertions. Extend the test to assert state.accounts drops the removed id and the raw state file contains neither of its tokens. --- packages/opencode/src/tests/accounts-store.test.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/opencode/src/tests/accounts-store.test.ts b/packages/opencode/src/tests/accounts-store.test.ts index 5b88a65..4f31de5 100644 --- a/packages/opencode/src/tests/accounts-store.test.ts +++ b/packages/opencode/src/tests/accounts-store.test.ts @@ -276,6 +276,15 @@ describe('mutateAccounts (authoritative structural edits)', () => { // proving the deletion was authoritative, not just an in-memory filter. const cfg = JSON.parse(readFileSync(cfgPath, 'utf8')) expect(cfg.accounts.map((a: { id: string }) => a.id)).toEqual(['a', 'c']) + + // The state file is rebuilt from the authoritative account set, so the + // removed account's per-account secrets must not linger at rest — a stale + // access/refresh token for a deleted account is a credential leak. + const stateRaw = readFileSync(statePath, 'utf8') + const state = JSON.parse(stateRaw) + expect(Object.keys(state.accounts ?? {}).sort()).toEqual(['a', 'c']) + expect(stateRaw).not.toContain('acc-b') + expect(stateRaw).not.toContain('ref-b') }) it('reordering persists (union-merge would have ignored it)', async () => {