@@ -30,6 +30,7 @@ import type {
3030 OAuthCredentials ,
3131} from "./types.js" ;
3232
33+ /** Legacy auth.json store shape before auth-profiles.json/SQLite. */
3334export type LegacyAuthStore = Record < string , AuthProfileCredential > ;
3435
3536type LoadPersistedAuthProfileStoreOptions = {
@@ -42,6 +43,8 @@ type RejectedCredentialEntry = { key: string; reason: CredentialRejectReason };
4243
4344const AUTH_PROFILE_TYPES = new Set < AuthProfileCredential [ "type" ] > ( [ "api_key" , "oauth" , "token" ] ) ;
4445
46+ // Persisted credential normalization accepts old field names and SecretRef-ish
47+ // values, then emits the current credential discriminated union.
4548function normalizeOptionalCredentialString ( value : unknown ) : string | undefined {
4649 if ( typeof value !== "string" ) {
4750 return undefined ;
@@ -70,6 +73,8 @@ function normalizeCredentialMetadata(value: unknown): Record<string, string> | u
7073 return Object . keys ( metadata ) . length > 0 ? metadata : undefined ;
7174}
7275
76+ // Secret-backed key/token fields may have been stored in the value field by old
77+ // writers. Move them to the ref field so secret values are not treated as text.
7378function normalizeSecretBackedField ( params : {
7479 entry : Record < string , unknown > ;
7580 valueField : "key" | "token" ;
@@ -258,6 +263,7 @@ function coerceLegacyAuthStore(raw: unknown): LegacyAuthStore | null {
258263 return Object . keys ( entries ) . length > 0 ? entries : null ;
259264}
260265
266+ /** Coerces a persisted auth profile store payload into the current store shape. */
261267export function coercePersistedAuthProfileStore ( raw : unknown ) : AuthProfileStore | null {
262268 if ( ! isRecord ( raw ) ) {
263269 return null ;
@@ -286,6 +292,8 @@ export function coercePersistedAuthProfileStore(raw: unknown): AuthProfileStore
286292 } ;
287293}
288294
295+ // Merge store/state records by key. Undefined means "no persisted record", not
296+ // "empty override", so preserve the other side in that case.
289297function mergeRecord < T > (
290298 base ?: Record < string , T > ,
291299 override ?: Record < string , T > ,
@@ -306,6 +314,8 @@ function dedupeMergedProfileOrder(profileIds: string[]): string[] {
306314 return uniqueStrings ( profileIds ) ;
307315}
308316
317+ // Legacy OAuth profiles may be replaced by safer main-store profiles when the
318+ // main store has a newer compatible credential for the same provider identity.
309319function hasComparableOAuthIdentityConflict (
310320 existing : OAuthCredential ,
311321 candidate : OAuthCredential ,
@@ -498,6 +508,7 @@ function reconcileMainStoreOAuthProfileDrift(params: {
498508 } ) ;
499509}
500510
511+ /** Merges two auth profile stores, preserving valid runtime external profile metadata. */
501512export function mergeAuthProfileStores (
502513 base : AuthProfileStore ,
503514 override : AuthProfileStore ,
@@ -525,6 +536,8 @@ export function mergeAuthProfileStores(
525536 : [ ] ,
526537 ) ;
527538 const profiles = { ...base . profiles , ...override . profiles } ;
539+ // Authoritative runtime snapshots may remove stale external profiles that are
540+ // no longer observed, unless the caller is intentionally preserving base ones.
528541 for ( const profileId of removedRuntimeExternalProfileIds ) {
529542 delete profiles [ profileId ] ;
530543 }
@@ -596,6 +609,7 @@ export function mergeAuthProfileStores(
596609 } ) ;
597610}
598611
612+ /** Builds the persisted secrets store, stripping resolved literals when refs exist. */
599613export function buildPersistedAuthProfileSecretsStore (
600614 store : AuthProfileStore ,
601615 shouldPersistProfile ?: ( params : {
@@ -628,6 +642,7 @@ export function buildPersistedAuthProfileSecretsStore(
628642 } ;
629643}
630644
645+ /** Applies legacy auth.json credentials into an auth profile store. */
631646export function applyLegacyAuthStore ( store : AuthProfileStore , legacy : LegacyAuthStore ) : void {
632647 for ( const [ provider , cred ] of Object . entries ( legacy ) ) {
633648 const profileId = `${ provider } :default` ;
@@ -665,6 +680,7 @@ export function applyLegacyAuthStore(store: AuthProfileStore, legacy: LegacyAuth
665680 }
666681}
667682
683+ /** Imports the legacy oauth.json file into missing default OAuth profiles. */
668684export function mergeOAuthFileIntoStore ( store : AuthProfileStore ) : boolean {
669685 const oauthPath = resolveOAuthPath ( ) ;
670686 const oauthRaw = loadJsonFile ( oauthPath ) ;
@@ -691,6 +707,7 @@ export function mergeOAuthFileIntoStore(store: AuthProfileStore): boolean {
691707 return mutated ;
692708}
693709
710+ /** Loads the persisted auth profile store and merges runtime state. */
694711export function loadPersistedAuthProfileStore (
695712 agentDir ?: string ,
696713 options ?: LoadPersistedAuthProfileStoreOptions ,
@@ -710,6 +727,7 @@ export function loadPersistedAuthProfileStore(
710727 return merged ;
711728}
712729
730+ /** Loads the legacy auth.json auth profile store if present. */
713731export function loadLegacyAuthProfileStore ( agentDir ?: string ) : LegacyAuthStore | null {
714732 return coerceLegacyAuthStore ( loadJsonFile ( resolveLegacyAuthStorePath ( agentDir ) ) ) ;
715733}
0 commit comments