@@ -354,6 +354,46 @@ function mergeImportedAuthProfileState(params: {
354354 } ;
355355}
356356
357+ function formatMissingAuthProfileSqliteVerification ( params : {
358+ expected : AuthProfileStore ;
359+ importedProfileIds : ReadonlySet < string > ;
360+ loaded : AuthProfileStore | null ;
361+ } ) : string | null {
362+ const missingProfileIds = [ ...params . importedProfileIds ] . filter (
363+ ( profileId ) => ! params . loaded ?. profiles [ profileId ] ,
364+ ) ;
365+ const missingStateFields : string [ ] = [ ] ;
366+ for ( const [ provider , profileIds ] of Object . entries ( params . expected . order ?? { } ) ) {
367+ const loadedProfileIds = params . loaded ?. order ?. [ provider ] ;
368+ if (
369+ ! loadedProfileIds ||
370+ loadedProfileIds . length !== profileIds . length ||
371+ loadedProfileIds . some ( ( profileId , index ) => profileId !== profileIds [ index ] )
372+ ) {
373+ missingStateFields . push ( `order.${ provider } ` ) ;
374+ }
375+ }
376+ for ( const [ provider , profileId ] of Object . entries ( params . expected . lastGood ?? { } ) ) {
377+ if ( params . loaded ?. lastGood ?. [ provider ] !== profileId ) {
378+ missingStateFields . push ( `lastGood.${ provider } ` ) ;
379+ }
380+ }
381+ for ( const profileId of Object . keys ( params . expected . usageStats ?? { } ) ) {
382+ if ( ! params . loaded ?. usageStats ?. [ profileId ] ) {
383+ missingStateFields . push ( `usageStats.${ profileId } ` ) ;
384+ }
385+ }
386+
387+ const parts : string [ ] = [ ] ;
388+ if ( missingProfileIds . length > 0 ) {
389+ parts . push ( `imported profile(s): ${ missingProfileIds . toSorted ( ) . join ( ", " ) } ` ) ;
390+ }
391+ if ( missingStateFields . length > 0 ) {
392+ parts . push ( `auth state field(s): ${ missingStateFields . toSorted ( ) . join ( ", " ) } ` ) ;
393+ }
394+ return parts . length > 0 ? parts . join ( "; " ) : null ;
395+ }
396+
357397function filterRawAuthProfileState (
358398 raw : Record < string , unknown > ,
359399 shouldKeepProfileId : ( profileId : string ) => boolean ,
@@ -483,9 +523,14 @@ export async function maybeMigrateAuthProfileJsonStoresToSqlite(params: {
483523 prompter : Pick < DoctorPrompter , "confirmAutoFix" > ;
484524 now ?: ( ) => number ;
485525 env ?: NodeJS . ProcessEnv ;
526+ deps ?: {
527+ loadPersistedAuthProfileStore ?: typeof loadPersistedAuthProfileStore ;
528+ } ;
486529} ) : Promise < LegacyFlatAuthProfileRepairResult > {
487530 const now = params . now ?? Date . now ;
488531 const env = params . env ?? process . env ;
532+ const loadMigratedStore =
533+ params . deps ?. loadPersistedAuthProfileStore ?? loadPersistedAuthProfileStore ;
489534 const candidates = listAuthProfileSqliteMigrationCandidates ( params . cfg , env ) ;
490535 const detected = candidates . filter (
491536 ( candidate ) =>
@@ -582,23 +627,30 @@ export async function maybeMigrateAuthProfileJsonStoresToSqlite(params: {
582627 continue ;
583628 }
584629
585- const existing = loadPersistedAuthProfileStore ( candidate . agentDir ) ?? {
630+ const existing = loadMigratedStore ( candidate . agentDir ) ?? {
586631 version : AUTH_STORE_VERSION ,
587632 profiles : { } ,
588633 } ;
589634 const existingProfileIds = new Set ( Object . keys ( existing . profiles ) ) ;
590635 const existingState = coerceAuthProfileState ( existing ) ;
591636 let next : AuthProfileStore = { ...existing } ;
637+ const importedProfileIds = new Set < string > ( ) ;
592638 if ( legacyStore ) {
593639 const legacyAsStore : AuthProfileStore = { version : AUTH_STORE_VERSION , profiles : { } } ;
594640 applyLegacyAuthStore ( legacyAsStore , legacyStore ) ;
641+ for ( const profileId of Object . keys ( legacyAsStore . profiles ) ) {
642+ importedProfileIds . add ( profileId ) ;
643+ }
595644 next = mergeImportedAuthProfiles ( {
596645 store : next ,
597646 profiles : legacyAsStore . profiles ,
598647 existingProfileIds,
599648 } ) ;
600649 }
601650 if ( canonicalStore ) {
651+ for ( const profileId of Object . keys ( canonicalStore . profiles ) ) {
652+ importedProfileIds . add ( profileId ) ;
653+ }
602654 next = {
603655 ...next ,
604656 version : Math . max ( next . version , canonicalStore . version ) ,
@@ -631,6 +683,17 @@ export async function maybeMigrateAuthProfileJsonStoresToSqlite(params: {
631683 preserveStateProfileIds : stateProfileIds ,
632684 syncExternalCli : false ,
633685 } ) ;
686+ const verificationFailure = formatMissingAuthProfileSqliteVerification ( {
687+ expected : next ,
688+ importedProfileIds,
689+ loaded : loadMigratedStore ( candidate . agentDir ) ,
690+ } ) ;
691+ if ( verificationFailure ) {
692+ result . warnings . push (
693+ `Left auth profile JSON in place for ${ shortenHomePath ( candidate . authPath ) } because SQLite verification did not find ${ verificationFailure } .` ,
694+ ) ;
695+ continue ;
696+ }
634697 }
635698
636699 const backups : string [ ] = [ ] ;
0 commit comments