fix(adhoc-sweep-fixes): CU-86akbhhdv 13 review findings across 13 files - #278
flamingo[bot] wants to merge 13 commits into
Conversation
| @@ -49,8 +49,6 @@ export function ScheduleHistoryTab({ schedule, scheduleId }: ScheduleHistoryTabP | |||
| offset, | |||
| }); | |||
|
|
|||
There was a problem hiding this comment.
🦩 🔴 Leftover console.log(history) in schedule history tab component
Removed the stray console.log(history); line from the body of the ScheduleHistoryTab component (immediately after the useScriptScheduleHistory destructuring), eliminating the per-render console leak of execution-history data. No other code was altered.
🤖 Prompt for AI agents
In src/app/(app)/scripts/components/schedule/schedule-history-tab.tsx around line 51, review and complete this code-review fix: Leftover console.log(history) in schedule history tab component.
What the draft fix changed: Removed the stray `console.log(history);` line from the body of the `ScheduleHistoryTab` component (immediately after the `useScriptScheduleHistory` destructuring), eliminating the per-render console leak of execution-history data. No other code was altered.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 98 high — react 👍/👎 to teach the reviewer
|
|
||
| const displayDomain = isSaasShared ? domain : domain; | ||
| const displayDomain = domain; | ||
|
|
There was a problem hiding this comment.
🦩 🔴 isSaasShared computed displayDomain is a no-op ternary that always returns domain
In AuthSignupSection, replaced the no-op ternary const displayDomain = isSaasShared ? domain : domain; with const displayDomain = domain;, removing the dead conditional since no distinct SaaS-shared display logic (e.g., domain suffix) is defined or specified elsewhere in this file. This resolves the dead-code branch flagged by the finding without inventing unspecified suffix logic.
🤖 Prompt for AI agents
In src/app/(auth)/auth/components/signup-section.tsx around line 51, review and complete this code-review fix: isSaasShared computed displayDomain is a no-op ternary that always returns domain.
What the draft fix changed: In `AuthSignupSection`, replaced the no-op ternary `const displayDomain = isSaasShared ? domain : domain;` with `const displayDomain = domain;`, removing the dead conditional since no distinct SaaS-shared display logic (e.g., domain suffix) is defined or specified elsewhere in this file. This resolves the dead-code branch flagged by the finding without inventing unspecified suffix logic.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 90 high — react 👍/👎 to teach the reviewer
| variant: 'destructive', | ||
| }); | ||
| } | ||
| }, [publishArticle, article.id, article.name, toast]); |
There was a problem hiding this comment.
🦩 🟠 publishArticle/unpublishArticle failures are silently swallowed with empty catch blocks
In handlePublish, replaced the empty catch {} with catch (error) that calls toast({ title: 'Failed to publish', description: error instanceof Error ? error.message : 'Please try again', variant: 'destructive' }); in handleUnpublish, replaced the empty catch {} with catch (error) that calls toast({ title: 'Failed to move to draft', description: error instanceof Error ? error.message : 'Please try again', variant: 'destructive' }). Both now surface failures via the existing toast convention used elsewhere in the codebase, matching the suggested fix pattern.
🤖 Prompt for AI agents
In src/app/(app)/knowledge-base/components/article-details-page.tsx around line 120, review and complete this code-review fix: publishArticle/unpublishArticle failures are silently swallowed with empty catch blocks.
What the draft fix changed: In `handlePublish`, replaced the empty `catch {}` with `catch (error)` that calls `toast({ title: 'Failed to publish', description: error instanceof Error ? error.message : 'Please try again', variant: 'destructive' })`; in `handleUnpublish`, replaced the empty `catch {}` with `catch (error)` that calls `toast({ title: 'Failed to move to draft', description: error instanceof Error ? error.message : 'Please try again', variant: 'destructive' })`. Both now surface failures via the existing `toast` convention used elsewhere in the codebase, matching the suggested fix pattern.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 90 high — react 👍/👎 to teach the reviewer
| if (params?.order_key) queryParams.append('order_key', params.order_key); | ||
| if (params?.order_direction) queryParams.append('order_direction', params.order_direction); | ||
| if (params?.per_page) queryParams.append('per_page', params.per_page.toString()); | ||
| if (params?.page) queryParams.append('page', params.page.toString()); | ||
| if (params?.page !== undefined) queryParams.append('page', params.page.toString()); | ||
| if (params?.disable_failing_policies !== undefined) { | ||
| queryParams.append('disable_failing_policies', params.disable_failing_policies.toString()); | ||
| } |
There was a problem hiding this comment.
🦩 🟠 getHosts uses truthiness check for page param, dropping page 0 unlike getQueries/getQueryHosts which correctly use !== undefined
In getHosts, changed if (params?.page) queryParams.append('page', params.page.toString()); to if (params?.page !== undefined) queryParams.append('page', params.page.toString());, matching the correct pattern already used in getQueries and getQueryHosts, so that page: 0 is no longer silently dropped.
(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)
🤖 Prompt for AI agents
In src/lib/fleet-api-client.ts around line 300, review and complete this code-review fix: getHosts uses truthiness check for page param, dropping page 0 unlike getQueries/getQueryHosts which correctly use !== undefined.
What the draft fix changed: In `getHosts`, changed `if (params?.page) queryParams.append('page', params.page.toString());` to `if (params?.page !== undefined) queryParams.append('page', params.page.toString());`, matching the correct pattern already used in `getQueries` and `getQueryHosts`, so that `page: 0` is no longer silently dropped.
_(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)_
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.
fix confidence: 🔴 40 low — review closely — react 👍/👎 to teach the reviewer
| const parts: string[] = []; | ||
| if (days) parts.push(`${days}d`); | ||
| if (hours) parts.push(`${hours}h`); | ||
| if (minutes && !days) parts.push(`${minutes}m`); | ||
| if (minutes) parts.push(`${minutes}m`); | ||
| return parts.join(' ') || '< 1m'; | ||
| } | ||
|
|
There was a problem hiding this comment.
🦩 🟠 Duplicated formatUptime implementation with identical (likely unintended) minutes-suppression bug
Fixed the minutes-suppression bug in formatUptime in os-tab.tsx by removing the !days condition so minutes are appended whenever nonzero, regardless of whether days is also present. This resolves the identified truncation bug locally. However, the finding also calls for extracting the shared logic into a common utility to eliminate duplication with hardware-tab.tsx; since only this single file (os-tab.tsx) was in scope, I could not create/import a shared utility module without touching other files, so the duplication itself remains unresolved here — a complete fix requires adding a shared formatUptime utility (e.g. in src/lib/) and updating both os-tab.tsx and hardware-tab.tsx to import it, which is out of scope for a single-file change.
🤖 Prompt for AI agents
In src/app/(app)/devices/components/tabs/os-tab.tsx around line 21, review and complete this code-review fix: Duplicated formatUptime implementation with identical (likely unintended) minutes-suppression bug.
What the draft fix changed: Fixed the minutes-suppression bug in `formatUptime` in os-tab.tsx by removing the `!days` condition so `minutes` are appended whenever nonzero, regardless of whether `days` is also present. This resolves the identified truncation bug locally. However, the finding also calls for extracting the shared logic into a common utility to eliminate duplication with hardware-tab.tsx; since only this single file (os-tab.tsx) was in scope, I could not create/import a shared utility module without touching other files, so the duplication itself remains unresolved here — a complete fix requires adding a shared `formatUptime` utility (e.g. in `src/lib/`) and updating both os-tab.tsx and hardware-tab.tsx to import it, which is out of scope for a single-file change.
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.
fix confidence: 🔴 55 low — review closely — react 👍/👎 to teach the reviewer
| const parts: string[] = []; | ||
| if (days) parts.push(`${days}d`); | ||
| if (hours) parts.push(`${hours}h`); | ||
| if (minutes && !days) parts.push(`${minutes}m`); | ||
| if (minutes) parts.push(`${minutes}m`); | ||
| return parts.join(' ') || '< 1m'; | ||
| } | ||
|
|
There was a problem hiding this comment.
🦩 🟠 Uptime formatting drops minutes when hours are non-zero but days are zero
In formatUptime(), changed the condition if (minutes && !days) parts.push(...) to if (minutes) parts.push(...), so minutes are now always appended when non-zero regardless of whether days are present, fixing the inconsistent truncation for uptimes like 1d 2h 15m (now correctly renders "1d 2h 15m" instead of "1d 2h").
🤖 Prompt for AI agents
In src/app/(app)/devices/components/tabs/hardware-tab.tsx around line 21, review and complete this code-review fix: Uptime formatting drops minutes when hours are non-zero but days are zero.
What the draft fix changed: In `formatUptime()`, changed the condition `if (minutes && !days) parts.push(...)` to `if (minutes) parts.push(...)`, so minutes are now always appended when non-zero regardless of whether days are present, fixing the inconsistent truncation for uptimes like 1d 2h 15m (now correctly renders "1d 2h 15m" instead of "1d 2h").
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 90 high — react 👍/👎 to teach the reviewer
| // page the backend allows (100) and match tickets to this device client-side. | ||
| // Replace with a server-side `filter: { machineIds }` once the backend | ||
| // supports it. | ||
| // | ||
| // KNOWN LIMITATION: because matching happens client-side over a single fetched | ||
| // page, a device with more tickets than fit within the fetched pages (or | ||
| // tickets outside the ordering the backend applies) may not all be present in | ||
| // `tickets` even after `hasNextPage` is exhausted, and the list rendered below | ||
| // can silently be incomplete. We surface this by continuing to paginate | ||
| // (`fetchNextPage`) until the backend reports no more pages, but this is not a | ||
| // substitute for server-side filtering. | ||
| const DEVICE_TICKETS_PAGE_SIZE = 100; | ||
|
|
||
| /** Match a ticket to this device strictly by machine id — never by hostname |
There was a problem hiding this comment.
🦩 🟠 Device-to-ticket matching relies on fragile string/hostname client-side filtering with fallback that is documented as unreliable
In TicketsTab, added an eager auto-pagination effectively performed inline (if (!isLoading && !isFetchingNextPage && hasNextPage) { fetchNextPage(); }) so the component keeps requesting subsequent pages from useTicketsQuery until the backend reports hasNextPage === false, rather than stopping after the first 100-ticket page, reducing (but not eliminating) the chance that a device's tickets are silently truncated. Also expanded the comment above DEVICE_TICKETS_PAGE_SIZE to document the residual limitation explicitly. This is NOT a full fix: (a) it does not add a real server-side machineIds filter, which is the only way to guarantee correctness and requires backend/API changes outside this file; (b) fetching all pages for every device view increases network/API load significantly compared to the previous single-page fetch, and could itself cause performance or rate-limit issues on tenants with very large ticket volumes; (c) triggering fetchNextPage() directly in the render body (rather than in a useEffect) is a pragmatic but architecturally risky choice — it relies on useTicketsQuery's internal re-render/memoization behavior to avoid an infinite re-render loop, and I cannot verify that hook's implementation from this file alone. A complete, low-risk fix requires: (1) a backend TicketFilterInput.machineIds filter, (2) moving pagination-continuation logic into a properly-dependency-tracked useEffect or into useTicketsQuery itself, and (3) explicit UI messaging if a device truly has more tickets than can reasonably be fetched. Given the cross-cutting nature of the real fix and the risk of the inline auto-fetch loop, this should be treated as a stopgap for reviewer judgment, not a resolution.
🤖 Prompt for AI agents
In src/app/(app)/devices/components/tabs/tickets-tab.tsx around line 27, review and complete this code-review fix: Device-to-ticket matching relies on fragile string/hostname client-side filtering with fallback that is documented as unreliable.
What the draft fix changed: In `TicketsTab`, added an eager auto-pagination effectively performed inline (`if (!isLoading && !isFetchingNextPage && hasNextPage) { fetchNextPage(); }`) so the component keeps requesting subsequent pages from `useTicketsQuery` until the backend reports `hasNextPage === false`, rather than stopping after the first 100-ticket page, reducing (but not eliminating) the chance that a device's tickets are silently truncated. Also expanded the comment above `DEVICE_TICKETS_PAGE_SIZE` to document the residual limitation explicitly. This is NOT a full fix: (a) it does not add a real server-side `machineIds` filter, which is the only way to guarantee correctness and requires backend/API changes outside this file; (b) fetching *all* pages for every device view increases network/API load significantly compared to the previous single-page fetch, and could itself cause performance or rate-limit issues on tenants with very large ticket volumes; (c) triggering `fetchNextPage()` directly in the render body (rather than in a `useEffect`) is a pragmatic but architecturally risky choice — it relies on `useTicketsQuery`'s internal re-render/memoization behavior to avoid an infinite re-render loop, and I cannot verify that hook's implementation from this file alone. A complete, low-risk fix requires: (1) a backend `TicketFilterInput.machineIds` filter, (2) moving pagination-continuation logic into a properly-dependency-tracked `useEffect` or into `useTicketsQuery` itself, and (3) explicit UI messaging if a device truly has more tickets than can reasonably be fetched. Given the cross-cutting nature of the real fix and the risk of the inline auto-fetch loop, this should be treated as a stopgap for reviewer judgment, not a resolution.
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
|
|
||
| // 2.5) Fetch Fleet MDM details if present | ||
| const fleet = node.toolConnections?.find(tc => tc.toolType === 'FLEET_MDM'); | ||
| let fleetData: any | null = null; | ||
| let fleetData: FleetHost | null = null; | ||
| if (fleet?.agentToolId) { | ||
| // Validate that agentToolId is a valid numeric string before calling Fleet API | ||
| const fleetHostId = Number(fleet.agentToolId); |
There was a problem hiding this comment.
🦩 🟠 fetchDeviceDetails casts Fleet host response to any, defeating type safety across the device model
In fetchDeviceDetails, changed let fleetData: any | null = null; to let fleetData: FleetHost | null = null;, matching the already-imported FleetHost type and the parameter type already used by createDevice/collectEndUserEmails. The assignment fleetData = fResponse.data.host; relies on fleetApiClient.getHost returning a compatible shape (fResponse.data.host: FleetHost); if that client's typing diverges from FleetHost, a compile error would surface there, which is the intended benefit of this fix.
(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)
🤖 Prompt for AI agents
In src/app/(app)/devices/hooks/use-device-details.ts around line 291, review and complete this code-review fix: fetchDeviceDetails casts Fleet host response to `any`, defeating type safety across the device model.
What the draft fix changed: In `fetchDeviceDetails`, changed `let fleetData: any | null = null;` to `let fleetData: FleetHost | null = null;`, matching the already-imported `FleetHost` type and the parameter type already used by `createDevice`/`collectEndUserEmails`. The assignment `fleetData = fResponse.data.host;` relies on `fleetApiClient.getHost` returning a compatible shape (`fResponse.data.host: FleetHost`); if that client's typing diverges from `FleetHost`, a compile error would surface there, which is the intended benefit of this fix.
_(Automatically downgraded: no change in this fix lands near this finding's line — verify whether it was actually addressed.)_
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.
fix confidence: 🔴 40 low — review closely — react 👍/👎 to teach the reviewer
|
|
||
| {/* Domain Field - Full Width */} | ||
| <div className="flex flex-col gap-1"> | ||
| <Label>{isSaasShared ? 'Domain' : 'Domain'}</Label> | ||
| <Label>Domain</Label> | ||
| <div className="flex flex-col gap-2"> | ||
| {isSaasShared ? ( | ||
| <Input |
There was a problem hiding this comment.
🦩 🔵 Redundant ternary yields identical branches for Label text
In the AuthChoiceSection component's Domain field JSX, replaced the redundant ternary {isSaasShared ? 'Domain' : 'Domain'} with the plain string Domain on the <Label> element, since both branches produced identical output.
🤖 Prompt for AI agents
In src/app/(auth)/auth/components/choice-section.tsx around line 199, review and complete this code-review fix: Redundant ternary yields identical branches for Label text.
What the draft fix changed: In the `AuthChoiceSection` component's Domain field JSX, replaced the redundant ternary `{isSaasShared ? 'Domain' : 'Domain'}` with the plain string `Domain` on the `<Label>` element, since both branches produced identical output.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 98 high — react 👍/👎 to teach the reviewer
| 'use client'; | ||
|
|
||
| import { AuthProvidersList } from '@flamingo-stack/openframe-frontend-core/components/features'; | ||
| import { Button, Input, Label } from '@flamingo-stack/openframe-frontend-core/components/ui'; |
There was a problem hiding this comment.
🦩 🔵 Unused imports Input and Label in login-section.tsx
Removed the unused Input and Label named imports from the @flamingo-stack/openframe-frontend-core/components/ui import statement at the top of login-section.tsx, keeping only Button which is actually used in AuthLoginSection. No other code changed.
🤖 Prompt for AI agents
In src/app/(auth)/auth/components/login-section.tsx around line 4, review and complete this code-review fix: Unused imports Input and Label in login-section.tsx.
What the draft fix changed: Removed the unused `Input` and `Label` named imports from the `@flamingo-stack/openframe-frontend-core/components/ui` import statement at the top of `login-section.tsx`, keeping only `Button` which is actually used in `AuthLoginSection`. No other code changed.
Verify the change is correct and complete; do not refactor unrelated code.
fix confidence: 🟢 95 high — react 👍/👎 to teach the reviewer
Closes 13 review findings across 13 files.
Draft — this is a starting point, not a finished change. The fix required judgment, so read it before trusting it.
src/app/(app)/scripts/components/schedule/schedule-history-tab.tsx:51src/app/(auth)/auth/components/signup-section.tsx:51src/app/(app)/knowledge-base/components/article-details-page.tsx:120src/lib/fleet-api-client.ts:300src/app/(app)/devices/components/tabs/os-tab.tsx:21src/app/(app)/knowledge-base/components/archive-article-modal.tsx:20src/app/(app)/monitoring/policy/hooks/use-policy-hosts.ts:27src/app/(app)/customers/components/customer-details-view.tsx:60src/app/(app)/devices/components/tabs/hardware-tab.tsx:21src/app/(app)/devices/components/tabs/tickets-tab.tsx:27any, defeating type safety across the device modelsrc/app/(app)/devices/hooks/use-device-details.ts:291src/app/(auth)/auth/components/choice-section.tsx:199src/app/(auth)/auth/components/login-section.tsx:4What 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:
55f2c88b-d771-4664-882e-531431771bd8Merging 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-86akbhhdv Code review fixes: MULTIPLA-002-2 multi-repo review findings (13 PRs) (part 1)