From eeb7d8b0ead4ea2fff20bb4c12695eff022a7f27 Mon Sep 17 00:00:00 2001 From: ValayaDase Date: Thu, 16 Jul 2026 01:01:55 +0530 Subject: [PATCH 1/2] recent scans added --- README.md | 1 + backend/app/__pycache__/main.cpython-312.pyc | Bin 6275 -> 88674 bytes backend/app/__pycache__/main.cpython-313.pyc | Bin 10907 -> 87889 bytes .../app/__pycache__/models.cpython-312.pyc | Bin 2499 -> 3907 bytes backend/app/main.py | 33 + backend/app/ml/fp_predictor.py | 21 +- .../__pycache__/engine.cpython-312.pyc | Bin 1926 -> 1914 bytes .../__pycache__/templates.cpython-312.pyc | Bin 1172 -> 1143 bytes .../__pycache__/evidence_pack.cpython-312.pyc | Bin 3766 -> 5443 bytes .../__pycache__/verify.cpython-312.pyc | Bin 1346 -> 4922 bytes .../__pycache__/gitleaks.cpython-312.pyc | Bin 2239 -> 2908 bytes .../scanners/__pycache__/osv.cpython-312.pyc | Bin 2348 -> 5459 bytes .../__pycache__/semgrep.cpython-312.pyc | Bin 2386 -> 3597 bytes .../utils/__pycache__/exec.cpython-312.pyc | Bin 1072 -> 1826 bytes .../app/utils/__pycache__/fs.cpython-312.pyc | Bin 2038 -> 5732 bytes backend/tests/conftest.py | 14 + backend/tests/test_job_endpoints.py | 58 ++ .../app/components/dashboard/RecentScans.tsx | 54 +- frontend/src/app/hooks/useRecentJobs.ts | 150 ++-- frontend/src/app/lib/api.ts | 769 +++++++++--------- frontend/src/app/pages/findings.tsx | 59 +- frontend/src/app/pages/verify.tsx | 2 +- 22 files changed, 694 insertions(+), 467 deletions(-) create mode 100644 backend/tests/conftest.py diff --git a/README.md b/README.md index a91a755..b82c315 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ Open `http://localhost:5173` in your browser. | Method | Route | Description | |---|---|---| | `GET` | `/health` | Health check | +| `GET` | `/jobs` | List scan jobs (paginated) | | `POST` | `/scan` | Upload ZIP and scan | | `POST` | `/scan-url` | Import GitHub repo URL and scan | | `POST` | `/fix` | Generate proposed fixes | diff --git a/backend/app/__pycache__/main.cpython-312.pyc b/backend/app/__pycache__/main.cpython-312.pyc index a8965af794361da0c6354518d9f4cfa5e1f95376..ab8b357c438595f024b4059b60aaf418d192bbd1 100644 GIT binary patch literal 88674 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

