Summary
The /fix page in the frontend (frontend/src/app/pages/fix.tsx) is completely disconnected from the backend. It renders hardcoded sample diffs and mock fix data. Users who select findings on the Findings page and click "Propose Fixes" are navigated to a page that shows predetermined fake data, not real remediation proposals. Furthermore, the selected finding IDs are not persisted or passed through navigation state, so even if the backend /fix endpoint were called, the frontend has lost the user's selection context.
Affected Files
frontend/src/app/pages/fix.tsx — Entire file (lines 1–196). 100% hardcoded sample data, no API calls.
frontend/src/app/pages/findings.tsx — "Propose Fixes" button navigation (line 450–451): <Link to="/fix"> with no state, query params, or context.
frontend/src/app/lib/api.ts — fix() function (lines 130–138) exists but is never called from any component.
frontend/src/app/routes.ts — Fix route definition (line 17).
backend/app/remediation/engine.py — The backend propose_fixes() function exists and works, but is unused by the frontend.
Root Cause
Issue A — No navigation state for selected findings
In findings.tsx line 450:
<Link to="/fix">
<Button size="sm">Propose Fixes</Button>
</Link>
This is a plain <Link> with no state, no search params (e.g., ?findingIds=...), and no callback. The selectedFindings state (a Set<string>) exists in the Findings component but is never passed anywhere. When the user navigates to /fix, the Fix component has no idea which findings were selected.
Even if we fixed the Fix page to call the backend, it would call POST /fix with either no finding_ids or a hardcoded list, because the selection context is lost.
Issue B — Fix page is fully hardcoded
The Fix component (fix.tsx:31–52) defines its own inline array of fix objects:
const fixes = [
{
id: 0,
title: "Fix SQL Injection in user query",
severity: "critical",
...
diff: sampleDiffs, // hardcoded inline diff data
},
...
];
It never:
- Reads
scan-store.ts for the current job_id
- Calls
api.fix(jobId, findingIds)
- Parses URL params for
findingIds
- Displays real
Fix objects from the backend response
- Shows actual diffs — all
DiffViewer data is fabricated
Issue C — Backend /fix endpoint is orphaned
The backend endpoint at POST /fix (main.py:609–619) works correctly, receiving FixRequest(job_id, finding_ids) and returning FixResponse(job_id, fixes). But no frontend code calls api.fix() on any page. The api.ts export of fix() is defined but has zero callers.
Expected Behavior
- When the user selects findings and clicks "Propose Fixes", the selected finding IDs must be passed to the
/fix page.
- The
/fix page should:
- Read current
job_id from scan-store.ts
- Read selected finding IDs from navigation state or URL params
- Call
POST /fix with { job_id, finding_ids }
- Display the returned
Fix objects with real diffs, status, summaries, and notes
- The "Apply Patch" and "Verify" navigation should pass the applied fix IDs forward.
- If no findings are selected, the page should show a meaningful empty state.
Suggested Approach
- Change the "Propose Fixes" link in
findings.tsx to pass selected IDs via React Router state or search params:
<Link to="/fix" state={{ findingIds: [...selectedFindings] }}>
- Rewrite
fix.tsx to:
- Read
state from useLocation()
- If no state, read
scan-store for job_id (but show error if no findings selected)
- Call
api.fix(jobId, findingIds) on mount
- Render the real backend response
- Add loading, error, and empty states.
- Ensure the backend
FixResponse.diff field is populated (currently always None for semgrep: and osv: finding types — engine.py:21,36 set diff=None). The engine needs to be enhanced to actually generate diffs.
- After applying a fix, navigate to
/verify with the applied fix metadata.
Summary
The
/fixpage in the frontend (frontend/src/app/pages/fix.tsx) is completely disconnected from the backend. It renders hardcoded sample diffs and mock fix data. Users who select findings on the Findings page and click "Propose Fixes" are navigated to a page that shows predetermined fake data, not real remediation proposals. Furthermore, the selected finding IDs are not persisted or passed through navigation state, so even if the backend/fixendpoint were called, the frontend has lost the user's selection context.Affected Files
frontend/src/app/pages/fix.tsx— Entire file (lines 1–196). 100% hardcoded sample data, no API calls.frontend/src/app/pages/findings.tsx— "Propose Fixes" button navigation (line 450–451):<Link to="/fix">with no state, query params, or context.frontend/src/app/lib/api.ts—fix()function (lines 130–138) exists but is never called from any component.frontend/src/app/routes.ts— Fix route definition (line 17).backend/app/remediation/engine.py— The backendpropose_fixes()function exists and works, but is unused by the frontend.Root Cause
Issue A — No navigation state for selected findings
In
findings.tsxline 450:This is a plain
<Link>with nostate, no search params (e.g.,?findingIds=...), and no callback. TheselectedFindingsstate (aSet<string>) exists in theFindingscomponent but is never passed anywhere. When the user navigates to/fix, theFixcomponent has no idea which findings were selected.Even if we fixed the Fix page to call the backend, it would call
POST /fixwith either nofinding_idsor a hardcoded list, because the selection context is lost.Issue B — Fix page is fully hardcoded
The
Fixcomponent (fix.tsx:31–52) defines its own inline array of fix objects:It never:
scan-store.tsfor the current job_idapi.fix(jobId, findingIds)findingIdsFixobjects from the backend responseDiffViewerdata is fabricatedIssue C — Backend
/fixendpoint is orphanedThe backend endpoint at
POST /fix(main.py:609–619) works correctly, receivingFixRequest(job_id, finding_ids)and returningFixResponse(job_id, fixes). But no frontend code callsapi.fix()on any page. Theapi.tsexport offix()is defined but has zero callers.Expected Behavior
/fixpage./fixpage should:job_idfromscan-store.tsPOST /fixwith{ job_id, finding_ids }Fixobjects with real diffs, status, summaries, and notesSuggested Approach
findings.tsxto pass selected IDs via React Routerstateor search params:fix.tsxto:statefromuseLocation()scan-storefor job_id (but show error if no findings selected)api.fix(jobId, findingIds)on mountFixResponse.difffield is populated (currently alwaysNoneforsemgrep:andosv:finding types —engine.py:21,36setdiff=None). The engine needs to be enhanced to actually generate diffs./verifywith the applied fix metadata.