fix: populate feature flags before auth notification [IDE-1901]#1194
fix: populate feature flags before auth notification [IDE-1901]#1194nick-y-snyk wants to merge 3 commits intorefactor/IDE-1786_folder-config-refactoringfrom
Conversation
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
| // canceled (e.g. when the IDE cancels the snyk.login request after auth completes). | ||
| cmd.ldxSyncService.RefreshConfigFromLdxSync(context.Background(), conf, cmd.engine, logger, config.GetWorkspace(conf).Folders(), cmd.notifier) | ||
| go sendFolderConfigs(conf, cmd.engine, logger, cmd.notifier, cmd.featureFlagService, cmd.configResolver) | ||
| sendFolderConfigs(conf, cmd.engine, logger, cmd.notifier, cmd.featureFlagService, cmd.configResolver) |
There was a problem hiding this comment.
Ideally, if a user has large workspaces with 100+ projects, we want a separation between the login flow and the setup folders. With clear indications for the user that they are logged in, but snyk is not ready to scan until all configs are ready.
There was a problem hiding this comment.
This can still run in a go routine, since it will get to this point after the postAuth hook
| // Expired or revoked refresh tokens cause the OAuth2 token endpoint to reject | ||
| // the request. http.Client wraps this in url.Error, so detect it before the | ||
| // generic transport-error guard. | ||
| errMsg := err.Error() |
There was a problem hiding this comment.
Could we user a re.Response.StatusCode == 401 or 400 to catch expired/invalid API credentials?
https://github.com/snyk/sweater-comb/blob/main/docs/standards/rest.md#401---unauthorized
Needs to be verified for both token an oauth.
| if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) { | ||
| return false | ||
| } | ||
| // Expired or revoked refresh tokens cause the OAuth2 token endpoint to reject |
There was a problem hiding this comment.
Should the change here be submitted as a separate PR for for changelog clarity?
domain/ide/command/folder_handler.go
Outdated
| } | ||
| log := logger.With().Str("method", "populateAllFolderConfigs").Logger() | ||
| for _, folder := range ws.Folders() { | ||
| fc, err := folderconfig.GetOrCreateFolderConfig(conf, folder.Path(), &log) |
domain/ide/command/folder_handler.go
Outdated
| if fc == nil { | ||
| continue | ||
| } | ||
| featureFlagService.PopulateFolderConfig(fc.Clone()) |
domain/ide/command/folder_handler.go
Outdated
| return | ||
| } | ||
| log := logger.With().Str("method", "populateAllFolderConfigs").Logger() | ||
| for _, folder := range ws.Folders() { |
| // the request. http.Client wraps this in url.Error, so detect it before the | ||
| // generic transport-error guard. | ||
| errMsg := err.Error() | ||
| if strings.Contains(errMsg, "oauth2/token") && strings.Contains(errMsg, "authentication failed") { |
There was a problem hiding this comment.
nitpick: make the comparison case insensitive
This comment has been minimized.
This comment has been minimized.
Race condition: after login, IDE receives $/snyk.hasAuthenticated and triggers scan before SAST settings are cached → "Snyk Code not enabled". Fix: postCredentialUpdateHook runs populateAllFolderConfigs between credential storage and auth notification, ensuring feature flags and SAST settings are available before the IDE reacts. Review feedback addressed: - Use unenriched folder config (no git enrichment for feature flag fetch) - Loop only on trusted folders - Remove unnecessary Clone() - Set ConfigResolver on folder config so SetFeatureFlag persists to GAF - Make sendFolderConfigs synchronous in login command - Case-insensitive error string matching in shouldCauseLogout - Extract isTransientNetworkError to reduce cyclomatic complexity Includes regression test verifying feature flags populate before auth notification is sent (fails when hook is removed).
166ec3f to
ce97199
Compare
This comment has been minimized.
This comment has been minimized.
- Synchronize SetPostCredentialUpdateHook with a.m mutex to prevent data race - Skip hook when token is empty (logout path) to avoid wasteful API calls - Wrap hook invocation in recover() to prevent LSP server crash on panic
This comment has been minimized.
This comment has been minimized.
| func() { | ||
| defer func() { | ||
| if r := recover(); r != nil { | ||
| a.engine.GetLogger().Error().Interface("panic", r).Msg("postCredentialUpdateHook panicked") |
There was a problem hiding this comment.
why are you expecting it to panic?
There was a problem hiding this comment.
I didn't. just a double safety (ai suggestion to prevent ls crash). Do you want this removed?
There was a problem hiding this comment.
I also added an actual test which fails without other changes. But haven't tested manually yet
There was a problem hiding this comment.
we have a global recovery that should catch it if it happens, I think this is not necessary here.
…DE-1901-sast-not-enabled-after-login
PR Reviewer Guide 🔍
|
Summary
postCredentialUpdateHookrunspopulateAllFolderConfigsbetween credential storage and auth notification, ensuring feature flags and SAST settings are available before the IDE reactssendFolderConfigsmade synchronous in login commandReview feedback addressed
Clone()—PopulateFolderConfigonly reads org from configConfigResolveron folder config soSetFeatureFlagpersists to GAF (was silently no-op without it)shouldCauseLogoutisTransientNetworkErrorhelper to reduce cyclomatic complexityTest plan
TestLoginCommand_Execute_FeatureFlagsPopulatedBeforeAuthNotification— regression test verifying feature flags populate BEFORE$/snyk.hasAuthenticatednotification (fails when hook is removed)Test_PostCredentialUpdateHook_CalledBeforeNotification— hook runs between token storage and notificationTest_shouldCauseLogout— all 13 cases pass including expired refresh token and transient network errorsTestIsAuthenticated_ConcurrentCallsSendOnlyOneNotification— concurrent dedup still worksTestLoginCommand_*tests pass