|dKS?L* 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 LJ5?X#aiISPukdnF literal 6275 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 X+Y8>#64Ui5%QIa#-2Dkch8q6@krcC6 diff --git a/backend/app/__pycache__/main.cpython-313.pyc b/backend/app/__pycache__/main.cpython-313.pyc index ec94d8cfb7cfa08ca16139b6ac2e3ecf5ca44c9d..ac43730076a5f95c209a7cde281622b633c15799 100644 GIT binary patch literal 87889 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 WA-hiokKivPn!jkXp4w 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 literal 10907 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 list[float]: for f in findings ] - if not self.is_ready or not findings: + if not TORCH_AND_TRANSFORMERS_AVAILABLE or not self.is_ready or not findings: return scores try: diff --git a/backend/app/remediation/__pycache__/engine.cpython-312.pyc b/backend/app/remediation/__pycache__/engine.cpython-312.pyc index 705feea38a9058c61d35694a506b3ee61f284205..9fbb26c43997c2bb1e4d398bfd4559b452cd53d5 100644 GIT binary patch delta 941 zcma)4O=uHA6rRccWPh@oCZ$c%q{b#~(?mfu9z<-4VD%Du@lXs(h}msS&7ZSdY@ww+ zNHHLkum?Q~f*^_D#hWK@QVRtO4oiy#^-xd2#)}u7X&VF!;yZlv-kbNm$9(fv-9J@z zT~Q=JtiCZl`%-AAewc2=Vq*|!tj3l2vNPi(KCd}TLRrj+Who<(Ski`_Y zwApmgF!vm!O&r?H)#Cgfq`t%UX?jhsXnG~Tke#a)P)^gcm8z*XHUo(~t?!yb90mZm z|C}%%g92D`EW#_`);j=}80#tY$*@U#5<>}V3MLX7Fr9}90GdZmi)|j|y2TJYN)h@H zq@d7A98 z`*jv9IFr^lx|Hix5dK7dum@MtXIshp~ATI@mX#B z+eDm0R4SxWa8u}|;I-bevC9SG65E`Jvwv54Nj}cml40hMY1}WGcWgdaqkn^_Vult;ym(^6Vd-fe(NwWJw4Lme~IHg^V40|66b zBrze)nCQZ|aYZ1}mH)uFaG^vNlTia37VH|S8#a0`()hr$_~zU*-*>+II0y2>p!{Bv z0su#T@r^#g*5o+M*HWoblgTkAn`0qRfl3=(j#K?AWAJ7m7r-@Ey@%%T;B6xpEUHS3H{CB2Fj(;QkA&d7*!&5><1tK6LPF~EGbMaL=L2l}4{!dkE!$M0BvEv7Dz64gz71iWKGt~+ zGfpN&Roal(@n%Uh)!6qP4HkS;ARTmG`U;S7C~Cx+pcLmd^&_07Q4q6H3xN=Ui1U$7 zjijl6>S@0huxtg{*1T@t@))IB)ygX3i9{eEI-~y6eb+K)@)yl&Po`3|^5@k#rCii9 z+FbsUqL+KFqRMTpXj=~Qk1cg#5fNIu7?yz>ODtd53ATR&DZlWDas_#Hd}aLEsV$-3 z6+^4pmF)Add!oyY^}6wb+tuT?CB8(5K1GKc65B2}04oLSEkJ79ITH473CUwZ^S4m` zTj`u*qDy}`>_kd#q*C`&vDOC95d#hzv=ReOS`}BsCsS^$-3@oRk>LhQM+4sh%?tHO zh<9JV4uKe2&hF!bfi#2S_=Cu!p#+9|JQ>m(mW`%829Mw@Dj$`cZN?9S&Mq^!gvj(D z7K6vC`pk@>-}D%>qH2b9c;y~%Yi89@Y|T2leZnVKx&}}e$vZF{aA&b**3iaL3NOi+ jTHP4x6ol|A=-mbJZIIdosn0+@%qJVnAPk`{GDANB214mD diff --git a/backend/app/remediation/__pycache__/templates.cpython-312.pyc b/backend/app/remediation/__pycache__/templates.cpython-312.pyc index 0be60c3ddc0339c073c88dea74983edac4ee222c..0d6e58c438d485961c42b01392fc4a28336cbe9d 100644 GIT binary patch delta 99 zcmbQj`JIFJG%qg~0}ync4bPgkk@qJfhqo$KSs9ARZQKCjQo??SYnKB waoFVMrc092 delta 102 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 HF>U-m=+KII delta 2030 zcma)7U2GIp6u$Gj^RvHfyDg>I^4l)BluE1B@K>mof(QhSrIZZI+}kqC?o7Qi+n>$W z*2FhnB=dj?AsQcygeF2vfX7CIVtm=sO&}wL2lT=CQY{HdU-aHB(}JXlH<@$3d(WBg zoO|coGe2y(v9{@#P)Gq}d^>)_h!XUePW-_x0%rc~g{EEGA%H?w%E^6lPU%w^07V$c zs<~iakYEK$pYnYns6v_O@EDs6Ubwa6%_QsbU54&>T&Fqq2jxpLUI6D!P0vA{_X814 zv)}+==5G*r5x9SbdbdF4DzoS^&KDWT7THSxaz(Bp`AgukSWp2N7m9+baT}o%^7#fy za$hk;00UFfRl-NdxcGuye#stq!LGbymx=;Z-IHANW(sIz7^E^2Sq$*JEQ*v^Tf=p3L=X3M7$!)SromJ~f{&~UOS zea`koh#aIlG~R@1rN}yk7{N4Ij8HUWVJ9_U;auABc$$O9;q*u$_$>JPaaC^=QM0t4kkqfJdR|Hs|j*FWle`oTR`LUW8wX- zxB7c>LycXQZufV>;k2ovE;QVKIBl4XM;G^GyQ`(vrudn>k%bx>HXu0=q|r!t7a?; znc-WmaW@0k1Gl8<^|RaGE*<@_#J80B-X+I|8KL}<9-m@dYXc#9CevfK(K1^$W!&X$%4I#oXG9%o4Ui?kBJnKKZS+v+JOG7 z(-9*85_u{OeUyNU0Fri0x&d2cX!j=VU6=UFf#V=4yyrfR9AmGr?!jn>dp_Fg-j4RT zHL*S4os50Ybkci^1u8ZY;mL+=Emk5JVTwEvBPWl|ifd9_tj8B!aHsE_jChKs z4dlrSNYgO=_uv{pesp-No2{xJ6P>Xka?x;r8t4&uO5QQD_BJ$%bWE>MrQ#}kxdQNB zxb^}mD0d9jwMdh&XL I;VUfv0_(EjGXMYp diff --git a/backend/app/sandbox/__pycache__/verify.cpython-312.pyc b/backend/app/sandbox/__pycache__/verify.cpython-312.pyc index c289c4ce37b84256b4c82819c8d3f6ee1b1ae307..5d58dbfbb22f9122a3c40077fc9afe2aefaa1015 100644 GIT binary patch literal 4922 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 Z{3kklfL=R5@dI@J2X$PM!t__5_g}?2?y~>@ delta 1348 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 literal 2348 zcmai0OKcm*8J^`n$<yt}wZBP|dd?H|eaFp51*RLRRN65d zGo7->ftSu0&Sk#7YTC|s90V}xaWjR@RDzQkD#!G5`gtX zVL@=7$P|PEV7?`;fD|7Ko`MHUA)pooI^;!8Z6BdosVeZyRF_?;*;^13XhAB7v)*UK zstlGBXr<=6tAgzj0L_A2kVnzQAK+f4pzNrn?4YF9 zw{nZ`d3HhAR`)b`&@Z4}q}rd70zc#DARqmmkevm6H>7oqT`YF|pYuTd90zgeUHMk$ z3RDdr^?d=o{fUI${xAFpw&WN409Ghtw zBYwq55Sum6Wi7C1Trw@wF=4}F;=F!(;(YAf_^I*J7si=%a_q#(yad;eYzZSwt*J68 zWh4m`GglJKhe?K{FiFL8`OxSSI{dWlT$rhLHkmYNj;WY9hH2Rhng4?#WtuTFL*fp> z%ty%#p6qAYYG!ylVw#l($tslu5ZG`GeyNkCsdyR_%B#HUFG6YF%O4Fynlfo@{P^j7 zh&yItI|$(!cmly;Cmn|NWfq}dMdd0O8U`aY!lzz7?Slz$YOpYg$BoHW+Q2sR9=jSR z+qlF8ahPIcxF0D`z-S}WD9NO!u}LAINz4R5QN=4lENL^hCPF}I3s5w`S(!WBX2Kj( zImNxkQP{lb!%vT`Q==nOW64Z-G#$66j^H^1JU&Y1rv7M{sqh(^o`rDOQ_!~Km(Q41 z+L^ip2?Nlk0O3?E3+*Xz&rl}EntA)?QK}u#LvSCDp8X$auGbLry?pKHU9EXhTn?5e zzS0g}JF=-D&07rq^-r4~(c5viJ+L%#ePr1vX*aG^+6RiGn;Pl~7e%+NW2ygo|MGC@ zQl%}r-u7boY*BUFJ0BpwH&8t420EAKug@>%%P&;|L+gQG-svr#bOU=Ip!UYVqUZ*@ z-dAs^YvF@;UaACty&gQg+Pf&bp`Hh*wKcGK#O>MpKDj|kqvcqo=g{H_cW>X~N%y(H z(ks_rd3WC36Db`ih02lg(c33(p13o%N-KkZ_`xZQWN?@mKy;J5DnU)ZZNdme?u=FE4{uJ9C)NFt-ej9wCFH-_01;K&~$C=@uO1$Y6(3+g15tM_y2ut zQv_5V=a?)f%d%*G=>g z1QCV)i?+1GAfL6!@8}U=A?J|I8wCItgbmbt59u2yxPby2sCxs2A1N`RiT)l0egbhU BROJ8w diff --git a/backend/app/scanners/__pycache__/semgrep.cpython-312.pyc b/backend/app/scanners/__pycache__/semgrep.cpython-312.pyc index fa376a61b98e1e786f2be853c2ec5c80d15c07f5..aa176e972d9b0acbd8d1af0f034f0f3e06af641e 100644 GIT binary patch literal 3597 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 XLC-$uZiXOKH>4(D>^M9KH80FR{E3!; literal 1072 zcmZ8gOKa3n6h1e}WRmI3^x>neA{Id*Q2YT>gkr%5T8p}hk&xzIZE9ZL+|-VY&_y@m zqIK21J89Sc372k$ON(Gv?g||@t~@sx7xqBD^SZe?=Q}6gI-M4v{Oo^?x*EW-a{fu9 zHpr=m#vV|hB!+~zgeY5!HCIEe$9iJ8Min#SMq;{V(sY}Nxyl5wG?t=J zNPRKwh4qCsl94)Xqp=4JTtdOsdc@JBeJ7z$SW(7e+0mut`)QCc-6DrrlTl_Gg z{3?2?o8ke&793hrJKYc6fi-s69^chJ-WyC`9&{!L6SKoH(>Avjhh1o27_`R+=g#jf zd|DWcPwZ@d*c_>$-DsO9&}f*|932wPBm0h374^r8zs+x;t9GQgj&PzALXP0tF-#u8%nz9V4)a5k5PR1c0;=Cuht$pe1+caC A>Hq)$ diff --git a/backend/app/utils/__pycache__/fs.cpython-312.pyc b/backend/app/utils/__pycache__/fs.cpython-312.pyc index 913f802579657ec10c83637f5ee0388df53899b8..16918e124ceadf4be56ad6d716930066fb0081a8 100644 GIT binary patch literal 5732 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 delta 940 zcmb_aO;1xn6rFjWGcB*61%;CGAs`emgs34JF)=9`MT|rfk_OY%z7k(;X)}G0*gT>O zH^c=rv%r$n!aIDS2yZ3$=Mx$!IJbZj!72q&h;M`G4w%WalPCgOIETlgHN`~`lG4Sq-J_7dm^ z9&l-0;w$)c&EkQ9^JqqLq@>EfseOj-x^r-n@|YIjeHsnPw)c>i7jYSz(!(x<<}uS9 z*_0cAOd7Bw*mh9OD4^kU_f;~mHT;$4uU7Iv=0SNzb=0I^aDLTP-)gQij2xxx;zk(V z8-RtHUFQlVPq?U(ZQ){nIGSto2&Xz4v>wsVcq=LazT|6Cp#T19|4$$6_Gv!S$8}c8 zj>^YKPoI9Ph}jQusZ6{`QHk2=>|Le-4*80D-pWo`sYFqaSlO!p_+K)Lbv{aKC7kEa zXrm(DjK8Ce1Kj|Q!OR6f?Fm|^HFM3g&Cly!p8ZNYcMw*aUiYsOI#)GYH9xjYf`4S7 zb_tJo;yNGsg)qIqKY7}Mkhh3$&X_gk { const date = new Date(timestamp); return new Intl.DateTimeFormat("en-US", { @@ -60,7 +63,17 @@ export function RecentScans({ recentJobs, onClearRecents }: RecentScansProps) { {recentJobs.map((job) => ( - + { + if (job.status === "completed") { + navigate(`/findings?job_id=${job.id}`); + } + }} + > {job.id} {job.repoName} @@ -69,11 +82,15 @@ export function RecentScans({ recentJobs, onClearRecents }: RecentScansProps) { {job.status === "completed" && {job.findingsCount}} - + e.stopPropagation()}> {job.status === "completed" && } - - - + {job.status === "completed" ? ( + + + + ) : ( + + )} ))} @@ -82,9 +99,12 @@ export function RecentScans({ recentJobs, onClearRecents }: RecentScansProps) {

