fix(FLEETMDM-002): CU-86akj32d7 37 review findings across 18 files - #163
flamingo[bot] wants to merge 18 commits into
Conversation
|
|
||
| vc, ok := viewer.FromContext(ctx) | ||
| if !ok { | ||
| return nil, errors.New("user must be authenticated to create team policies") |
There was a problem hiding this comment.
🦩 🔴 errors.New used instead of ctxerr.New in server-layer NewTeamPolicy
Replaced errors.New("user must be authenticated to create team policies") with ctxerr.New(ctx, "user must be authenticated to create team policies") in NewTeamPolicy. Also removed the now-unused errors import from the import block since errors.New was its only use in the file.
🤖 Prompt for AI agents
In server/service/team_policies.go around line 64, review and complete this code-review fix: errors.New used instead of ctxerr.New in server-layer NewTeamPolicy.
What the draft fix changed: Replaced `errors.New("user must be authenticated to create team policies")` with `ctxerr.New(ctx, "user must be authenticated to create team policies")` in `NewTeamPolicy`. Also removed the now-unused `errors` import from the import block since `errors.New` was its only use in the file.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer
| @@ -261,15 +260,17 @@ func (svc *Service) populateSoftwareIconURLs(ctx context.Context, policies []*fl | |||
| // to (see getPolicySoftwareTitleIconURL), so it's safe to point at it | |||
| // without risking a 404. | |||
| if hasCustomIcon || p.VPPAppsTeamsID != nil { | |||
There was a problem hiding this comment.
🦩 🔴 populateSoftwareIconURLs uses new(...) on a function call, likely a bug — should be a pointer to a string result
In populateSoftwareIconURLs, replaced the invalid t.IconURL = new(getPolicySoftwareTitleIconURL(teamID, t.SoftwareTitleID)) in the InstallSoftware branch with iconURL := getPolicySoftwareTitleIconURL(teamID, t.SoftwareTitleID); t.IconURL = &iconURL, matching the suggested fix and the *string type of IconURL.
🤖 Prompt for AI agents
In server/service/team_policies.go around line 263, review and complete this code-review fix: populateSoftwareIconURLs uses `new(...)` on a function call, likely a bug — should be a pointer to a string result.
What the draft fix changed: In `populateSoftwareIconURLs`, replaced the invalid `t.IconURL = new(getPolicySoftwareTitleIconURL(teamID, t.SoftwareTitleID))` in the InstallSoftware branch with `iconURL := getPolicySoftwareTitleIconURL(teamID, t.SoftwareTitleID); t.IconURL = &iconURL`, matching the suggested fix and the `*string` type of `IconURL`.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 90 high — react 👍/👎 to teach the reviewer
| if t := p.PatchSoftware; t != nil { | ||
| // Patch software is always a package installer (never a VPP app), so | ||
| // it only gets an icon URL when a custom icon was uploaded. | ||
| if _, ok := icons[t.SoftwareTitleID]; ok { |
There was a problem hiding this comment.
🦩 🔴 populateSoftwareIconURLs: same new(...) misuse for PatchSoftware icon assignment
Same fix applied to the PatchSoftware branch in populateSoftwareIconURLs: iconURL := getPolicySoftwareTitleIconURL(teamID, t.SoftwareTitleID); t.IconURL = &iconURL replacing the invalid new(...) call.
🤖 Prompt for AI agents
In server/service/team_policies.go around line 271, review and complete this code-review fix: populateSoftwareIconURLs: same new(...) misuse for PatchSoftware icon assignment.
What the draft fix changed: Same fix applied to the PatchSoftware branch in `populateSoftwareIconURLs`: `iconURL := getPolicySoftwareTitleIconURL(teamID, t.SoftwareTitleID); t.IconURL = &iconURL` replacing the invalid `new(...)` call.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 90 high — react 👍/👎 to teach the reviewer
| @@ -413,11 +414,11 @@ func (svc *Service) CountTeamPolicies(ctx context.Context, teamID uint, matchQue | |||
| if mergeInherited { | |||
There was a problem hiding this comment.
🦩 🟠 CountTeamPolicies missing wrap on ds.CountMergedTeamPolicies error
In CountTeamPolicies, wrapped the two bare error returns from svc.ds.CountMergedTeamPolicies and svc.ds.CountPolicies (inherited count) with ctxerr.Wrap(ctx, err, "count merged team policies") and ctxerr.Wrap(ctx, err, "count inherited policies") respectively, matching the file's existing error-wrapping convention.
🤖 Prompt for AI agents
In server/service/team_policies.go around line 413, review and complete this code-review fix: CountTeamPolicies missing wrap on ds.CountMergedTeamPolicies error.
What the draft fix changed: In `CountTeamPolicies`, wrapped the two bare error returns from `svc.ds.CountMergedTeamPolicies` and `svc.ds.CountPolicies` (inherited count) with `ctxerr.Wrap(ctx, err, "count merged team policies")` and `ctxerr.Wrap(ctx, err, "count inherited policies")` respectively, matching the file's existing error-wrapping convention.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟡 85 medium — react 👍/👎 to teach the reviewer
| @@ -326,7 +328,7 @@ func (svc *MDMAppleCommander) InstallEnterpriseApplicationWithEmbeddedManifest( | |||
|
|
|||
| raw, err := plist.Marshal(cmd) | |||
There was a problem hiding this comment.
🦩 🔴 fmt.Errorf used instead of ctxerr in server-layer package
In InstallEnterpriseApplicationWithEmbeddedManifest (line ~327), replaced return fmt.Errorf("marshal command payload plist: %w", err) with return ctxerr.Wrap(ctx, err, "marshal command payload plist"), matching the suggested fix exactly and the pattern used elsewhere in the file. ctxerr was already imported.
🤖 Prompt for AI agents
In server/mdm/apple/commander.go around line 327, review and complete this code-review fix: fmt.Errorf used instead of ctxerr in server-layer package.
What the draft fix changed: In InstallEnterpriseApplicationWithEmbeddedManifest (line ~327), replaced `return fmt.Errorf("marshal command payload plist: %w", err)` with `return ctxerr.Wrap(ctx, err, "marshal command payload plist")`, matching the suggested fix exactly and the pattern used elsewhere in the file. `ctxerr` was already imported.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer
| @@ -21,7 +21,7 @@ func updateSoftwareTitleDisplayName(ctx context.Context, tx sqlx.ExtContext, tea | |||
| ON DUPLICATE KEY UPDATE | |||
| display_name = VALUES(display_name)`, tmID, titleID, displayName) | |||
| if err != nil { | |||
There was a problem hiding this comment.
🦩 🟠 updateSoftwareTitleDisplayName returns raw MySQL error without ctxerr wrapping
In updateSoftwareTitleDisplayName, replaced return err with return ctxerr.Wrap(ctx, err, "upserting software title display name") for the error returned by tx.ExecContext, matching the wrapping pattern used in getDisplayNamesByTeamAndTitleIds and getSoftwareTitleDisplayName in the same file.
🤖 Prompt for AI agents
In server/datastore/mysql/software_title_display_names.go around line 23, review and complete this code-review fix: updateSoftwareTitleDisplayName returns raw MySQL error without ctxerr wrapping.
What the draft fix changed: In updateSoftwareTitleDisplayName, replaced `return err` with `return ctxerr.Wrap(ctx, err, "upserting software title display name")` for the error returned by tx.ExecContext, matching the wrapping pattern used in getDisplayNamesByTeamAndTitleIds and getSoftwareTitleDisplayName in the same file.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer
| @@ -56,7 +56,7 @@ func (ds *Datastore) GetChallengeByID(ctx context.Context, accountID, challengeI | |||
| // UpdateChallenge handles updating the challenge status, and the authorization status as well as moving the order status. | |||
| func (ds *Datastore) UpdateChallenge(ctx context.Context, challenge *types.Challenge) (*types.Challenge, error) { | |||
There was a problem hiding this comment.
🦩 🟠 errors.New used instead of ctxerr.New in server-layer challenge.go
Replaced errors.New("Challenge can not be nil for update") with ctxerr.New(ctx, "Challenge can not be nil for update") in UpdateChallenge in server/mdm/acme/internal/mysql/challenge.go. The errors package import is still required for errors.Is usage in GetChallengeByID, so it remains in the import block.
🤖 Prompt for AI agents
In server/mdm/acme/internal/mysql/challenge.go around line 57, review and complete this code-review fix: errors.New used instead of ctxerr.New in server-layer challenge.go.
What the draft fix changed: Replaced `errors.New("Challenge can not be nil for update")` with `ctxerr.New(ctx, "Challenge can not be nil for update")` in `UpdateChallenge` in server/mdm/acme/internal/mysql/challenge.go. The `errors` package import is still required for `errors.Is` usage in `GetChallengeByID`, so it remains in the import block.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer
| Status: &actionRequired, | ||
| }, nil | ||
| } | ||
| return fleet.HostMDMDiskEncryption{}, err | ||
| return fleet.HostMDMDiskEncryption{}, ctxerr.Wrap(ctx, err) | ||
| } | ||
|
|
||
| if key.ClientError != "" { |
There was a problem hiding this comment.
🦩 🟠 GetHostDiskEncryptionKey error path returns raw error without ctxerr wrapping
In LinuxHostDiskEncryptionStatus (server/service/linux_mdm.go), the non-not-found error path now wraps the error from svc.ds.GetHostDiskEncryptionKey with ctxerr.Wrap(ctx, err) before returning, matching the pattern used elsewhere in the same file (e.g., GetMDMLinuxProfilesSummary). ctxerr is already imported in this file, so no new imports are needed.
🤖 Prompt for AI agents
In server/service/linux_mdm.go around line 19, review and complete this code-review fix: GetHostDiskEncryptionKey error path returns raw error without ctxerr wrapping.
What the draft fix changed: In LinuxHostDiskEncryptionStatus (server/service/linux_mdm.go), the non-not-found error path now wraps the error from svc.ds.GetHostDiskEncryptionKey with ctxerr.Wrap(ctx, err) before returning, matching the pattern used elsewhere in the same file (e.g., GetMDMLinuxProfilesSummary). ctxerr is already imported in this file, so no new imports are needed.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer
| @@ -59,11 +66,11 @@ func (msrc MSRCClient) GetFeed(month time.Month, year int) (string, error) { | |||
| minD := time.Date(MSRCMinYear, time.January, 1, 0, 0, 0, 0, time.UTC) | |||
|
|
|||
| if d.Before(minD) { | |||
There was a problem hiding this comment.
🦩 🟠 fmt.Errorf used instead of ctxerr.New in server-layer GetFeed
In GetFeed (server/vulnerabilities/msrc/msrc_api.go), replaced the direct fmt.Errorf("min allowed date is %s", minD) string-only error with a wrapped sentinel error fmt.Errorf("%w: %s", ErrMinAllowedDate, minD) using a new package-level ErrMinAllowedDate var, and also replaced the adjacent errors.New("date can't be in the future") with a new sentinel ErrFutureDate for consistency. This does not fully satisfy the finding, since ctxerr.New/ctxerr.Wrap require a context.Context parameter that GetFeed (and the MSRCAPI interface it implements) does not have, and changing the signature would be a breaking API change across callers not shown here. This change only makes the errors identifiable/wrappable via errors.Is at the call site, where callers with access to a ctx can wrap them with ctxerr.Wrap before propagating — a partial mitigation. A complete fix would require threading context.Context through MSRCAPI.GetFeed and all its call sites/mocks, which is out of scope for a single-file, minimal change.
🤖 Prompt for AI agents
In server/vulnerabilities/msrc/msrc_api.go around line 61, review and complete this code-review fix: fmt.Errorf used instead of ctxerr.New in server-layer GetFeed.
What the draft fix changed: In `GetFeed` (server/vulnerabilities/msrc/msrc_api.go), replaced the direct `fmt.Errorf("min allowed date is %s", minD)` string-only error with a wrapped sentinel error `fmt.Errorf("%w: %s", ErrMinAllowedDate, minD)` using a new package-level `ErrMinAllowedDate` var, and also replaced the adjacent `errors.New("date can't be in the future")` with a new sentinel `ErrFutureDate` for consistency. This does not fully satisfy the finding, since `ctxerr.New`/`ctxerr.Wrap` require a `context.Context` parameter that `GetFeed` (and the `MSRCAPI` interface it implements) does not have, and changing the signature would be a breaking API change across callers not shown here. This change only makes the errors identifiable/wrappable via `errors.Is` at the call site, where callers with access to a `ctx` can wrap them with `ctxerr.Wrap` before propagating — a partial mitigation. A complete fix would require threading `context.Context` through `MSRCAPI.GetFeed` and all its call sites/mocks, which is out of scope for a single-file, minimal change.
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.
fix confidence: 🔴 35 low — review closely — react 👍/👎 to teach the reviewer
| @@ -49,7 +49,7 @@ func (ds *Datastore) FindPasswordResetByToken(ctx context.Context, token string) | |||
| passwordResetRequest := &fleet.PasswordResetRequest{} | |||
| err := sqlx.GetContext(ctx, ds.reader(ctx), passwordResetRequest, sqlStatement, token) | |||
There was a problem hiding this comment.
🦩 🟠 errors.Is/sql.ErrNoRows path wraps a not-found condition as a generic error rather than a typed not-found error
In FindPasswordResetByToken (server/datastore/mysql/password_reset.go), changed the sql.ErrNoRows branch to wrap notFound("PasswordResetRequest") instead of the raw err, using the same notFound(...) helper pattern seen in packs.go. This makes fleet.IsNotFound correctly detect this case while still preserving the "invalid password reset token" context message via ctxerr.Wrap.
🤖 Prompt for AI agents
In server/datastore/mysql/password_reset.go around line 50, review and complete this code-review fix: errors.Is/sql.ErrNoRows path wraps a not-found condition as a generic error rather than a typed not-found error.
What the draft fix changed: In FindPasswordResetByToken (server/datastore/mysql/password_reset.go), changed the sql.ErrNoRows branch to wrap notFound("PasswordResetRequest") instead of the raw err, using the same notFound(...) helper pattern seen in packs.go. This makes fleet.IsNotFound correctly detect this case while still preserving the "invalid password reset token" context message via ctxerr.Wrap.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟡 80 medium — react 👍/👎 to teach the reviewer
Closes 37 review findings across 18 files.
Draft — this is a starting point, not a finished change. The fix required judgment, so read it before trusting it.
server/service/team_policies.go:64new(...)on a function call, likely a bug — should be a pointer to a string resultserver/service/team_policies.go:263server/service/team_policies.go:271server/service/team_policies.go:413server/mdm/apple/commander.go:327server/mdm/apple/commander.go:327server/mdm/apple/commander.go:361server/mdm/apple/commander.go:158server/service/mdm_scep.go:94server/service/mdm_scep.go:80server/service/mdm_scep.go:86server/vulnerabilities/macoffice/analyzer.go:150server/vulnerabilities/macoffice/analyzer.go:35server/vulnerabilities/macoffice/analyzer.go:83server/datastore/mysql/scep.go:47server/datastore/mysql/scep.go:86server/datastore/mysql/scep.go:73server/vulnerabilities/msrc/analyzer.go:41server/vulnerabilities/msrc/analyzer.go:37server/mdm/acme/internal/service/endpoint_utils.go:34server/mdm/acme/internal/service/endpoint_utils.go:1server/logging/webhook.go:20server/logging/webhook.go:46server/platform/endpointer/clientip.go:40server/platform/endpointer/clientip.go:30server/mail/mail.go:101server/service/validation_setup.go:34server/datastore/mysql/nanomdm_storage.go:426server/datastore/mysql/nanomdm_storage.go:110server/datastore/mysql/nanomdm_storage.go:241server/vulnerabilities/oval/analyzer.go:156server/vulnerabilities/oval/analyzer.go:140server/datastore/mysql/software_title_display_names.go:23server/mdm/acme/internal/mysql/challenge.go:57server/service/linux_mdm.go:19server/vulnerabilities/msrc/msrc_api.go:61server/datastore/mysql/password_reset.go:50What changed — and what was deliberately left — is explained per finding as inline review comments on the lines each finding touched.
Run: https://product-hub.flamingo.so/admin/code-review
Run id:
1446a072-096e-4294-8082-c7cadffe76deMerging this PR is recorded as acceptance of the rule that produced it;
closing it unmerged is recorded as rejection. Both feed rule health, so
closing a wrong suggestion is useful rather than merely tidy.
ClickUp task: CU-86akj32d7 FleetMDM bulk review findings sweep (12 PRs)