When onSearchCommit is provided, the loading spinner should only appear
after Enter is pressed (actual search commit), not on every keystroke.
- Skip setIsLoading(true) in handleChange when onSearchCommit is present
- Cancel pending debounce timer when Enter fires (prevents stale
onSearchChange from firing 500ms after commit)
- Sync display state via onSearchChange on Enter to keep input and
committed state consistent
- Fix pre-existing React.ReactNode namespace usage in data-table.tsx
6 tests passing (1 new test for debounce cancellation on Enter).
Address 6 UX items from Pepe's product review:
- Lighthouse AI: change 'View This Finding' to 'Analyze This Finding
With Lighthouse AI'
- Remediation headings: shorten 'Terraform Command' to 'Terraform' and
'CloudFormation Command' to 'CloudFormation' for cleaner labels
- Search on Enter: split resourceSearch into input display state and
committed search state, fire actual search only on Enter key.
Remove resourceSearch from InlineResourceContainer key to prevent
full remount on every keystroke
- Muted icon: add 'Muted' text indicator with VolumeX icon in resource
row status cell for muted findings
- Risk section: wrap in danger-styled container with border-danger and
bg-bg-fail-secondary background for visual emphasis
- Section headings: upgrade Risk/Description labels from text-xs to
text-sm font-semibold. Add border separator after Description section
Also fix pre-existing React.ReactNode namespace usage in data-table.tsx
(replaced with named import type).
18 tests across 3 test suites (2 new, 1 extended). All passing.
Judgment Day: 1 round, 0 CRITICAL, warnings documented as follow-ups.
Known follow-ups:
- Spinner fires on keystroke in commit-on-Enter mode (cosmetic)
- Debounce timer not cancelled on Enter (edge case, no crash)
- Remediation card labels still text-xs (inconsistent with overview)
Address 3 product blockers from Pepe's review:
- Add sort=-status to getFindingGroupResources and
getLatestFindingGroupResources so FAIL resources appear before PASS
in the drill-down list (sort kept as future-proofing even when
filter[status]=FAIL makes it a no-op for now)
- Add filter[status]=FAIL to both resource endpoints so drill-down
only shows impacted resources, matching the count in the group header
- Add filter[status]=FAIL to createResourceFindingResolutionUrl so
muting a group only affects active FAIL findings, not all historical
- Use .set() after appendSanitizedProviderFilters to guarantee
hardcoded FAIL wins even if caller passes filter[status] in filters
(prevents duplicate filter[status] params with undefined API behavior)
- Apply symmetric .set() pattern in findings-by-resource.ts for
consistency
26 tests (10 new). All passing.
Judgment Day: 2 rounds, 0 discrepancies remaining.
- Replace `any` with `unknown` + type guards in finding-groups and
findings-by-resource adapters (4 adapter functions hardened)
- Add unmount cleanup for AbortController in use-resource-detail-drawer
to prevent memory leaks on mid-flight unmount
- Add try/catch/finally error handling for onBeforeOpen in floating mute
button to prevent permanent spinner state on network errors
- Replace hardcoded colors (border-gray-300, bg-white, text-slate-950)
with semantic tokens (border-default-200, bg-background, text-foreground)
for dark mode compatibility
- Change non-accessible `<p onClick>` to `<button>` with w-full and
type=button in column-finding-groups for keyboard accessibility
- Fix region flag mapping: asia-east1 (Taiwan) now correctly shows flag_tw
instead of flag_hk by adding specific rule before Hong Kong regex
- Fix import type usage in adapter files (value imports preserved for
runtime constants like FINDINGS_ROW_TYPE)
- Restore pageRef.current = 1 in refresh() for error path safety
43 new tests across 7 test files. 50 total tests passing.
TypeScript: 0 errors. ESLint: 0 errors.
Judgment Day: 2 rounds, 0 discrepancies remaining.
- Fix SSRF path traversal: encode checkId with encodeURIComponent in
getFindingGroupResources and getLatestFindingGroupResources URL paths
- Fix SSR crash: add isMounted guard for createPortal(document.body) in
InlineResourceContainer to prevent document access during server render
- Fix invalid Tailwind: replace mt-[-10] (no unit) with -mt-2.5 scale token
- Fix unbounded page[size]: cap at 500 via Math.min in URL builder as
defense-in-depth alongside existing chunking
- Fix pageRef race condition: move page counter increment inside fetchPage
after successful non-aborted response, remove redundant pre-set from
refresh() to prevent permanent page skip on concurrent abort
26 tests across 4 test suites (2 new, 2 extended). All passing.
TypeScript: 0 errors in changed files. ESLint: 0 errors.
Claude Code validation: PASSED.
Pre-existing healthcheck failures (.next/types, @codemirror) unrelated.