diff --git a/internal/watcher/watcher.go b/internal/watcher/watcher.go index a0fa4128..458b8cf5 100644 --- a/internal/watcher/watcher.go +++ b/internal/watcher/watcher.go @@ -526,8 +526,14 @@ func (w *Watcher) SnapshotCoreAuths() []*coreauth.Auth { if email, _ := metadata["email"].(string); email != "" { label = email } + // Use relative path under authDir as ID to stay consistent with FileStore + id := full + if rel, errRel := filepath.Rel(w.authDir, full); errRel == nil && rel != "" { + id = rel + } + a := &coreauth.Auth{ - ID: full, + ID: id, Provider: provider, Label: label, Status: coreauth.StatusActive, diff --git a/sdk/cliproxy/auth/filestore.go b/sdk/cliproxy/auth/filestore.go index ac303aec..6fbcbd54 100644 --- a/sdk/cliproxy/auth/filestore.go +++ b/sdk/cliproxy/auth/filestore.go @@ -64,6 +64,15 @@ func (s *FileStore) Save(ctx context.Context, auth *Auth) error { if path == "" { return fmt.Errorf("auth filestore: missing file path attribute for %s", auth.ID) } + // If the auth has been disabled and the original file was removed, avoid + // recreating it on disk. This lets operators delete auth files explicitly. + if auth.Disabled { + if _, err := os.Stat(path); err != nil { + if os.IsNotExist(err) { + return nil + } + } + } s.mu.Lock() defer s.mu.Unlock() if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {