@@ -6,7 +6,11 @@ import { resolveOAuthDir } from "../../config/paths.js";
66import { AUTH_STORE_VERSION } from "./constants.js" ;
77import { legacyOAuthSidecarTestUtils } from "./legacy-oauth-sidecar.js" ;
88import { resolveAuthStorePath } from "./paths.js" ;
9- import { coercePersistedAuthProfileStore , loadPersistedAuthProfileStore } from "./persisted.js" ;
9+ import {
10+ coercePersistedAuthProfileStore ,
11+ loadPersistedAuthProfileStore ,
12+ mergeAuthProfileStores ,
13+ } from "./persisted.js" ;
1014
1115function withEnvValue ( key : string , value : string | undefined ) : ( ) => void {
1216 const previous = process . env [ key ] ;
@@ -212,4 +216,139 @@ describe("persisted auth profile boundary", () => {
212216 fs . rmSync ( stateDir , { recursive : true , force : true } ) ;
213217 }
214218 } ) ;
219+
220+ it ( "lets authoritative runtime external metadata remove stale base profiles" , ( ) => {
221+ const merged = mergeAuthProfileStores (
222+ {
223+ version : AUTH_STORE_VERSION ,
224+ runtimeExternalProfileIds : [ "anthropic:claude-cli" ] ,
225+ runtimeExternalProfileIdsAuthoritative : true ,
226+ profiles : {
227+ "anthropic:claude-cli" : {
228+ type : "oauth" ,
229+ provider : "anthropic" ,
230+ access : "stale-access" ,
231+ refresh : "stale-refresh" ,
232+ expires : 1 ,
233+ } ,
234+ } ,
235+ order : {
236+ anthropic : [ "anthropic:claude-cli" ] ,
237+ } ,
238+ lastGood : {
239+ anthropic : "anthropic:claude-cli" ,
240+ } ,
241+ } ,
242+ {
243+ version : AUTH_STORE_VERSION ,
244+ runtimeExternalProfileIds : [ ] ,
245+ runtimeExternalProfileIdsAuthoritative : true ,
246+ profiles : { } ,
247+ } ,
248+ ) ;
249+
250+ expect ( merged . runtimeExternalProfileIds ) . toEqual ( [ ] ) ;
251+ expect ( merged . runtimeExternalProfileIdsAuthoritative ) . toBe ( true ) ;
252+ expect ( merged . profiles [ "anthropic:claude-cli" ] ) . toBeUndefined ( ) ;
253+ expect ( merged . order ?. anthropic ) . toBeUndefined ( ) ;
254+ expect ( merged . lastGood ?. anthropic ) . toBeUndefined ( ) ;
255+ } ) ;
256+
257+ it ( "keeps override profiles when authoritative metadata removes base runtime external state" , ( ) => {
258+ const profileId = "anthropic:claude-cli" ;
259+ const merged = mergeAuthProfileStores (
260+ {
261+ version : AUTH_STORE_VERSION ,
262+ runtimeExternalProfileIds : [ profileId ] ,
263+ runtimeExternalProfileIdsAuthoritative : true ,
264+ profiles : {
265+ [ profileId ] : {
266+ type : "oauth" ,
267+ provider : "anthropic" ,
268+ access : "stale-access" ,
269+ refresh : "stale-refresh" ,
270+ expires : 1 ,
271+ } ,
272+ } ,
273+ order : {
274+ anthropic : [ profileId ] ,
275+ } ,
276+ lastGood : {
277+ anthropic : profileId ,
278+ } ,
279+ } ,
280+ {
281+ version : AUTH_STORE_VERSION ,
282+ runtimeExternalProfileIds : [ ] ,
283+ runtimeExternalProfileIdsAuthoritative : true ,
284+ profiles : {
285+ [ profileId ] : {
286+ type : "api_key" ,
287+ provider : "anthropic" ,
288+ key : "sk-local" ,
289+ } ,
290+ } ,
291+ order : {
292+ anthropic : [ profileId ] ,
293+ } ,
294+ lastGood : {
295+ anthropic : profileId ,
296+ } ,
297+ } ,
298+ ) ;
299+
300+ expect ( merged . runtimeExternalProfileIds ) . toEqual ( [ ] ) ;
301+ expect ( merged . runtimeExternalProfileIdsAuthoritative ) . toBe ( true ) ;
302+ expect ( merged . profiles [ profileId ] ) . toMatchObject ( {
303+ type : "api_key" ,
304+ provider : "anthropic" ,
305+ key : "sk-local" ,
306+ } ) ;
307+ expect ( merged . order ?. anthropic ) . toEqual ( [ profileId ] ) ;
308+ expect ( merged . lastGood ?. anthropic ) . toBe ( profileId ) ;
309+ } ) ;
310+
311+ it ( "preserves inherited base runtime external profiles during agent-store merges" , ( ) => {
312+ const profileId = "anthropic:claude-cli" ;
313+ const merged = mergeAuthProfileStores (
314+ {
315+ version : AUTH_STORE_VERSION ,
316+ runtimeExternalProfileIds : [ profileId ] ,
317+ runtimeExternalProfileIdsAuthoritative : true ,
318+ profiles : {
319+ [ profileId ] : {
320+ type : "oauth" ,
321+ provider : "anthropic" ,
322+ access : "main-access" ,
323+ refresh : "main-refresh" ,
324+ expires : 1 ,
325+ } ,
326+ } ,
327+ order : {
328+ anthropic : [ profileId ] ,
329+ } ,
330+ lastGood : {
331+ anthropic : profileId ,
332+ } ,
333+ } ,
334+ {
335+ version : AUTH_STORE_VERSION ,
336+ runtimeExternalProfileIds : [ ] ,
337+ runtimeExternalProfileIdsAuthoritative : true ,
338+ profiles : { } ,
339+ } ,
340+ { preserveBaseRuntimeExternalProfiles : true } ,
341+ ) ;
342+
343+ expect ( merged . runtimeExternalProfileIds ) . toEqual ( [ profileId ] ) ;
344+ expect ( merged . runtimeExternalProfileIdsAuthoritative ) . toBe ( true ) ;
345+ expect ( merged . profiles [ profileId ] ) . toMatchObject ( {
346+ type : "oauth" ,
347+ provider : "anthropic" ,
348+ access : "main-access" ,
349+ refresh : "main-refresh" ,
350+ } ) ;
351+ expect ( merged . order ?. anthropic ) . toEqual ( [ profileId ] ) ;
352+ expect ( merged . lastGood ?. anthropic ) . toBe ( profileId ) ;
353+ } ) ;
215354} ) ;
0 commit comments