33 * These checks intentionally avoid loading secret-bearing credential payloads.
44 */
55import fs from "node:fs" ;
6+ import { evaluateStoredCredentialEligibility } from "./credential-state.js" ;
67import {
78 resolveAuthStatePath ,
89 resolveAuthStorePath ,
910 resolveLegacyAuthStorePath ,
1011} from "./path-resolve.js" ;
12+ import { coerceLegacyAuthStore , coercePersistedAuthProfileStore } from "./persisted.js" ;
1113import {
1214 getRuntimeAuthProfileStoreSnapshot ,
1315 hasAnyRuntimeAuthProfileStoreSource ,
1416} from "./runtime-snapshots.js" ;
1517import { readPersistedAuthProfileStateRaw , readPersistedAuthProfileStoreRaw } from "./sqlite.js" ;
16- import type { AuthProfileStore } from "./types.js" ;
18+ import type { AuthProfileCredential , AuthProfileStore } from "./types.js" ;
1719
1820// Auth-profile source checks look at runtime snapshots, JSON compatibility
1921// files, legacy files, and SQLite stores without materializing secret values.
@@ -37,34 +39,58 @@ function normalizeProvider(provider: string): string {
3739 return provider . trim ( ) . toLowerCase ( ) ;
3840}
3941
40- function rawStoreHasProviderProfile ( raw : unknown , provider : string ) : boolean {
41- if ( ! raw || typeof raw !== "object" ) {
42+ function isAuthProfileCredential ( value : unknown ) : value is AuthProfileCredential {
43+ if ( ! value || typeof value !== "object" ) {
4244 return false ;
4345 }
44- const profiles = ( raw as { profiles ?: unknown } ) . profiles ;
45- if ( ! profiles || typeof profiles !== "object" ) {
46+ const credential = value as { provider ?: unknown ; type ?: unknown } ;
47+ const type = credential . type ;
48+ return (
49+ typeof credential . provider === "string" &&
50+ ( type === "api_key" || type === "token" || type === "oauth" )
51+ ) ;
52+ }
53+
54+ function isEligibleProviderCredential ( rawCredential : unknown , expectedProvider : string ) : boolean {
55+ if ( ! isAuthProfileCredential ( rawCredential ) ) {
56+ return false ;
57+ }
58+ return (
59+ normalizeProvider ( rawCredential . provider ) === expectedProvider &&
60+ evaluateStoredCredentialEligibility ( { credential : rawCredential } ) . eligible
61+ ) ;
62+ }
63+
64+ function coerceRawStoreProfiles ( raw : unknown ) : Record < string , AuthProfileCredential > | null {
65+ return coercePersistedAuthProfileStore ( raw ) ?. profiles ?? coerceLegacyAuthStore ( raw ) ;
66+ }
67+
68+ function rawStoreHasProviderProfile (
69+ raw : unknown ,
70+ provider : string ,
71+ profileIds ?: readonly string [ ] ,
72+ ) : boolean {
73+ const profiles = coerceRawStoreProfiles ( raw ) ;
74+ if ( ! profiles ) {
4675 return false ;
4776 }
4877 const expected = normalizeProvider ( provider ) ;
49- for ( const [ profileId , rawCredential ] of Object . entries ( profiles ) ) {
50- if ( normalizeProvider ( profileId ) . startsWith ( `${ expected } :` ) ) {
78+ const credentials =
79+ profileIds ?. map ( ( profileId ) => profiles [ profileId ] ) ?? Object . values ( profiles ) ;
80+ for ( const rawCredential of credentials ) {
81+ if ( isEligibleProviderCredential ( rawCredential , expected ) ) {
5182 return true ;
5283 }
53- if ( rawCredential && typeof rawCredential === "object" ) {
54- const rawProvider = ( rawCredential as { provider ?: unknown } ) . provider ;
55- if ( typeof rawProvider === "string" && normalizeProvider ( rawProvider ) === expected ) {
56- return true ;
57- }
58- }
5984 }
6085 return false ;
6186}
6287
6388function runtimeStoreHasProviderProfile (
6489 store : AuthProfileStore | undefined ,
6590 provider : string ,
91+ profileIds ?: readonly string [ ] ,
6692) : boolean {
67- return rawStoreHasProviderProfile ( store , provider ) ;
93+ return rawStoreHasProviderProfile ( store , provider , profileIds ) ;
6894}
6995
7096/** Returns true when any local/runtime/main auth profile source exists. */
@@ -104,37 +130,62 @@ export function hasLocalAuthProfileStoreSource(agentDir?: string): boolean {
104130 ) ;
105131}
106132
133+ type AuthProfileSourceForProviderOptions = {
134+ /** Optional hard order/profile constraint from config auth.order. */
135+ profileIds ?: readonly string [ ] ;
136+ } ;
137+
107138/** Returns true when a read-only auth-profile source contains a profile for a provider. */
108- export function hasAuthProfileStoreSourceForProvider ( provider : string , agentDir ?: string ) : boolean {
139+ export function hasAuthProfileStoreSourceForProvider (
140+ provider : string ,
141+ agentDir ?: string ,
142+ options ?: AuthProfileSourceForProviderOptions ,
143+ ) : boolean {
109144 if ( ! normalizeProvider ( provider ) ) {
110145 return false ;
111146 }
147+ const profileIds = options ?. profileIds ;
148+ if ( profileIds ?. length === 0 ) {
149+ return false ;
150+ }
112151 const localRuntimeStore = getRuntimeAuthProfileStoreSnapshot ( agentDir ) ;
113- if ( runtimeStoreHasProviderProfile ( localRuntimeStore , provider ) ) {
152+ if ( runtimeStoreHasProviderProfile ( localRuntimeStore , provider , profileIds ) ) {
114153 return true ;
115154 }
116- if ( rawStoreHasProviderProfile ( readJsonFile ( resolveAuthStorePath ( agentDir ) ) , provider ) ) {
155+ if (
156+ rawStoreHasProviderProfile ( readJsonFile ( resolveAuthStorePath ( agentDir ) ) , provider , profileIds )
157+ ) {
117158 return true ;
118159 }
119- if ( rawStoreHasProviderProfile ( readJsonFile ( resolveLegacyAuthStorePath ( agentDir ) ) , provider ) ) {
160+ if (
161+ rawStoreHasProviderProfile (
162+ readJsonFile ( resolveLegacyAuthStorePath ( agentDir ) ) ,
163+ provider ,
164+ profileIds ,
165+ )
166+ ) {
120167 return true ;
121168 }
122- if ( rawStoreHasProviderProfile ( readPersistedAuthProfileStoreRaw ( agentDir ) , provider ) ) {
169+ if (
170+ rawStoreHasProviderProfile ( readPersistedAuthProfileStoreRaw ( agentDir ) , provider , profileIds )
171+ ) {
123172 return true ;
124173 }
125174
126175 if ( ! agentDir ) {
127176 return false ;
128177 }
129178 const mainRuntimeStore = getRuntimeAuthProfileStoreSnapshot ( ) ;
130- if ( runtimeStoreHasProviderProfile ( mainRuntimeStore , provider ) ) {
179+ if ( runtimeStoreHasProviderProfile ( mainRuntimeStore , provider , profileIds ) ) {
131180 return true ;
132181 }
133- if ( rawStoreHasProviderProfile ( readJsonFile ( resolveAuthStorePath ( ) ) , provider ) ) {
182+ if ( rawStoreHasProviderProfile ( readJsonFile ( resolveAuthStorePath ( ) ) , provider , profileIds ) ) {
134183 return true ;
135184 }
136- if ( rawStoreHasProviderProfile ( readJsonFile ( resolveLegacyAuthStorePath ( ) ) , provider ) ) {
185+ if (
186+ rawStoreHasProviderProfile ( readJsonFile ( resolveLegacyAuthStorePath ( ) ) , provider , profileIds )
187+ ) {
137188 return true ;
138189 }
139- return rawStoreHasProviderProfile ( readPersistedAuthProfileStoreRaw ( ) , provider ) ;
190+ return rawStoreHasProviderProfile ( readPersistedAuthProfileStoreRaw ( ) , provider , profileIds ) ;
140191}
0 commit comments