- {recentJobs.map((job) => ( - - + {recentJobs.map((job) => { + const cardContent = ( +
@@ -95,15 +115,25 @@ export function RecentScans({ recentJobs, onClearRecents }: RecentScansProps) {
{formatTimestamp(job.timestamp)} -
+
e.stopPropagation()}> {job.status === "completed" && } {job.status === "completed" && {job.findingsCount} findings}
- - ))} + ); + + return job.status === "completed" ? ( + + {cardContent} + + ) : ( +
+ {cardContent} +
+ ); + })}
)} diff --git a/frontend/src/app/hooks/useRecentJobs.ts b/frontend/src/app/hooks/useRecentJobs.ts index bd84496..53c24be 100644 --- a/frontend/src/app/hooks/useRecentJobs.ts +++ b/frontend/src/app/hooks/useRecentJobs.ts @@ -1,63 +1,87 @@ -import { useState, useCallback } from "react"; -import { useNavigate } from "react-router-dom"; -import { saveLastScan } from "../lib/scan-store"; - -export type UiJobStatus = "completed" | "running" | "failed" | "pending"; - -export type UiJob = { - id: string; - repoName: string; - status: UiJobStatus; - timestamp: string; - duration?: string; - findingsCount: number; -}; - -const RECENTS_KEY = "patchpilot:recentJobs"; - -function getLocalRecentJobs(): UiJob[] { - const raw = localStorage.getItem(RECENTS_KEY); - if (!raw) return []; - try { - const parsed = JSON.parse(raw) as UiJob[]; - return Array.isArray(parsed) ? parsed : []; - } catch { - return []; - } -} - -export function useRecentJobs() { - const navigate = useNavigate(); - const [recentJobs, setRecentJobs] = useState(getLocalRecentJobs); - - const handleScanSuccess = useCallback((scan: { job_id: string; project_name: string; findings?: any[] }) => { - saveLastScan(scan as any); - - const job: UiJob = { - id: scan.job_id, - repoName: scan.project_name, - status: "completed", - timestamp: new Date().toISOString(), - duration: "-", - findingsCount: scan.findings?.length ?? 0, - }; - - const currentJobs = getLocalRecentJobs(); - const next = [job, ...currentJobs.filter((j) => j.id !== job.id)].slice(0, 10); - localStorage.setItem(RECENTS_KEY, JSON.stringify(next)); - - setRecentJobs(next); - navigate("/findings"); - }, [navigate]); - - const onClearRecents = useCallback(() => { - localStorage.removeItem(RECENTS_KEY); - setRecentJobs([]); - }, []); - - return { - recentJobs, - handleScanSuccess, - onClearRecents - }; -} \ No newline at end of file +import { useState, useCallback, useEffect } from "react"; +import { useNavigate } from "react-router-dom"; +import { saveLastScan } from "../lib/scan-store"; +import { listJobs } from "../lib/api"; + +export type UiJobStatus = "completed" | "running" | "failed" | "pending"; + +export type UiJob = { + id: string; + repoName: string; + status: UiJobStatus; + timestamp: string; + duration?: string; + findingsCount: number; +}; + +const CLEARED_KEY = "patchpilot:clearedJobs"; + +function getClearedJobIds(): string[] { + const raw = localStorage.getItem(CLEARED_KEY); + if (!raw) return []; + try { + const parsed = JSON.parse(raw); + return Array.isArray(parsed) ? parsed : []; + } catch { + return []; + } +} + +export function useRecentJobs() { + const navigate = useNavigate(); + const [recentJobs, setRecentJobs] = useState([]); + + const fetchJobs = useCallback(async () => { + try { + const res = await listJobs(10, 0); + const clearedIds = getClearedJobIds(); + const filtered = res.jobs + .filter((j) => !clearedIds.includes(j.job_id)) + .map((j) => ({ + id: j.job_id, + repoName: j.project_name, + status: j.status as UiJobStatus, + timestamp: j.created_at, + duration: "-", + findingsCount: j.finding_count ?? 0, + })); + setRecentJobs(filtered); + } catch (err) { + console.error("Failed to fetch recent jobs:", err); + } + }, []); + + useEffect(() => { + fetchJobs(); + }, [fetchJobs]); + + const handleScanSuccess = useCallback((scan: { job_id: string; project_name: string; findings?: any[] }) => { + saveLastScan(scan as any); + + const job: UiJob = { + id: scan.job_id, + repoName: scan.project_name, + status: "completed", + timestamp: new Date().toISOString(), + duration: "-", + findingsCount: scan.findings?.length ?? 0, + }; + + setRecentJobs((prev) => [job, ...prev.filter((j) => j.id !== job.id)].slice(0, 10)); + navigate(`/findings?job_id=${scan.job_id}`); + }, [navigate]); + + const onClearRecents = useCallback(() => { + const jobIds = recentJobs.map((j) => j.id); + const clearedIds = getClearedJobIds(); + const next = Array.from(new Set([...clearedIds, ...jobIds])); + localStorage.setItem(CLEARED_KEY, JSON.stringify(next)); + setRecentJobs([]); + }, [recentJobs]); + + return { + recentJobs, + handleScanSuccess, + onClearRecents + }; +} \ No newline at end of file diff --git a/frontend/src/app/lib/api.ts b/frontend/src/app/lib/api.ts index b2ef971..76d2a5e 100644 --- a/frontend/src/app/lib/api.ts +++ b/frontend/src/app/lib/api.ts @@ -1,374 +1,395 @@ -export const API_BASE = - import.meta.env.VITE_API_BASE_URL?.replace(/\/$/, "") || - "http://localhost:8000"; - -export type HealthResponse = { - ok: boolean; - status: "healthy" | "degraded"; - scanners: Record; -}; - -export async function getHealth() { - const res = await fetch(`${API_BASE}/health`); - - if (!res.ok) { - throw new Error(await res.text()); - } - - return (await res.json()) as HealthResponse; -} - -export type ScanResponse = { - job_id: string; - project_name: string; - repo_path: string; - scanners: Record; - findings: BackendFinding[]; -}; - -export type BackendFinding = { - id: string; - severity: "CRITICAL" | "HIGH" | "MEDIUM" | "LOW" | "INFO"; - category: string; - title: string; - description?: string; - - location?: { - path?: string; - start_line?: number; - end_line?: number; - }; - - metadata?: { - engine?: string; - [key: string]: unknown; - }; - - reachability?: { - reachable?: boolean; - reason?: string; -}; - -features?: Record; - confidence?: number; - code?: string; - suggested_fix?: string; - references?: string[]; - ml_score?: number; - false_positive?: boolean | number | null; - version?: number; -}; - -export type ScanInitResponse = { - job_id: string; - project_name: string; - status: string; -}; - -export async function scanZip(file: File, projectName = "project") { - const form = new FormData(); - form.append("project", file); - form.append("project_name", projectName); - - const res = await fetch(`${API_BASE}/scan`, { - method: "POST", - body: form, - }); - - if (!res.ok) throw new Error(await res.text()); - return (await res.json()) as ScanInitResponse; -} - -export async function scanRepoUrl( - repoUrl: string, - ref = "main", - projectName = "project", -) { - const form = new FormData(); - form.append("repo_url", repoUrl); - form.append("ref", ref); - form.append("project_name", projectName); - - const res = await fetch(`${API_BASE}/scan-url`, { - method: "POST", - body: form, - }); - - if (!res.ok) { - const err = await res.json().catch(() => null); - throw new Error(err?.detail ?? "Import from URL failed"); - } - - return (await res.json()) as ScanInitResponse; -} -export async function getJobFindings(jobId: string): Promise { - const res = await fetch(`${API_BASE}/jobs/${jobId}/findings`); - if (!res.ok) throw new Error(await res.text()); - return (await res.json()) as BackendFinding[]; -} - -export async function labelFinding( - findingId: string, - falsePositive: boolean, - expectedVersion: number, - signal?: AbortSignal, -) { - const res = await fetch(`${API_BASE}/findings/${findingId}/label`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ false_positive: falsePositive, expected_version: expectedVersion }), - signal, - }); - if (!res.ok) { - const errText = await res.text(); - const error = new Error(errText); - (error as any).status = res.status; - throw error; - } - return res.json(); -} - -export async function updateFindingStatus(findingId: string, status: "open" | "accepted" | "ignored") { - const res = await fetch(`${API_BASE}/findings/${findingId}/status`, { - method: "PATCH", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ status }), - }); - - if (!res.ok) throw new Error(await res.text()); - return res.json(); -} - -export async function fix(jobId: string, findingIds: string[]) { - const res = await fetch(`${API_BASE}/fix`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ job_id: jobId, finding_ids: findingIds }), - }); - - if (!res.ok) throw new Error(await res.text()); - return res.json(); -} - -export async function verify(jobId: string) { - const form = new FormData(); - form.append("job_id", jobId); - - const res = await fetch(`${API_BASE}/verify`, { method: "POST", body: form }); - if (!res.ok) throw new Error(await res.text()); - return res.json(); -} - -/** - * POST /evidence-pack -> returns a ZIP (FileResponse) - * This fetches it as a Blob and tries to infer a filename from Content-Disposition. - */ -export async function downloadEvidencePack( - jobId: string, - projectName = "project", -) { - const form = new FormData(); - form.append("job_id", jobId); - form.append("project_name", projectName); - - const res = await fetch(`${API_BASE}/evidence-pack`, { - method: "POST", - body: form, - }); - - if (!res.ok) { - throw new Error(await res.text()); - } - - const blob = await res.blob(); - - const cd = res.headers.get("content-disposition") || ""; - const match = cd.match(/filename="?([^"]+)"?/i); - const filename = match?.[1] || `evidence-pack-${jobId}.zip`; - - return { blob, filename }; -} - -export type TrendData = { - date: string; - findings: number; -}; - -export async function getTrends(limit = 6) { - const res = await fetch(`${API_BASE}/trends?limit=${limit}`); - if (!res.ok) throw new Error(await res.text()); - return (await res.json()) as TrendData[]; -} - -export type CweData = { - name: string; - value: number; -}; - -export async function getCweDistribution() { - const res = await fetch(`${API_BASE}/cwe-distribution`); - if (!res.ok) throw new Error(await res.text()); - return (await res.json()) as CweData[]; -} - -export interface DepFinding { - id: string; - rule_id: string; - severity: string; - message: string; - package_name: string; - package_version: string; -} - -export interface DependencyDiffResult { - introduced: DepFinding[]; - resolved: DepFinding[]; - persistent: DepFinding[]; -} - -export const getDependencyDiff = async (): Promise => { - const response = await fetch(`${API_BASE}/dependency-diff`); - if (!response.ok) { - throw new Error("Failed to fetch dependency diff"); - } - return response.json(); -}; - -export interface ContributorStat { - github_username: string; - findings_closed: number; - fixes_passed: number; - prs_merged: number; - last_updated: string; - total_score: number; -} - -export interface LeaderboardUpdateRequest { - github_username: string; - pr_description?: string; - fixes_passed?: number; - is_pr_merged?: boolean; -} - -export async function getLeaderboard(): Promise { - const res = await fetch(`${API_BASE}/leaderboard`); - if (!res.ok) throw new Error(await res.text()); - return res.json(); -} - -export async function updateLeaderboard(data: LeaderboardUpdateRequest) { - const res = await fetch(`${API_BASE}/leaderboard/update`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(data), - }); - if (!res.ok) throw new Error(await res.text()); - return res.json(); -} - -export async function downloadAuditReport(jobId: string) { - const res = await fetch(`${API_BASE}/api/scans/${jobId}/report/pdf`); - - if (!res.ok) { - throw new Error(await res.text()); - } - - const blob = await res.blob(); - return { blob, filename: `PatchPilot-Audit-${jobId}.pdf` }; -} - -export type RepoStatus = { - job_id: string; - project_name: string; - status: "pending" | "scanning" | "completed" | "failed" | "aborted"; -}; - -export type OrgJobStatusResponse = { - org_job_id: string; - status: "pending" | "scanning" | "completed" | "failed" | "aborted"; - repos: RepoStatus[]; -}; - -export async function scanOrganization(orgUrl: string) { - const res = await fetch(`${API_BASE}/api/scans/org`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ org_url: orgUrl }), - }); - - if (!res.ok) { - throw new Error(await res.text()); - } - - return (await res.json()) as { org_job_id: string; org_name: string; repo_count: number }; -} - -export async function getOrgJobStatus(orgJobId: string) { - const res = await fetch(`${API_BASE}/api/scans/org/${orgJobId}/status`); - - if (!res.ok) { - throw new Error(await res.text()); - } - - return (await res.json()) as OrgJobStatusResponse; -} - -export const abortOrganizationScan = async (orgJobId: string, mode: "pending" | "force" = "pending") => { - const response = await fetch(`${API_BASE}/api/scans/org/${orgJobId}/abort?mode=${mode}`, { - method: "POST", - }); - if (!response.ok) throw new Error("Failed to abort scan"); - return response.json(); -}; - -export async function getOrgSummary(orgJobId: string) { - const res = await fetch(`${API_BASE}/api/scans/org/${orgJobId}/summary`); - if (!res.ok) throw new Error("Failed to fetch organization summary"); - return res.json(); -} - -export async function getOrgFindings(orgJobId: string) { - const res = await fetch(`${API_BASE}/api/scans/org/${orgJobId}/findings`); - if (!res.ok) throw new Error("Failed to fetch organization findings"); - return res.json(); -} - -export async function downloadOrgAuditReport(orgJobId: string) { - const res = await fetch(`${API_BASE}/api/scans/org/${orgJobId}/report/pdf`); - - if (!res.ok) { - throw new Error(await res.text()); - } - - const blob = await res.blob(); - - const cd = res.headers.get("content-disposition") || ""; - const match = cd.match(/filename="?([^"]+)"?/i); - const filename = match?.[1] || `PatchPilot-Org-Audit-${orgJobId}.pdf`; - - return { blob, filename }; -} - -export const getOrgBlastRadius = async (orgJobId: string) => { - const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8000'; - const response = await fetch(`${baseUrl}/api/scans/org/${orgJobId}/blast-radius`); - - if (!response.ok) { - throw new Error('Failed to fetch blast radius data'); - } - return response.json(); -}; - -export interface OllamaHealthResponse { - available: boolean; - models: string[]; - base_url: string; -} - -export async function getOllamaHealth(): Promise { - const res = await fetch(`${API_BASE}/api/health/ollama`); - if (!res.ok) { - throw new Error(await res.text()); - } - return res.json(); -} \ No newline at end of file +export const API_BASE = + import.meta.env.VITE_API_BASE_URL?.replace(/\/$/, "") || + "http://localhost:8000"; + +export type HealthResponse = { + ok: boolean; + status: "healthy" | "degraded"; + scanners: Record; +}; + +export async function getHealth() { + const res = await fetch(`${API_BASE}/health`); + + if (!res.ok) { + throw new Error(await res.text()); + } + + return (await res.json()) as HealthResponse; +} + +export type ScanResponse = { + job_id: string; + project_name: string; + repo_path: string; + scanners: Record; + findings: BackendFinding[]; +}; + +export type BackendFinding = { + id: string; + severity: "CRITICAL" | "HIGH" | "MEDIUM" | "LOW" | "INFO"; + category: string; + title: string; + description?: string; + + location?: { + path?: string; + start_line?: number; + end_line?: number; + }; + + metadata?: { + engine?: string; + [key: string]: unknown; + }; + + reachability?: { + reachable?: boolean; + reason?: string; +}; + +features?: Record; + confidence?: number; + code?: string; + suggested_fix?: string; + references?: string[]; + ml_score?: number; + false_positive?: boolean | number | null; + version?: number; +}; + +export type ScanInitResponse = { + job_id: string; + project_name: string; + status: string; +}; + +export async function scanZip(file: File, projectName = "project") { + const form = new FormData(); + form.append("project", file); + form.append("project_name", projectName); + + const res = await fetch(`${API_BASE}/scan`, { + method: "POST", + body: form, + }); + + if (!res.ok) throw new Error(await res.text()); + return (await res.json()) as ScanInitResponse; +} + +export async function scanRepoUrl( + repoUrl: string, + ref = "main", + projectName = "project", +) { + const form = new FormData(); + form.append("repo_url", repoUrl); + form.append("ref", ref); + form.append("project_name", projectName); + + const res = await fetch(`${API_BASE}/scan-url`, { + method: "POST", + body: form, + }); + + if (!res.ok) { + const err = await res.json().catch(() => null); + throw new Error(err?.detail ?? "Import from URL failed"); + } + + return (await res.json()) as ScanInitResponse; +} +export async function getJobFindings(jobId: string): Promise { + const res = await fetch(`${API_BASE}/jobs/${jobId}/findings`); + if (!res.ok) throw new Error(await res.text()); + return (await res.json()) as BackendFinding[]; +} + +export async function labelFinding( + findingId: string, + falsePositive: boolean, + expectedVersion: number, + signal?: AbortSignal, +) { + const res = await fetch(`${API_BASE}/findings/${findingId}/label`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ false_positive: falsePositive, expected_version: expectedVersion }), + signal, + }); + if (!res.ok) { + const errText = await res.text(); + const error = new Error(errText); + (error as any).status = res.status; + throw error; + } + return res.json(); +} + +export async function updateFindingStatus(findingId: string, status: "open" | "accepted" | "ignored") { + const res = await fetch(`${API_BASE}/findings/${findingId}/status`, { + method: "PATCH", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ status }), + }); + + if (!res.ok) throw new Error(await res.text()); + return res.json(); +} + +export async function fix(jobId: string, findingIds: string[]) { + const res = await fetch(`${API_BASE}/fix`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ job_id: jobId, finding_ids: findingIds }), + }); + + if (!res.ok) throw new Error(await res.text()); + return res.json(); +} + +export async function verify(jobId: string) { + const form = new FormData(); + form.append("job_id", jobId); + + const res = await fetch(`${API_BASE}/verify`, { method: "POST", body: form }); + if (!res.ok) throw new Error(await res.text()); + return res.json(); +} + +/** + * POST /evidence-pack -> returns a ZIP (FileResponse) + * This fetches it as a Blob and tries to infer a filename from Content-Disposition. + */ +export async function downloadEvidencePack( + jobId: string, + projectName = "project", +) { + const form = new FormData(); + form.append("job_id", jobId); + form.append("project_name", projectName); + + const res = await fetch(`${API_BASE}/evidence-pack`, { + method: "POST", + body: form, + }); + + if (!res.ok) { + throw new Error(await res.text()); + } + + const blob = await res.blob(); + + const cd = res.headers.get("content-disposition") || ""; + const match = cd.match(/filename="?([^"]+)"?/i); + const filename = match?.[1] || `evidence-pack-${jobId}.zip`; + + return { blob, filename }; +} + +export type TrendData = { + date: string; + findings: number; +}; + +export async function getTrends(limit = 6) { + const res = await fetch(`${API_BASE}/trends?limit=${limit}`); + if (!res.ok) throw new Error(await res.text()); + return (await res.json()) as TrendData[]; +} + +export type CweData = { + name: string; + value: number; +}; + +export async function getCweDistribution() { + const res = await fetch(`${API_BASE}/cwe-distribution`); + if (!res.ok) throw new Error(await res.text()); + return (await res.json()) as CweData[]; +} + +export interface DepFinding { + id: string; + rule_id: string; + severity: string; + message: string; + package_name: string; + package_version: string; +} + +export interface DependencyDiffResult { + introduced: DepFinding[]; + resolved: DepFinding[]; + persistent: DepFinding[]; +} + +export const getDependencyDiff = async (): Promise => { + const response = await fetch(`${API_BASE}/dependency-diff`); + if (!response.ok) { + throw new Error("Failed to fetch dependency diff"); + } + return response.json(); +}; + +export interface ContributorStat { + github_username: string; + findings_closed: number; + fixes_passed: number; + prs_merged: number; + last_updated: string; + total_score: number; +} + +export interface LeaderboardUpdateRequest { + github_username: string; + pr_description?: string; + fixes_passed?: number; + is_pr_merged?: boolean; +} + +export async function getLeaderboard(): Promise { + const res = await fetch(`${API_BASE}/leaderboard`); + if (!res.ok) throw new Error(await res.text()); + return res.json(); +} + +export async function updateLeaderboard(data: LeaderboardUpdateRequest) { + const res = await fetch(`${API_BASE}/leaderboard/update`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(data), + }); + if (!res.ok) throw new Error(await res.text()); + return res.json(); +} + +export async function downloadAuditReport(jobId: string) { + const res = await fetch(`${API_BASE}/api/scans/${jobId}/report/pdf`); + + if (!res.ok) { + throw new Error(await res.text()); + } + + const blob = await res.blob(); + return { blob, filename: `PatchPilot-Audit-${jobId}.pdf` }; +} + +export type RepoStatus = { + job_id: string; + project_name: string; + status: "pending" | "scanning" | "completed" | "failed" | "aborted"; +}; + +export type OrgJobStatusResponse = { + org_job_id: string; + status: "pending" | "scanning" | "completed" | "failed" | "aborted"; + repos: RepoStatus[]; +}; + +export async function scanOrganization(orgUrl: string) { + const res = await fetch(`${API_BASE}/api/scans/org`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ org_url: orgUrl }), + }); + + if (!res.ok) { + throw new Error(await res.text()); + } + + return (await res.json()) as { org_job_id: string; org_name: string; repo_count: number }; +} + +export async function getOrgJobStatus(orgJobId: string) { + const res = await fetch(`${API_BASE}/api/scans/org/${orgJobId}/status`); + + if (!res.ok) { + throw new Error(await res.text()); + } + + return (await res.json()) as OrgJobStatusResponse; +} + +export const abortOrganizationScan = async (orgJobId: string, mode: "pending" | "force" = "pending") => { + const response = await fetch(`${API_BASE}/api/scans/org/${orgJobId}/abort?mode=${mode}`, { + method: "POST", + }); + if (!response.ok) throw new Error("Failed to abort scan"); + return response.json(); +}; + +export async function getOrgSummary(orgJobId: string) { + const res = await fetch(`${API_BASE}/api/scans/org/${orgJobId}/summary`); + if (!res.ok) throw new Error("Failed to fetch organization summary"); + return res.json(); +} + +export async function getOrgFindings(orgJobId: string) { + const res = await fetch(`${API_BASE}/api/scans/org/${orgJobId}/findings`); + if (!res.ok) throw new Error("Failed to fetch organization findings"); + return res.json(); +} + +export async function downloadOrgAuditReport(orgJobId: string) { + const res = await fetch(`${API_BASE}/api/scans/org/${orgJobId}/report/pdf`); + + if (!res.ok) { + throw new Error(await res.text()); + } + + const blob = await res.blob(); + + const cd = res.headers.get("content-disposition") || ""; + const match = cd.match(/filename="?([^"]+)"?/i); + const filename = match?.[1] || `PatchPilot-Org-Audit-${orgJobId}.pdf`; + + return { blob, filename }; +} + +export const getOrgBlastRadius = async (orgJobId: string) => { + const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8000'; + const response = await fetch(`${baseUrl}/api/scans/org/${orgJobId}/blast-radius`); + + if (!response.ok) { + throw new Error('Failed to fetch blast radius data'); + } + return response.json(); +}; + +export interface OllamaHealthResponse { + available: boolean; + models: string[]; + base_url: string; +} + +export async function getOllamaHealth(): Promise { + const res = await fetch(`${API_BASE}/api/health/ollama`); + if (!res.ok) { + throw new Error(await res.text()); + } + return res.json(); +} + +export type Job = { + job_id: string; + project_name: string; + scan_method: string; + status: string; + finding_count: number | null; + raw_finding_count: number | null; + created_at: string; +}; + +export type ListJobsResponse = { + total: number; + jobs: Job[]; +}; + +export async function listJobs(limit = 20, offset = 0): Promise { + const res = await fetch(`${API_BASE}/jobs?limit=${limit}&offset=${offset}`); + if (!res.ok) throw new Error(await res.text()); + return (await res.json()) as ListJobsResponse; +} \ No newline at end of file diff --git a/frontend/src/app/pages/findings.tsx b/frontend/src/app/pages/findings.tsx index fd0b53f..2f91202 100644 --- a/frontend/src/app/pages/findings.tsx +++ b/frontend/src/app/pages/findings.tsx @@ -45,7 +45,7 @@ import { ToolBadge } from "../components/tool-badge"; import { CodeBlock } from "../components/code-block"; import { FilterChips } from "../components/filter-chips"; import type { Finding } from "../data/sample-data"; -import { loadLastScan } from "../lib/scan-store"; +import { loadLastScan, saveLastScan } from "../lib/scan-store"; import { getJobFindings, updateFindingStatus, labelFinding } from "../lib/api"; import { downloadFindingsAsCsv } from "../lib/csv-export"; type UiFinding = Finding & { false_positive?: boolean | null, version?: number }; @@ -145,32 +145,64 @@ export function MlScorePill({ score }: { score: number }) { export function Findings() { const navigate = useNavigate(); + const [searchParams, setSearchParams] = useSearchParams(); + const queryJobId = searchParams.get("job_id"); const [scan, setScan] = useState(null); const [findings, setFindings] = useState([]); const [isLoadingFindings, setIsLoadingFindings] = useState(true); useEffect(() => { - const storedScan = loadLastScan(); - if (!storedScan?.job_id) { - setIsLoadingFindings(false); - return; - } - setScan(storedScan); - getJobFindings(storedScan.job_id) - .then((response: any) => { + const fetchFindings = async () => { + setIsLoadingFindings(true); + try { + let jobId = queryJobId; + const storedScan = loadLastScan(); + + if (!jobId) { + jobId = storedScan?.job_id; + if (jobId) { + const nextParams = new URLSearchParams(window.location.search); + nextParams.set("job_id", jobId); + setSearchParams(nextParams, { replace: true }); + return; + } + } + + if (!jobId) { + setIsLoadingFindings(false); + return; + } + + const response: any = await getJobFindings(jobId); const actualFindings = Array.isArray(response) ? response : (response.findings || response.data || []); + const projectName = response.project_name || (storedScan?.job_id === jobId ? storedScan.project_name : "Unknown Project"); + + const updatedScan = { + job_id: jobId, + project_name: projectName, + findings: [] + }; + + setScan(updatedScan); + saveLastScan(updatedScan); + setFindings(actualFindings.map((bf: any) => ({ ...mapBackendFindingToUi(bf), false_positive: bf.false_positive === 1 || bf.false_positive === true ? true : (bf.false_positive === 0 || bf.false_positive === false ? false : null) }))); - }) - .catch((err) => console.error("Failed to fetch findings", err)) - .finally(() => setIsLoadingFindings(false)); - }, []); + } catch (err) { + console.error("Failed to fetch findings", err); + } finally { + setIsLoadingFindings(false); + } + }; + + fetchFindings(); + }, [queryJobId, setSearchParams]); const [selectedFindings, setSelectedFindings] = useState>(new Set()); const [detailFinding, setDetailFinding] = useState(null); @@ -243,7 +275,6 @@ export function Findings() { } }; - const [searchParams, setSearchParams] = useSearchParams(); const [searchQuery, setSearchQuery] = useState(() => (searchParams.get("q") ?? "").toString(), diff --git a/frontend/src/app/pages/verify.tsx b/frontend/src/app/pages/verify.tsx index d99d48a..63e58a0 100644 --- a/frontend/src/app/pages/verify.tsx +++ b/frontend/src/app/pages/verify.tsx @@ -330,7 +330,7 @@ export function Verify() { {/* Actions */}
- + From d0d188c231c5df24492ea8cb366f6e3c6a4ec5db Mon Sep 17 00:00:00 2001 From: ValayaDase Date: Sun, 19 Jul 2026 01:18:25 +0530 Subject: [PATCH 2/2] issue solved --- backend/README.md | 14 ++++++++ backend/app/__pycache__/main.cpython-312.pyc | Bin 88674 -> 91452 bytes backend/app/__pycache__/main.cpython-313.pyc | Bin 87889 -> 91999 bytes backend/app/main.py | 6 ++++ backend/app/ml/deduplicator.py | 9 ++++- backend/app/ml/embedder.py | 34 ++++++++++++------ backend/app/ml/fp_predictor.py | 1 + backend/tests/conftest.py | 3 +- backend/tests/test_job_endpoints.py | 1 - .../app/components/dashboard/RecentScans.tsx | 6 +++- frontend/src/app/hooks/useRecentJobs.ts | 19 +++++++++- frontend/src/app/lib/api.ts | 20 +++++++---- frontend/src/app/pages/findings.tsx | 6 ++-- frontend/src/app/pages/fix.tsx | 6 ++-- 14 files changed, 96 insertions(+), 29 deletions(-) diff --git a/backend/README.md b/backend/README.md index 8c050ad..fcdb5cf 100644 --- a/backend/README.md +++ b/backend/README.md @@ -30,3 +30,17 @@ SQLite database (`patchpilot.db`) is auto-created in `backend/` on first server | `scanner` | TEXT | `semgrep`, `osv`, or `gitleaks` | | `message` | TEXT | Description of the finding | | `created_at` | TEXT | Timestamp of finding creation | + +## API Reference + +| Method | Route | Description | +|---|---|---| +| `GET` | `/health` | Health check | +| `GET` | `/jobs` | List scan jobs (paginated) | +| `GET` | `/jobs/{job_id}/findings` | Get findings for a specific job | +| `DELETE` | `/jobs/{job_id}` | Delete a job workspace | +| `POST` | `/scan` | Upload ZIP and scan | +| `POST` | `/scan-url` | Import GitHub repo URL and scan | +| `POST` | `/fix` | Generate proposed fixes | +| `POST` | `/verify` | Verify fixes | +| `POST` | `/evidence-pack` | Build and download evidence ZIP | diff --git a/backend/app/__pycache__/main.cpython-312.pyc b/backend/app/__pycache__/main.cpython-312.pyc index ab8b357c438595f024b4059b60aaf418d192bbd1..6d76ebb112aef466183005389d827f098a656241 100644 GIT binary patch delta 16155 zcma)j3w%`7(fB?4-fZ6QcQzzImPZo8OA;Ui2q8Se8)SK`OYTkBu$v8MH$XyggQB9M zBpzf@QIe_!3R-ZjY1LZrfuMqfpov>rY(M)|Yuhg>U+o9B{%6k3ZZ?tn`!Bzp%spq$ zoS8Xu=FFM9{PAV=>+h)}-;an06W}xb!*zAr65At_6@QOv&vVRH*dxplq97{mk&Z}n zq$A24MFeulKIULv9a~&hiBORm6qa35nqj_7HJn;c`zW8m2!hTB;QnKso?Y%b={ z5%v~9j?He5yvxVa+_PZQbvz6ni_Dzmzb4Im8G>Z<&EIDe-HAK*(B^CBsbFHMQyUMK7 zd@weh|!5FGyRd4%%GO)&NaC5i`wh zXxk za-`F zfxt7Uz7s?~ogAMojt?}7`Fn)mvOOs6tmE#JRuJqj4C#L;&_8E_SOlU@3`{9b3ZZ&f zd_|nRM`hk8c8OEq?;|$B{HQop+ArRLE(A|)LzVJO3(RJ22ghk2aGdr)D>zQE`7uxi z9p|yYoaV>$uwU?>_{#t`@cb*WWRKd+#8<`XF#iGZHE{;~eO!E9{IysLJqI@n;;d(h z*(;Wr59x(Pz~YUeEI8ZWh_iwC3Gs|L2Zlc>o)zc9-=~ICif@YL(0&-LTUUavGiRPy zAC%KCC=h6Y^hNW z)l+<1ylYSvjkzP>3!|-pbrRnZH|FTK@+_vJ`f_>vA_%!d;jwcAk~8*QXN+a6@vKC9zlFqG6iNd|7_6MS^I(x^}hH> z$jB3%W-acpj7NhsABg)yXkG|NG@X`DTMA!fX?F+UmiyHix9fA zO^O^r+MFv;9psppNZQP`YlSw=zL&QPJCtjM?F9N8p}x8mP@lZEjn$WT~;$i?;e&7d;7N z?;vS1fL7rfg<73_BT@*DZOiLWA9G(dOuDR^L~*L>fh-wNLD0e%;x+l^jMnGO-ayC^ z-^CH7Btj6QFpJw2-V!cnnqh5(ex?`TF^A`)XV&U9lZ9Oo?vd;_-)6)_1iWgOQq z5SD&DjeYn>y;@945d`*CQvy46uTHTmhFNp6l9F3u0Z^RM3 zW|z7JWbtNalQcu*HZ;qY+X)H#Dlm?HkQ1Y*OJQXnr?KDX@h}oBS%b(`ol>8u%Fa%h}L{Ac0>y zFoU0zP~73o#T)b1S;se*jW-vLpO$Y~KYqhlQ(kHD`gQ9zuHUd>%=!(c()F$}(6VmE z^qF^OZy1YD`D09`(%j~}c?+yIyCfRjPGf@=w&idQZ1u*Gu44F_QvDifht1`7(cLJ9 z+U~T9F29~iR?*^?cDSjBJv}N%b3b&_2iUn$lgj)mXMP{^> zb;mE4_oUA1O`Y4FI`_=R%d6J(q~5uAVPB@HH?yESv*6>*3GJS+HdUM07ngMCjw^9F zeevnn;xZ12&&|0Sm)Dm$qP^l;LRN?BIq_=3*lU^D9l1yII`fWAJ7wz`F{>xDti9sX z%+YNXebJe{(IdK}M|4a&THIOu?DVVAg?-WSUPHU#(8`Xfhn9R4J+41N$SUej7LwDw zJKA@2=t0b+{NAJ@Pj^z$shMYrK2Dm~ro5pMl2Q-lu+853_WF($J&C4c+1-ibdJ~Jf z6N`EhC$%ZBC8r+IJ)!H1Uv_!L>Ti^al-M@)*BT){r7z8Rq~wW`j;&A4Y@6Gcl;&-2 zZ)PnWcXuaE?n^fI#gFKXAJrW{s>6M>xwHA%maFlT`m%D5?0lkl=dlS--F+pi_*6=7 zW?6S;Sx@F1&?r9HyRdy>M|{Wjj;N2~3%^Pek}F962q8SWb>ZGgtqcEoqlvIT7#$3_ zRHR=5?IlS|l9eAOtCwW>>P_z}$uq2Y{A6;NHH`O!qiehHgoA^f-5Oso-T@D;2xw>( z4v+50?l7NTY} zdV(bvWTof7~6zR3lG81n?eoYMzA%3lO zlasn7k$%Q{Ca#_GDfX%C5HaX=j>75hq8>z*4bBGoCSVk!g z80m3#_>N8xf9A9%GQJha{TfkngX|Pj3i>jD=D5vncY~|AprF>~-rTq;zuM_2pi9_i z#Ul)FBhfho@3NSZ1ah8@E-4tWmP~DFwl!E9sht{Owij4KiHB@t{Uw!z`HH81q$4gC zU7kdeSYG)=lFZhZ=PDuzyQjQ}xY;kt?Sa%1NsfqFY+O_FTc*V*Zcj08CvBc&OE8U&;Fu>Y#aN%{(( zT{tRilhq|bRJ2>0=w6mFzceip$o!F;n%t5LT%cOAZG%-U#Ic=h`}{1;J{aaoct`P|F4l z9g@pst(9mj(jf`>X$0c(N<#xZ1Hf+(C08}I$xegfQmBgy^m8PLK`;iXBCKLvqsz^* zmPKT6W*Ukan_uU!TWs|Wjc$HWz|^dA*%%|&BhF%NXs|a~Y8oI5mGES8Qo0^^k5u^B zvV5fu3fuySdxc$CnE}VfpI44hOVBjK7rE+rL*80oZz9~`O-jGIVKbPPqMB3-L@wMf zMq?}N+~3|cmn>sOYu;Q;S>aHZc%BRCabtZwB)l-iGdS!pfmY*XzW;x;0$)01>jdTHrn9)M>vTd!R8JGuxeGXUNw@{-AJWC>LE5dAQOPhQlO&{ zs1W=c0mcjZJpuvw2V)FX!J{b+R)MXpHs#ph$*&MMacfd5(sRS{F!(J#o?y>c&&}yX zv;m2=7!T_u%KcP!Pk7@Z&{Zs4EZ1`yh z0l=gJUX2cil{V4UOlw~UCld6(3N!hf_I+wHfql2NETIS+lM!H!NAnRYV9V(w53*}c zD5um(jV|jp@D*cY1Ma+HBhA9T_{#ciR=Z6!LO2@ix)V8U0dQQ&eUa|M2JTcz6yD$r zY_a1w8(+v-*oNl{<*`Lo4>_J+=VoeG=6pBy&4xZ$8b}}OtqzHYBEJgLLD^Z#kY+B9 z=c`bT8159vBl2@7=TGh_aV-g z;ZdJ;#{s1W?RcC}cz+>OQEu?$N=E~nZpIqwbQo7HUu2XIJ+L`nq;lkd)}?I#Op&x5 z@y8G_1VMxGvw>o4q}(Fhz=Kvo1JQ$=5&DtIKo4O{8UmC?UbUcI=#$unTKlzu!-pHf z1MMyYwDZGL2J-b?#}9Tqr8F(E51+*Kdc?W<$ z0)5D3sord@uZ4q#hnh3kdlo?x&eP1M-#>D^3sLS({9NOEI)Zx%gdp1vh!3quaUX(C z_UQeoNqxvaO0?C~SnRfXX&}al>^JvMfZ+Yr{VD3VfVkQh^+1O*`!Jwi{1gXszfjRf z5D#^Z%MTq_tl|3^SG|hwH;Th_q(JxzTHdfxJtw7;$h(*bu7m3;FkBM0{9 zxTE2je_B+5`}@7{YI>(q5DqH5%KO!7_QZiHB#vD^Fj5yNKzQ@gNY(^5rdR`GTNI-9 zq%QEj?t2V*ioIs6P0Pr$dw?rH1~=i}J*gYiuA#zl(pZoNz_2<{o|!t8Wb=$%Z;*o2K4 zK%`-7z2Riez*7V}<6WtlDzuS(e`n{sRfQb=D~D&Rp$Ji}*rnetOcnNBhwml$9)xcz zeCu+cGE^t?dHzs(8U_#kfl6a45!{)9=ei0sknevEWs&^b`7Aw$P7p?|+bvL$v(+>m zSIFn#*KGQeC1BniPi{!Stk^{00#PqQV5Tp^BmFu1%afNqxglPCTZabjaxOL<2ccil zMg-ds@T4LhF}~e#Kl@d-`Wh##LFy^kqe5)xvF_K~TuvZzSlO7v@s+!gq6KL)5PJ_X zIbI<48iK)?!NWz2ycs^iu8c|JFBezEd=u^RDGoZy05UujZah)k@^RbI$dBW~jD1*p=6 zBGll*Gy;4sln~&5VFrh#*zz8UUywdV`CbB9kgR(zQL`Xj`ChsbJF>DCDwOZdRKno* z2?6|l1>nAu9R(!Xjh=zQp1zIXVc(aX$CNxB<2gXcX~1_Dy^K`d03gs>xBHdOMmNM_ z`LG6@->Z2N#=|o@V{;T-_ie5c+fUC6RVtf1{!PNHX$0f!!_Cnspx1w87*f@Tw{K{ zivw~vC%J;rfcq6Tk@BlT3_fWGPE`3ea0ut=KmflClCO|(I{poDKIDiX6b}&ai^ghX z5w;xa7cLuI;hF-cAlDpl!a~klEv5r-%*uHiKXoD7kzZ**Mgp~wizukl?yP3^lcO@ZwPS;K zX=|fsb6Xn38hQ)J+I^=^suW45ai+&`CWT*7EBO_63GRj8c?)Amitn=*)0E`<$6m_! zU@*j+le-!!&=P$g9%U6S;ZPmaT5S%S+plrf)L?0drw2+%5Bz$!(`~hLslUfTJe{fn z>^3ih^r(Xclyp%&q=DxlWV@~d|IY>Ai!Ze*xl7P5k;`8Z@LYK}VtWwaVuUUX9qht& zF=>ad12?x3x@1l8=m0MWrZ@B-$TfrsuF(&Yr0`nFJ@{V90AhcRV*gEGr_ROu{{G5S zB=HmA12H^>pF;n)?JOP4=jg`w~;G zs#0W9q-suQ|9T_ISNbcHG6i=^bId&15sdXtxL4qIp~-Cb>$5zVjMHDCDv>Y__ALGh zIpLz<(XRuql5gxP?B#A6Jn+CMI392QO}yx?fqI4w&Tm|0`T=&SV5y6KV4DcLbyJLF z515Ch0`DlbZ`rRKl_^+jg3DVq*6JkDueH_IJE25Eli2k$Id{@hz2ws*OazQ&W|!W)f=9%39AR$~Wmu))Ac$ZGnB-`TV4l+io@ zhj^54+&c+`JG*>?{;T4M(K%=AH#rL603qy?ZN4_nE zp|1=a_&G3WA+9oHXW-!fY!#riAD#H{j{TXwGw0@n90l?zfj0@i7V2sem}@13g*hk? zzXjYbU&1_2UgR{y2J90&8|2g<*UyD{5eg}b7$?tQsf&S76ExW<5Z38q@A*lr8c_NW zj0wJFWu6aG)Opanhduql-@|zyFy{`5jD6c1Jx{Nenn2I1G`lEitG z@3n9!P&ZHulo8+tSOqR04ZJD*^iH6$2$E2MNr=TEn2cZwf~g3G?a4xHL(qwu`>elz=yF2c#f0AGWxQjaYMs)m+LMfeT*&Yo9w{~Al;6XJQTO! z<1PeuBWOjyH~VhH?g3y5^Xr_n*20~j90%fLezn`VMXKlZXSx^2uyEvR@T>7)c2PWR zxWBu?pbuSL{!qBHlTQ-Vi$JR$U)m=*QF5%jg&cTc152m$862L4;0ORX8^1z91}-;< zQ#*E6Am%`<9)S}<1A zi`bip@mtqueCz9wqi`B_r6b_ESQvVTTr}b9Bp*>cKx?rJlP7*r3zoWQ2M+ciu;L7I z<(8XVF5P0|ZtT7X!MzB0y3vCjJe%o6jIZ_m*o*mQXiXO%A3(4d!Go;)%lY7WkA9h= zUJdK_x$oqclVc23xRme}=q>iw?}`ayqyLo|gWloSqu`rxbJ9At`d@#WKe*ybK!7?cK7U90BE-Y^R^gW7rr}09 zh{I48UM7Hpd=3wPhp;&V0g50SgG+?Q_~9uo*E~Tv>ICxcu5b0EhiD$b@u#~k8^{Jl zCSOg=EpEmvp|$)56OxvB7e;6LpBQZ_E#lz#J(M219>PA;t6!|+LbzN{V_#Xvf zUB-B#ClMGd1834Q@00|RO&<2%nLsi;81bQ4X@S85ClJnfyJdM3r9O**#~Qx()JTll zLGsBp*@1j2v6Z_huS+B450cJE{^HmY#TCGU{Z1H}tnE@Jl8@CMzB11to97X1MXpB? z!_6m$l%Z=vG0y=FKSTL$B0!btBp4I8+5N|Wyc;QbMC0xU>r@$9_0|nWCyL8M-3a(` z#Wy5RWKsFhs}j8KL$1fXo#~{2ly-HelUhaTaa7@F2u`A43fX4I0Ox5Mmds(4KL)Od zlGPEqxOW5p8Q$$##6(`~>dYbuYI3BjE0;_rse4cy`1vus14GV$2m@yDYDSTJru;{} zxkK``M7>SAA-?E+V-(3GRo>r?BIDDzR8c{H8+en|22Q5o$Rn!%v{(Sex)X%>A9raGzx$|s?pr{SMPC14WXI=f$yrB3PEpHH6Cki*_d zlZkNw`m`J*TG1@K5gb9Ya4X%5kKAbYAvWA-NOwPUSUUl*3Gc*rS;i6#>H6gqvX_tw zZ`mEhKKdn`VG)2TsFP}KE~~x1(ScX<{6ase=8K7`y7%fGWSU~E&Kot2+!@UWeS;&v zLh!YB`!tf}xdFH-{{K6G@bwBBm6o8rRCRD;qB~J?ye14UpX$J!YTWR1ez{Z;J!Bnh zK+nCJ2i1LOkw*}4|9%v){RsA<#5@_k379{^Wv!98e`1d3*YTPXOhXSquPYja7|7m& zf4~@b7n5}L5#aVg*O6l4)fzDL(gVmoxvOk8nMX$QO`QeJ^I$LIl@fjw*VG{S!?rcr zp`KygWS8hx@5wo2{L0fS&LG~)Wzl2{Ar^hK{}F3Ao*2GaOd z*hI6utLKuO4DS2fBRAQtQ1_r#(FW1>=RkOeuIu1j(ySmSyfGCdF6kIfbqYH0w*rW3 z5FGQCR1l-*zd!`oV}tGeK?*$5Z$`npPk4_Cxom#*r z`*~i&Iq_tYW87yD13iP&!wLj(`Z~`W*?|H4V{txH<0nmEDYvXZf-^m+6pmfq?R&CoP=tM-3)#1y0AaN?du6jc*X% z%Fnl#~s?9E^)$r&m$HeQP9yP6u%C(+cwK42%*926c*9kn_W_a zKi0Ci>`u$7rHhu7&9y9^ZCPHnhW-u3<10NMF}!g3l@99;I*ZHzR1e43BG3tbI1-IQ z-_QG@%1;*|X299tr|zJ$i@y+uax8zMZ+l-^Ofoe*ke~7T7Zc+|H<$x1)Abhk0X@Wo zH8`IG!6OJxBH(ws>xjkSY!>hMD)?`=pJD@lC9oc`cr>dKK?#C85UfD39)X15Apm|A zT*cj#pD#~gV<&1(f#d zraPQsqg|RwKLr|?TX2;dypAO#mxOuuFChm!{VF9%|E(&vKTHUZ+&}ffsrySGEIl;w z$jm2Z_87*r>ON5#+H@U?qhXz4M{3yJr-yp=9`XdFR>J?(Ic(ay~>Ew!c{W6kA?(yEYjBL~{AtbtARCIl@ zjMOPdRTC217arBGL+)OPX*o kKipyxt{e20WaafFf-p^M8Kt~Fk{~o`Et8bjClY}F54<}Fh5!Hn delta 14028 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

oEPmmimxN>06vKr>H}1P^YK}`8lN|+ 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 I5(&Wn4+EME&;S4c delta 10551 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 np.ndarray: @@ -18,15 +38,9 @@ def embed_findings(findings: list[dict]) -> np.ndarray: Returns: np.ndarray of shape (n, 384) """ - if MODEL is None: - raise RuntimeError( - "sentence-transformers is not installed. " - "Install it using: pip install sentence-transformers" - ) - texts = [ f"{getattr(finding, 'title', '')} {getattr(finding, 'description', '')}" for finding in findings ] - return MODEL.encode(texts, convert_to_numpy=True) + return _get_model().encode(texts, convert_to_numpy=True) diff --git a/backend/app/ml/fp_predictor.py b/backend/app/ml/fp_predictor.py index 54e6085..5c498db 100644 --- a/backend/app/ml/fp_predictor.py +++ b/backend/app/ml/fp_predictor.py @@ -6,6 +6,7 @@ try: import torch from transformers import AutoModel, AutoTokenizer + TORCH_AND_TRANSFORMERS_AVAILABLE = True except ImportError: torch = None diff --git a/backend/tests/conftest.py b/backend/tests/conftest.py index 0a86ebf..0aa3e14 100644 --- a/backend/tests/conftest.py +++ b/backend/tests/conftest.py @@ -1,9 +1,11 @@ import sys from unittest.mock import MagicMock + class DummyTensor: pass + # Mock out heavy ML libraries to allow running tests without them mock_torch = MagicMock() mock_torch.Tensor = DummyTensor @@ -11,4 +13,3 @@ class DummyTensor: sys.modules["transformers"] = MagicMock() sys.modules["sentence_transformers"] = MagicMock() - diff --git a/backend/tests/test_job_endpoints.py b/backend/tests/test_job_endpoints.py index 04a5973..c263cad 100644 --- a/backend/tests/test_job_endpoints.py +++ b/backend/tests/test_job_endpoints.py @@ -276,4 +276,3 @@ def test_list_jobs_invalid_limit_too_high(self): def test_list_jobs_invalid_offset(self): res = client.get("/jobs?offset=-1") assert res.status_code == 422 - diff --git a/frontend/src/app/components/dashboard/RecentScans.tsx b/frontend/src/app/components/dashboard/RecentScans.tsx index 7bb36a7..0e06aab 100644 --- a/frontend/src/app/components/dashboard/RecentScans.tsx +++ b/frontend/src/app/components/dashboard/RecentScans.tsx @@ -17,7 +17,11 @@ export function RecentScans({ recentJobs, onClearRecents }: RecentScansProps) { const navigate = useNavigate(); const formatTimestamp = (timestamp: string) => { - const date = new Date(timestamp); + let formattedStr = timestamp; + if (timestamp && !timestamp.endsWith("Z") && !timestamp.includes("+")) { + formattedStr = timestamp.replace(" ", "T") + "Z"; + } + const date = new Date(formattedStr); return new Intl.DateTimeFormat("en-US", { month: "short", day: "numeric", diff --git a/frontend/src/app/hooks/useRecentJobs.ts b/frontend/src/app/hooks/useRecentJobs.ts index 53c24be..9b3ad74 100644 --- a/frontend/src/app/hooks/useRecentJobs.ts +++ b/frontend/src/app/hooks/useRecentJobs.ts @@ -27,6 +27,23 @@ function getClearedJobIds(): string[] { } } +function mapBackendStatus(status: string): UiJobStatus { + switch (status) { + case "completed": + return "completed"; + case "scanning": + return "running"; + case "failed": + case "aborted": + return "failed"; + case "pending": + case "queued": + return "pending"; + default: + return "pending"; + } +} + export function useRecentJobs() { const navigate = useNavigate(); const [recentJobs, setRecentJobs] = useState([]); @@ -40,7 +57,7 @@ export function useRecentJobs() { .map((j) => ({ id: j.job_id, repoName: j.project_name, - status: j.status as UiJobStatus, + status: mapBackendStatus(j.status), timestamp: j.created_at, duration: "-", findingsCount: j.finding_count ?? 0, diff --git a/frontend/src/app/lib/api.ts b/frontend/src/app/lib/api.ts index 76d2a5e..edf17c1 100644 --- a/frontend/src/app/lib/api.ts +++ b/frontend/src/app/lib/api.ts @@ -45,11 +45,11 @@ export type BackendFinding = { }; reachability?: { - reachable?: boolean; - reason?: string; -}; + reachable?: boolean; + reason?: string; + }; -features?: Record; + features?: Record; confidence?: number; code?: string; suggested_fix?: string; @@ -101,10 +101,18 @@ export async function scanRepoUrl( return (await res.json()) as ScanInitResponse; } -export async function getJobFindings(jobId: string): Promise { +export type JobFindingsResponse = { + job_id: string; + project_name?: string | null; + raw_finding_count: number; + finding_count: number; + findings: BackendFinding[]; +}; + +export async function getJobFindings(jobId: string): Promise { const res = await fetch(`${API_BASE}/jobs/${jobId}/findings`); if (!res.ok) throw new Error(await res.text()); - return (await res.json()) as BackendFinding[]; + return (await res.json()) as JobFindingsResponse; } export async function labelFinding( diff --git a/frontend/src/app/pages/findings.tsx b/frontend/src/app/pages/findings.tsx index 2f91202..61b2df3 100644 --- a/frontend/src/app/pages/findings.tsx +++ b/frontend/src/app/pages/findings.tsx @@ -174,10 +174,8 @@ export function Findings() { return; } - const response: any = await getJobFindings(jobId); - const actualFindings = Array.isArray(response) - ? response - : (response.findings || response.data || []); + const response = await getJobFindings(jobId); + const actualFindings = response.findings || []; const projectName = response.project_name || (storedScan?.job_id === jobId ? storedScan.project_name : "Unknown Project"); diff --git a/frontend/src/app/pages/fix.tsx b/frontend/src/app/pages/fix.tsx index 53e16a2..99327cb 100644 --- a/frontend/src/app/pages/fix.tsx +++ b/frontend/src/app/pages/fix.tsx @@ -88,11 +88,9 @@ export function Fix() { const response = await fix(scan.job_id, findingIds); setBackendFixes(response.fixes || []); - const findingsResponse: any = await getJobFindings(scan.job_id); + const findingsResponse = await getJobFindings(scan.job_id); - const actualFindings = Array.isArray(findingsResponse) - ? findingsResponse - : findingsResponse.findings ?? []; + const actualFindings = findingsResponse.findings || []; setFindings( actualFindings.map((bf: any) =>