@@ -43,6 +43,9 @@ import {
4343} from "./state.js" ;
4444import type { AuthProfileStore } from "./types.js" ;
4545
46+ // Auth profile store orchestration. This module merges persisted stores,
47+ // runtime snapshots, inherited main-agent OAuth profiles, and external CLI
48+ // overlays while keeping save paths local and secret-safe.
4649type LoadAuthProfileStoreOptions = {
4750 allowKeychainPrompt ?: boolean ;
4851 config ?: OpenClawConfig ;
@@ -108,6 +111,8 @@ function preserveLegacyOAuthRefsOnSave(params: {
108111 ) {
109112 continue ;
110113 }
114+ // Preserve legacy oauthRef ownership when current save data did not replace
115+ // inline OAuth material; otherwise older credential references would be lost.
111116 nextProfiles ??= { ...params . payload . profiles } ;
112117 nextProfiles [ profileId ] = {
113118 ...credential ,
@@ -159,6 +164,8 @@ function isInheritedMainOAuthCredential(params: {
159164 return false ;
160165 }
161166
167+ // Local agent stores can inherit main OAuth credentials. Do not persist the
168+ // inherited copy unless the local store actually owns or improves it.
162169 const mainCredential = loadPersistedAuthProfileStore ( ) ?. profiles [ params . profileId ] ;
163170 return (
164171 mainCredential ?. type === "oauth" &&
@@ -308,6 +315,8 @@ function maybeSyncPersistedExternalCliAuthProfiles(params: {
308315 }
309316
310317 try {
318+ // External CLI sync writes only profiles that still match the loaded
319+ // baseline, avoiding overwrite of concurrent local auth changes.
311320 return runAuthProfileWriteTransaction ( params . agentDir , ( database ) => {
312321 const latestStore = loadPersistedAuthProfileStore ( params . agentDir , {
313322 ...resolvePersistedLoadOptions ( params . options ) ,
@@ -373,6 +382,8 @@ function shouldKeepProfileInLocalStore(params: {
373382 return true ;
374383 }
375384 if ( params . store . runtimeExternalProfileIds ?. includes ( params . profileId ) ) {
385+ // Runtime external profiles are normally overlays. Persist only when they
386+ // have explicit local state or differ from the runtime snapshot.
376387 const persistedCredential = loadPersistedAuthProfileStore ( params . agentDir ) ?. profiles [
377388 params . profileId
378389 ] ;
@@ -702,6 +713,7 @@ function mergeRuntimeExternalProfileState(params: {
702713 return merged ;
703714}
704715
716+ /** Apply an auth store update inside the SQLite write lock. */
705717export async function updateAuthProfileStoreWithLock ( params : {
706718 agentDir ?: string ;
707719 saveOptions ?: SaveAuthProfileStoreOptions ;
@@ -725,6 +737,7 @@ export async function updateAuthProfileStoreWithLock(params: {
725737 }
726738}
727739
740+ /** Load the main auth profile store with runtime external profiles overlaid. */
728741export function loadAuthProfileStore ( ) : AuthProfileStore {
729742 const asStore = loadPersistedAuthProfileStore ( ) ;
730743 if ( asStore ) {
@@ -797,6 +810,7 @@ export function loadAuthProfileStoreForRuntime(
797810 ) ;
798811}
799812
813+ /** Load auth profiles for secret resolution without keychain prompts or writes. */
800814export function loadAuthProfileStoreForSecretsRuntime (
801815 agentDir ?: string ,
802816 options ?: Pick <
@@ -811,6 +825,7 @@ export function loadAuthProfileStoreForSecretsRuntime(
811825 } ) ;
812826}
813827
828+ /** Load auth profiles with runtime external profiles removed from the result. */
814829export function loadAuthProfileStoreWithoutExternalProfiles (
815830 agentDir ?: string ,
816831 loadOptions ?: Pick < LoadAuthProfileStoreOptions , "allowKeychainPrompt" > ,
@@ -832,6 +847,7 @@ export function loadAuthProfileStoreWithoutExternalProfiles(
832847 } ) ;
833848}
834849
850+ /** Ensure an auth store is available, including runtime/external profile overlays. */
835851export function ensureAuthProfileStore (
836852 agentDir ?: string ,
837853 options ?: {
@@ -862,6 +878,7 @@ export function ensureAuthProfileStore(
862878 } ) ;
863879}
864880
881+ /** Ensure an auth store is available without external profile overlays. */
865882export function ensureAuthProfileStoreWithoutExternalProfiles (
866883 agentDir ?: string ,
867884 options ?: {
@@ -894,6 +911,7 @@ export function ensureAuthProfileStoreWithoutExternalProfiles(
894911 } ) ;
895912}
896913
914+ /** Find a persisted credential in the scoped store, falling back to the main store. */
897915export function findPersistedAuthProfileCredential ( params : {
898916 agentDir ?: string ;
899917 profileId : string ;
@@ -913,6 +931,7 @@ export function findPersistedAuthProfileCredential(params: {
913931 return loadPersistedAuthProfileStore ( ) ?. profiles [ params . profileId ] ;
914932}
915933
934+ /** Resolve which agent dir owns a persisted profile, accounting for inherited OAuth. */
916935export function resolvePersistedAuthProfileOwnerAgentDir ( params : {
917936 agentDir ?: string ;
918937 profileId : string ;
@@ -941,6 +960,7 @@ export function resolvePersistedAuthProfileOwnerAgentDir(params: {
941960 return mainStore ?. profiles [ params . profileId ] ? undefined : params . agentDir ;
942961}
943962
963+ /** Load the store shape used when applying local-only auth updates. */
944964export function ensureAuthProfileStoreForLocalUpdate ( agentDir ?: string ) : AuthProfileStore {
945965 const options : LoadAuthProfileStoreOptions = { syncExternalCli : false } ;
946966 const store = loadAuthProfileStoreForAgent ( agentDir , options ) ;
@@ -961,22 +981,26 @@ export function ensureAuthProfileStoreForLocalUpdate(agentDir?: string): AuthPro
961981
962982export { hasAnyAuthProfileStoreSource , hasLocalAuthProfileStoreSource } from "./source-check.js" ;
963983
984+ /** Return the current runtime auth-profile snapshot for an agent dir. */
964985export function getRuntimeAuthProfileStoreSnapshot (
965986 agentDir ?: string ,
966987) : AuthProfileStore | undefined {
967988 return getRuntimeAuthProfileStoreSnapshotImpl ( agentDir ) ;
968989}
969990
991+ /** Replace runtime auth-profile snapshots, used by tests and prepared runtimes. */
970992export function replaceRuntimeAuthProfileStoreSnapshots (
971993 entries : Array < { agentDir ?: string ; store : AuthProfileStore } > ,
972994) : void {
973995 replaceRuntimeAuthProfileStoreSnapshotsImpl ( entries ) ;
974996}
975997
998+ /** Clear all runtime auth-profile snapshots. */
976999export function clearRuntimeAuthProfileStoreSnapshots ( ) : void {
9771000 clearRuntimeAuthProfileStoreSnapshotsImpl ( ) ;
9781001}
9791002
1003+ /** Save the auth profile store plus sidecar state, preserving runtime overlay metadata. */
9801004export function saveAuthProfileStore (
9811005 store : AuthProfileStore ,
9821006 agentDir ?: string ,
0 commit comments