agentic-qe 3.15.6 → 3.15.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/skills-manifest.json +1 -1
- package/CHANGELOG.md +141 -0
- package/README.md +2 -0
- package/assets/skills/skills-manifest.json +1 -1
- package/dist/cli/bundle.js +8 -6
- package/dist/cli/chunks/adapter-PEOUNYXJ.js +2 -0
- package/dist/cli/chunks/{agent-booster-wasm-SY7UCLBL.js → agent-booster-wasm-OS5G7KMQ.js} +2 -2
- package/dist/cli/chunks/{agent-handler-KAMYBU3S.js → agent-handler-PI4I7PME.js} +2 -2
- package/dist/cli/chunks/{agent-memory-branch-2CAW3KUM.js → agent-memory-branch-J7TXHX4U.js} +2 -2
- package/dist/cli/chunks/aqe-learning-engine-DHKZI5RX.js +2 -0
- package/dist/cli/chunks/{arena-QCCVIOAH.js → arena-FXESDCFR.js} +4 -4
- package/dist/cli/chunks/{arena-4OFLJ3R2.js → arena-OWUGXKNT.js} +2 -2
- package/dist/cli/chunks/{audit-RBDQJQJB.js → audit-EPAWLYIZ.js} +3 -3
- package/dist/cli/chunks/base-QZWK3D5P.js +2 -0
- package/dist/cli/chunks/{better-sqlite3-5JRACCDQ.js → better-sqlite3-IYVR5EQY.js} +2 -2
- package/dist/cli/chunks/{brain-handler-W4QIIRT4.js → brain-handler-3W2E6TC6.js} +3 -3
- package/dist/cli/chunks/{branch-enumerator-IBNGI572.js → branch-enumerator-HU7VACJ4.js} +2 -2
- package/dist/cli/chunks/{browser-GMSCVAOI.js → browser-72XOR6E2.js} +2 -2
- package/dist/cli/chunks/browser-workflow-ITPX72RX.js +2 -0
- package/dist/cli/chunks/{chunk-CR66HNAE.js → chunk-2423JAA5.js} +1 -1
- package/dist/cli/chunks/{chunk-LAY7NCQK.js → chunk-24CENUT4.js} +3 -3
- package/dist/cli/chunks/{chunk-PEMSXSP2.js → chunk-2AYBYXOA.js} +2 -2
- package/dist/cli/chunks/{chunk-TUDENMAE.js → chunk-2E3XWKEU.js} +2 -2
- package/dist/cli/chunks/{chunk-KIDOBLUO.js → chunk-2RJYA6WK.js} +2 -2
- package/dist/cli/chunks/{chunk-2IWPJUVV.js → chunk-2YVJ5OUL.js} +5 -5
- package/dist/cli/chunks/{chunk-34MDMFET.js → chunk-34JLY3U6.js} +2 -2
- package/dist/cli/chunks/{chunk-SV5BUYHH.js → chunk-3JD2USUH.js} +2 -2
- package/dist/cli/chunks/{chunk-EF5UHDCG.js → chunk-3RM46XFP.js} +1 -1
- package/dist/cli/chunks/{chunk-7XTANLTN.js → chunk-44DPYNPE.js} +1 -1
- package/dist/cli/chunks/{chunk-ONPPBLRB.js → chunk-4DIZ5BT6.js} +2 -2
- package/dist/cli/chunks/{chunk-22OZIJAD.js → chunk-4G2VNW4C.js} +2 -2
- package/dist/cli/chunks/{chunk-LJCEDTUM.js → chunk-56ZKQYZY.js} +3 -3
- package/dist/cli/chunks/{chunk-HOEWMEF2.js → chunk-5KCBX225.js} +2 -2
- package/dist/cli/chunks/{chunk-V3OLS2NG.js → chunk-5KS7HA37.js} +2 -2
- package/dist/cli/chunks/{chunk-MQCTLTGE.js → chunk-5PBRBS7D.js} +2 -2
- package/dist/cli/chunks/{chunk-TVLOED6O.js → chunk-5Q22XPTH.js} +2 -2
- package/dist/cli/chunks/{chunk-B7RHBKHL.js → chunk-634D2ENF.js} +2 -2
- package/dist/cli/chunks/{chunk-7TVIX4WL.js → chunk-6AYRAOCA.js} +2 -2
- package/dist/cli/chunks/{chunk-4KOVHQXK.js → chunk-6BO3WCK7.js} +2 -2
- package/dist/cli/chunks/{chunk-5HAPS6VD.js → chunk-6FEQ73BF.js} +2 -2
- package/dist/cli/chunks/{chunk-FQ5N666N.js → chunk-6JT73S5B.js} +1 -1
- package/dist/cli/chunks/{chunk-6MXAJBEA.js → chunk-6OS7HREG.js} +1 -1
- package/dist/cli/chunks/{chunk-6R3FBFCJ.js → chunk-6PKCQXEW.js} +2 -2
- package/dist/cli/chunks/{chunk-DQNUPEY5.js → chunk-7EX4DEQR.js} +2 -2
- package/dist/cli/chunks/{chunk-KCB6P463.js → chunk-7UCVYYWL.js} +2 -2
- package/dist/cli/chunks/{chunk-RLB7K7QP.js → chunk-AAA4SHEG.js} +1 -1
- package/dist/cli/chunks/{chunk-ITIJ23K2.js → chunk-AXO7OOOA.js} +2 -2
- package/dist/cli/chunks/{chunk-6RDVY26I.js → chunk-B7M323VL.js} +2 -2
- package/dist/cli/chunks/{chunk-EJ4KZFZN.js → chunk-BB7OLQKO.js} +1 -1
- package/dist/cli/chunks/{chunk-5NC7QEJ6.js → chunk-BTIBXGVQ.js} +4 -4
- package/dist/cli/chunks/{chunk-RD5BYLN7.js → chunk-BTYKGVJ5.js} +1 -1
- package/dist/cli/chunks/{chunk-YXU35GGD.js → chunk-C2CUPJGR.js} +1 -1
- package/dist/cli/chunks/{chunk-XFPQIWEH.js → chunk-C2MDBBFF.js} +3 -3
- package/dist/cli/chunks/{chunk-QLKUCMZC.js → chunk-CG5DZCOZ.js} +1 -1
- package/dist/cli/chunks/{chunk-YLNYPQDR.js → chunk-CIFWOMNX.js} +1 -1
- package/dist/cli/chunks/{chunk-ORBODZSO.js → chunk-CWPRU7ZI.js} +2 -2
- package/dist/cli/chunks/{chunk-WKDWRRDT.js → chunk-CXTJ47QS.js} +2 -2
- package/dist/cli/chunks/{chunk-SOSJWM3E.js → chunk-DCJW2DPL.js} +4 -4
- package/dist/cli/chunks/{chunk-GVRFSXY6.js → chunk-DGK6GQMO.js} +2 -2
- package/dist/cli/chunks/{chunk-X33F7NXH.js → chunk-DVPGBDBP.js} +3 -3
- package/dist/cli/chunks/chunk-EB2PP6X2.js +2 -0
- package/dist/cli/chunks/{chunk-HZFK2Z2Z.js → chunk-ECSLJJOQ.js} +1 -1
- package/dist/cli/chunks/{chunk-JCE76MPP.js → chunk-ED32XJ5R.js} +2 -2
- package/dist/cli/chunks/{chunk-ULCHPPW2.js → chunk-EDU72RTW.js} +1 -1
- package/dist/cli/chunks/{chunk-ZOUEQ6DL.js → chunk-EL75G2A3.js} +1 -1
- package/dist/cli/chunks/{chunk-GNYOHZVV.js → chunk-EV2BYY6T.js} +1 -1
- package/dist/cli/chunks/{chunk-RUTO67PT.js → chunk-F62EKVVC.js} +2 -2
- package/dist/cli/chunks/{chunk-IVJIHZSM.js → chunk-FTTFJ7SJ.js} +1 -1
- package/dist/cli/chunks/{chunk-NYS2GUNO.js → chunk-FVBFASOD.js} +2 -2
- package/dist/cli/chunks/{chunk-5DH5QI7G.js → chunk-G762PEFO.js} +3 -3
- package/dist/cli/chunks/{chunk-JPJEAK4G.js → chunk-G7YTZTGU.js} +1 -1
- package/dist/cli/chunks/{chunk-5VUIXDY2.js → chunk-GY2SAIXP.js} +2 -2
- package/dist/cli/chunks/{chunk-7XUB7U6Z.js → chunk-H4WHDFB5.js} +2 -2
- package/dist/cli/chunks/{chunk-72MQCZSM.js → chunk-HLZATDD2.js} +2 -2
- package/dist/cli/chunks/{chunk-AX26QJ6T.js → chunk-HPG7354V.js} +2 -2
- package/dist/cli/chunks/{chunk-7SAMMQVS.js → chunk-HSDOOFV7.js} +1 -1
- package/dist/cli/chunks/{chunk-K55EAWZ5.js → chunk-HTWIGQL4.js} +2 -2
- package/dist/cli/chunks/{chunk-BXATKI5S.js → chunk-HXBAQKMH.js} +2 -2
- package/dist/cli/chunks/{chunk-46HBVDMU.js → chunk-HZFT3P5B.js} +1 -1
- package/dist/cli/chunks/{chunk-RFDFET3O.js → chunk-I7H4IP7T.js} +2 -2
- package/dist/cli/chunks/{chunk-AJT3XDRD.js → chunk-IARSGAG7.js} +2 -2
- package/dist/cli/chunks/{chunk-TL5GV3PR.js → chunk-IC2WSSD5.js} +3 -3
- package/dist/cli/chunks/{chunk-TLUIO37P.js → chunk-ICPALF4Q.js} +2 -2
- package/dist/cli/chunks/{chunk-ZSBD4FUX.js → chunk-IWQQIXHO.js} +2 -2
- package/dist/cli/chunks/{chunk-AUOSHM63.js → chunk-IYQ7XNE5.js} +2 -2
- package/dist/cli/chunks/{chunk-RHIQ6QO5.js → chunk-J26GADQE.js} +281 -281
- package/dist/cli/chunks/{chunk-AUN4FG7V.js → chunk-J43DV3ME.js} +1 -1
- package/dist/cli/chunks/{chunk-ALCIUWFC.js → chunk-JFPXCQNP.js} +1 -1
- package/dist/cli/chunks/{chunk-R363XXGH.js → chunk-JK6B3ULP.js} +2 -2
- package/dist/cli/chunks/{chunk-7VTKR44N.js → chunk-JPHDMHFG.js} +2 -2
- package/dist/cli/chunks/{chunk-FOJRPEIP.js → chunk-JVYPXW6Y.js} +2 -2
- package/dist/cli/chunks/{chunk-ZUTFHGEO.js → chunk-JY4AIEZ7.js} +1 -1
- package/dist/cli/chunks/{chunk-47Q7JL3V.js → chunk-JY4WLN3K.js} +2 -2
- package/dist/cli/chunks/{chunk-IEPWO4XP.js → chunk-JYXOFN3E.js} +2 -2
- package/dist/cli/chunks/{chunk-2CIDFR2H.js → chunk-K7W55B7Q.js} +2 -2
- package/dist/cli/chunks/{chunk-D5N2O5EH.js → chunk-KPOPBUUJ.js} +2 -2
- package/dist/cli/chunks/{chunk-OQ4S6B7P.js → chunk-LDXQRNTT.js} +1 -1
- package/dist/cli/chunks/{chunk-6T6AHVLF.js → chunk-LDZWIV2O.js} +1 -1
- package/dist/cli/chunks/{chunk-A7ANPS4E.js → chunk-LGBN7TKC.js} +2 -2
- package/dist/cli/chunks/{chunk-X2DR27AY.js → chunk-LMEU64TR.js} +2 -2
- package/dist/cli/chunks/{chunk-GI5HWS4H.js → chunk-LP4AS2E4.js} +1 -1
- package/dist/cli/chunks/{chunk-VVF337SV.js → chunk-LQOVA4YX.js} +2 -2
- package/dist/cli/chunks/{chunk-KYVIOC3C.js → chunk-LVEX4GID.js} +2 -2
- package/dist/cli/chunks/{chunk-BO7UFNYV.js → chunk-M63QB466.js} +2 -2
- package/dist/cli/chunks/{chunk-UHHMAKPE.js → chunk-MDC4G323.js} +1 -1
- package/dist/cli/chunks/{chunk-4CLDYT36.js → chunk-MHZPC4HJ.js} +2 -2
- package/dist/cli/chunks/{chunk-24ZSGYC6.js → chunk-MJJC6HUK.js} +1 -1
- package/dist/cli/chunks/{chunk-ZL5LJT7D.js → chunk-MKFQNCXI.js} +2 -2
- package/dist/cli/chunks/{chunk-XZ46CI35.js → chunk-MMXG3LL6.js} +2 -2
- package/dist/cli/chunks/{chunk-OPDZBRIL.js → chunk-MNCF643K.js} +2 -2
- package/dist/cli/chunks/{chunk-CEXNW5TR.js → chunk-MNZFEIE5.js} +1 -1
- package/dist/cli/chunks/{chunk-L4D3TPFP.js → chunk-MQ6OF6DU.js} +1 -1
- package/dist/cli/chunks/{chunk-UB6DQGWM.js → chunk-MRHM4COP.js} +2 -2
- package/dist/cli/chunks/{chunk-CLAMMGY3.js → chunk-N4PMPSJJ.js} +2 -2
- package/dist/cli/chunks/{chunk-XQ53PZEF.js → chunk-NZQPP533.js} +3 -3
- package/dist/cli/chunks/{chunk-FU7LNUD7.js → chunk-OA4GR3EZ.js} +2 -2
- package/dist/cli/chunks/{chunk-ORFL3YXB.js → chunk-OJEZNLB6.js} +2 -2
- package/dist/cli/chunks/{chunk-5LST62QR.js → chunk-ONVALAZN.js} +2 -2
- package/dist/cli/chunks/{chunk-DA7DGDTI.js → chunk-PEKDSJBC.js} +2 -2
- package/dist/cli/chunks/{chunk-3DJNKNBR.js → chunk-PG64YV6C.js} +57 -57
- package/dist/cli/chunks/{chunk-2ZTWPMTK.js → chunk-PQV7E7XH.js} +2 -2
- package/dist/cli/chunks/chunk-PTK66HEY.js +2 -0
- package/dist/cli/chunks/{chunk-CZBIREL5.js → chunk-PUECC4WI.js} +2 -2
- package/dist/cli/chunks/{chunk-JYKQVYX2.js → chunk-PXZKPUW6.js} +2 -2
- package/dist/cli/chunks/{chunk-I7WAW7TM.js → chunk-PYHYOKYT.js} +2 -2
- package/dist/cli/chunks/{chunk-LCCTJ2PC.js → chunk-PZG3542B.js} +2 -2
- package/dist/cli/chunks/{chunk-F7A2UBZO.js → chunk-Q2T5FXEA.js} +2 -2
- package/dist/cli/chunks/{chunk-PS6WFCA4.js → chunk-QJE6ZW2X.js} +2 -2
- package/dist/cli/chunks/{chunk-LZWJ5BMP.js → chunk-QNQSM2OG.js} +2 -2
- package/dist/cli/chunks/{chunk-QLYO3H7E.js → chunk-QQT6QENQ.js} +2 -2
- package/dist/cli/chunks/{chunk-VCONCVSY.js → chunk-QVG4ZDXX.js} +2 -2
- package/dist/cli/chunks/{chunk-NMY4KTWA.js → chunk-QWLTHFZW.js} +2 -2
- package/dist/cli/chunks/{chunk-NBUXM5X6.js → chunk-RCYLCA7E.js} +2 -2
- package/dist/cli/chunks/{chunk-P7DXVL2S.js → chunk-REEIFA6A.js} +2 -2
- package/dist/cli/chunks/{chunk-5MT7DMD7.js → chunk-RNYX4CPI.js} +2 -2
- package/dist/cli/chunks/{chunk-HAN4MS5T.js → chunk-RORZ5O5Z.js} +2 -2
- package/dist/cli/chunks/{chunk-ZCP4P6O2.js → chunk-RRPYWBFX.js} +2 -2
- package/dist/cli/chunks/{chunk-3NJ7O3OH.js → chunk-RXAFLK34.js} +2 -2
- package/dist/cli/chunks/{chunk-VAYZ5QIE.js → chunk-SQHLC6I5.js} +1 -1
- package/dist/cli/chunks/{chunk-Q2RBOC7V.js → chunk-SSP2B2WR.js} +2 -2
- package/dist/cli/chunks/{chunk-CCL436IU.js → chunk-SX2YSHE7.js} +14 -6
- package/dist/cli/chunks/{chunk-ZTB32K5N.js → chunk-T3ZDVU6F.js} +3 -3
- package/dist/cli/chunks/{chunk-624QRKQX.js → chunk-T6W5APYP.js} +1 -1
- package/dist/cli/chunks/{chunk-BAYGQRNP.js → chunk-TU4LIIOP.js} +2 -2
- package/dist/cli/chunks/{chunk-L2TDHJR3.js → chunk-UBYCR3O4.js} +2 -2
- package/dist/cli/chunks/{chunk-JAPBSSFY.js → chunk-UCLN6AME.js} +1 -1
- package/dist/cli/chunks/{chunk-66NW3ZB4.js → chunk-UIYKR2SA.js} +2 -2
- package/dist/cli/chunks/{chunk-BIXRTOH3.js → chunk-UUHIEM2M.js} +3 -3
- package/dist/cli/chunks/{chunk-ELI4GDQO.js → chunk-UY3REQOK.js} +2 -2
- package/dist/cli/chunks/{chunk-BUTGIVKW.js → chunk-V2SAEMZY.js} +1 -1
- package/dist/cli/chunks/{chunk-6WOZUSSN.js → chunk-V5NGBQAQ.js} +2 -2
- package/dist/cli/chunks/{chunk-7TJZDRDU.js → chunk-VCA6YYII.js} +1 -1
- package/dist/cli/chunks/chunk-VJRZFWR5.js +2 -0
- package/dist/cli/chunks/{chunk-5GIJU2ZY.js → chunk-VKPKYMCT.js} +2 -2
- package/dist/cli/chunks/{chunk-XPB5BVU6.js → chunk-VNW5Q2CX.js} +2 -2
- package/dist/cli/chunks/{chunk-7QVPMH25.js → chunk-VUFRTGML.js} +2 -2
- package/dist/cli/chunks/{chunk-MP3FSUNB.js → chunk-W4X2VTIY.js} +2 -2
- package/dist/cli/chunks/{chunk-GWM4M5NF.js → chunk-WTLIEBDH.js} +1 -1
- package/dist/cli/chunks/{chunk-QS5KZYUZ.js → chunk-WUV5RZUI.js} +2 -2
- package/dist/cli/chunks/{chunk-HEGGV2PT.js → chunk-WXI2STKQ.js} +2 -2
- package/dist/cli/chunks/{chunk-GFB6BZWU.js → chunk-XEWXYGJI.js} +2 -2
- package/dist/cli/chunks/{chunk-NHRF3V4B.js → chunk-XNSQZ3O7.js} +2 -2
- package/dist/cli/chunks/{chunk-4POOJYXA.js → chunk-XTJMY3KS.js} +1 -1
- package/dist/cli/chunks/{chunk-LMAEMVPA.js → chunk-XXAVQACL.js} +1 -1
- package/dist/cli/chunks/{chunk-RV6HSMKJ.js → chunk-Y4SAWE45.js} +1 -1
- package/dist/cli/chunks/{chunk-DLSFT6PO.js → chunk-Y6A46M3B.js} +2 -2
- package/dist/cli/chunks/{chunk-5UPIL62W.js → chunk-YDZJWDR6.js} +3 -3
- package/dist/cli/chunks/{chunk-F3KS3TAB.js → chunk-YFOBQSOW.js} +2 -2
- package/dist/cli/chunks/{chunk-XBEI2JBA.js → chunk-YK3NOC2R.js} +2 -2
- package/dist/cli/chunks/{chunk-MQTA6KIO.js → chunk-YUC7RJGR.js} +1 -1
- package/dist/cli/chunks/{chunk-A74J23QB.js → chunk-Z3VJLWRR.js} +2 -2
- package/dist/cli/chunks/{chunk-YNG7E26C.js → chunk-ZLVQSEZK.js} +2 -2
- package/dist/cli/chunks/{chunk-6HWARQWV.js → chunk-ZRLNACPY.js} +2 -2
- package/dist/cli/chunks/{chunk-XBFQJZWX.js → chunk-ZTMZFF25.js} +2 -2
- package/dist/cli/chunks/chunk-ZUMDDMDE.js +3 -0
- package/dist/cli/chunks/{ci-GEJCXMBK.js → ci-5HEXJZ2C.js} +2 -2
- package/dist/cli/chunks/{ci-config-2ZVV4OXL.js → ci-config-WU4NPDAM.js} +2 -2
- package/dist/cli/chunks/{ci-output-E45OGVPR.js → ci-output-BJQVXX5E.js} +2 -2
- package/dist/cli/chunks/{circuit-breaker-X73ITYZC.js → circuit-breaker-3BMGTQCB.js} +2 -2
- package/dist/cli/chunks/{claude-flow-setup-W4PPH46C.js → claude-flow-setup-GVDGJWMU.js} +2 -2
- package/dist/cli/chunks/client-S7GNYTZ5.js +2 -0
- package/dist/cli/chunks/{cline-installer-NUEPMWDE.js → cline-installer-V4MRGWVA.js} +2 -2
- package/dist/cli/chunks/{code-6WQHBS7G.js → code-A3TGQPEO.js} +3 -3
- package/dist/cli/chunks/{code-index-extractor-BXQIFIFT.js → code-index-extractor-YJQSYWD3.js} +2 -2
- package/dist/cli/chunks/{codex-installer-Z337R2KH.js → codex-installer-7N7UQPAH.js} +2 -2
- package/dist/cli/chunks/{completions-F5DMYFHV.js → completions-PPGVYLZS.js} +2 -2
- package/dist/cli/chunks/{complexity-analyzer-W2SYPZDI.js → complexity-analyzer-XZTFLYV5.js} +2 -2
- package/dist/cli/chunks/{continuedev-installer-ZCHUIFTN.js → continuedev-installer-Z5I57RAH.js} +2 -2
- package/dist/cli/chunks/{copilot-installer-M5JNODXF.js → copilot-installer-F5YZ6BHB.js} +2 -2
- package/dist/cli/chunks/core-handlers-CUEPOQIO.js +2 -0
- package/dist/cli/chunks/{cost-tracker-LSYTHBHV.js → cost-tracker-GO33ZQAP.js} +2 -2
- package/dist/cli/chunks/{coverage-PGMRS5SS.js → coverage-GSHKLY74.js} +3 -3
- package/dist/cli/chunks/cross-domain-router-CXN5QFEV.js +2 -0
- package/dist/cli/chunks/{cursor-installer-XPUA73UW.js → cursor-installer-JJ7IVJZB.js} +2 -2
- package/dist/cli/chunks/daemon-3DQCKRYO.js +10 -0
- package/dist/cli/chunks/{daemon-ITKDIYMW.js → daemon-IRL7QRNE.js} +3 -3
- package/dist/cli/chunks/{dag-attention-scheduler-T55AXLD6.js → dag-attention-scheduler-ORXSUHPA.js} +2 -2
- package/dist/cli/chunks/{detect-DR7J6K4O.js → detect-RHU62KRI.js} +2 -2
- package/dist/cli/chunks/{dist-node-LAJJBOUT.js → dist-node-3VKV4Z6C.js} +2 -2
- package/dist/cli/chunks/{domain-handler-OMSHCRMK.js → domain-handler-SFIML4FK.js} +2 -2
- package/dist/cli/chunks/{domain-plugins-EQXSKC5K.js → domain-plugins-CJ4FA3OC.js} +2 -2
- package/dist/cli/chunks/{domain-transfer-FKRAGVSW.js → domain-transfer-BCRKPCAA.js} +2 -2
- package/dist/cli/chunks/dream-5AUNJW24.js +2 -0
- package/dist/cli/chunks/{embed-and-insert-pattern-JZFPCNL3.js → embed-and-insert-pattern-VL3HFLPV.js} +2 -2
- package/dist/cli/chunks/{eval-JSNNASBW.js → eval-GGKRI4P5.js} +2 -2
- package/dist/cli/chunks/{experience-capture-middleware-UPD3IZBK.js → experience-capture-middleware-F72TIRQY.js} +3 -3
- package/dist/cli/chunks/{fast-paths-YNMIBS2E.js → fast-paths-7KOOF3MA.js} +2 -2
- package/dist/cli/chunks/{feature-flags-SRLXDKBI.js → feature-flags-FNHBTHBH.js} +2 -2
- package/dist/cli/chunks/{feature-flags-VIR7O4L7.js → feature-flags-IOZEWWFU.js} +2 -2
- package/dist/cli/chunks/file-discovery-AYWF357I.js +2 -0
- package/dist/cli/chunks/{fleet-K2ED46EL.js → fleet-QX5KXTRC.js} +3 -3
- package/dist/cli/chunks/{gnn-wrapper-QCU4ZRYW.js → gnn-wrapper-OH2DOQP7.js} +2 -2
- package/dist/cli/chunks/{heartbeat-handler-YYQI4WZM.js → heartbeat-handler-W67NXTNE.js} +4 -4
- package/dist/cli/chunks/heartbeat-scheduler-7ZIDVXIP.js +2 -0
- package/dist/cli/chunks/hnsw-adapter-P77OC7FM.js +2 -0
- package/dist/cli/chunks/hnsw-index-3LBOTQAW.js +2 -0
- package/dist/cli/chunks/{hnsw-legacy-bridge-C5TJSWTZ.js → hnsw-legacy-bridge-6MLLOGOE.js} +2 -2
- package/dist/cli/chunks/{hnswlib-node-SE3MJJYS.js → hnswlib-node-4UDISJ3G.js} +2 -2
- package/dist/cli/chunks/{hooks-C572SRDH.js → hooks-NOQJWQ4P.js} +10 -10
- package/dist/cli/chunks/hybrid-backend-LOM54PDD.js +2 -0
- package/dist/cli/chunks/{hypergraph-engine-35A6G3M5.js → hypergraph-engine-2OD3APVP.js} +2 -2
- package/dist/cli/chunks/{hypergraph-handler-U2756CWI.js → hypergraph-handler-5AZGMBUM.js} +3 -3
- package/dist/cli/chunks/impact-analyzer-QSDJVBPS.js +2 -0
- package/dist/cli/chunks/init-guard-SMGJ45PW.js +2 -0
- package/dist/cli/chunks/init-handler-5T4MP2NM.js +88 -0
- package/dist/cli/chunks/init-wizard-MK2325JJ.js +2 -0
- package/dist/cli/chunks/kernel-2NJQQ2KT.js +2 -0
- package/dist/cli/chunks/{kilocode-installer-32PX5YH7.js → kilocode-installer-RLZYLVQJ.js} +2 -2
- package/dist/cli/chunks/{kiro-installer-C4ROMMUS.js → kiro-installer-LFZOC7VD.js} +2 -2
- package/dist/cli/chunks/knowledge-graph-SDISHO62.js +2 -0
- package/dist/cli/chunks/{learning-GEPVZGJQ.js → learning-XRPGLUWR.js} +20 -20
- package/dist/cli/chunks/{llm-router-XRKTTJTX.js → llm-router-OMK5HYPH.js} +4 -4
- package/dist/cli/chunks/llm-router-service-YTCMRBAN.js +2 -0
- package/dist/cli/chunks/{load-XVH6HW7E.js → load-XADC7KCU.js} +2 -2
- package/dist/cli/chunks/load-test-RPKHLBCC.js +2 -0
- package/dist/cli/chunks/{mcp-IULSTM4Z.js → mcp-PIBKSSVU.js} +2 -2
- package/dist/cli/chunks/{memory-6K7IAU4T.js → memory-AP7EZERS.js} +5 -5
- package/dist/cli/chunks/memory-backend-BZXFO4JZ.js +2 -0
- package/dist/cli/chunks/{memory-handlers-CG6DRLAW.js → memory-handlers-MOFDNB6E.js} +2 -2
- package/dist/cli/chunks/{multi-model-executor-VZDUYPLX.js → multi-model-executor-7JJ2FZ33.js} +2 -2
- package/dist/cli/chunks/{opencode-installer-QUTXKNH4.js → opencode-installer-ZZZ6EBYJ.js} +2 -2
- package/dist/cli/chunks/{orchestrator-PCKKUWOP.js → orchestrator-2H2YKSGJ.js} +5 -5
- package/dist/cli/chunks/pattern-null-store-4PRPIOR6.js +2 -0
- package/dist/cli/chunks/{pattern-usage-recorder-PX5HQVRL.js → pattern-usage-recorder-7MJJWC2Z.js} +2 -2
- package/dist/cli/chunks/{pipeline-O562GTOG.js → pipeline-LIE5BWQY.js} +2 -2
- package/dist/cli/chunks/{platform-PM7Q2AZS.js → platform-SMYUNLGX.js} +2 -2
- package/dist/cli/chunks/{plugin-OTYTFGPY.js → plugin-LJDIXQNT.js} +2 -2
- package/dist/cli/chunks/{prime-radiant-advanced-wasm-6CFXTHC2.js → prime-radiant-advanced-wasm-RIDNE5D2.js} +2 -2
- package/dist/cli/chunks/project-root-NBIQF63D.js +2 -0
- package/dist/cli/chunks/protocol-executor-BRPGIYWQ.js +2 -0
- package/dist/cli/chunks/{protocol-handler-PPGNSAOS.js → protocol-handler-YVM66DLI.js} +2 -2
- package/dist/cli/chunks/{prove-WQ3BKRZG.js → prove-ZBDT52GD.js} +2 -2
- package/dist/cli/chunks/qe-reasoning-bank-GDZACWKW.js +2 -0
- package/dist/cli/chunks/{quality-C5WUU3AA.js → quality-DUKXGDDO.js} +2 -2
- package/dist/cli/chunks/{quality-gate-WSSRKD5U.js → quality-gate-SM3RXF4V.js} +3 -3
- package/dist/cli/chunks/queen-coordinator-LDKLBPD5.js +2 -0
- package/dist/cli/chunks/{real-embeddings-CFQE7IRQ.js → real-embeddings-4QLQZDB5.js} +2 -2
- package/dist/cli/chunks/{ref-validation-DHKHXVZT.js → ref-validation-M3EO32YQ.js} +2 -2
- package/dist/cli/chunks/{roocode-installer-3PPODABV.js → roocode-installer-S6Q5OLV5.js} +2 -2
- package/dist/cli/chunks/router-H5YSIRH2.js +2 -0
- package/dist/cli/chunks/routing-feedback-5R36TJDH.js +2 -0
- package/dist/cli/chunks/{routing-handler-JNXTGT6T.js → routing-handler-55FMUACP.js} +2 -2
- package/dist/cli/chunks/{ruvector-commands-6YLROPVP.js → ruvector-commands-QATKAAPK.js} +2 -2
- package/dist/cli/chunks/rvf-dual-writer-TT2DBQQQ.js +2 -0
- package/dist/cli/chunks/rvf-migration-adapter-BCLFJKSK.js +2 -0
- package/dist/cli/chunks/{rvf-migration-coordinator-4DWB4WRK.js → rvf-migration-coordinator-RFXFU6JD.js} +2 -2
- package/dist/cli/chunks/rvf-native-adapter-UXI66OQJ.js +2 -0
- package/dist/cli/chunks/{rvf-store-integrity-YKR2ZNBF.js → rvf-store-integrity-PKDVXQAW.js} +2 -2
- package/dist/cli/chunks/safe-db-MSTD2GDH.js +2 -0
- package/dist/cli/chunks/schedule-KST6KIFD.js +2 -0
- package/dist/cli/chunks/scheduler-FTQS6YK3.js +2 -0
- package/dist/cli/chunks/security-CMRB6WA3.js +18 -0
- package/dist/cli/chunks/{shared-rvf-adapter-LNRLFP5I.js → shared-rvf-adapter-YHLLNFHF.js} +2 -2
- package/dist/cli/chunks/{shared-rvf-dual-writer-GWU6YQNS.js → shared-rvf-dual-writer-4BGDVPQ7.js} +2 -2
- package/dist/cli/chunks/sqlite-persistence-ZX5QFDMR.js +2 -0
- package/dist/cli/chunks/{standalone-memory-46KKBSSV.js → standalone-memory-LUHKQAGM.js} +2 -2
- package/dist/cli/chunks/{status-handler-35T5FTDQ.js → status-handler-S6S5PNR7.js} +2 -2
- package/dist/cli/chunks/{structural-health-P7QPQWLO.js → structural-health-PQ7NZAJ4.js} +2 -2
- package/dist/cli/chunks/{sync-W6Z4R4PL.js → sync-Q6KRQXU6.js} +2 -2
- package/dist/cli/chunks/{sync-Y43EWBSY.js → sync-S744AEJC.js} +2 -2
- package/dist/cli/chunks/{task-handler-5CX3ZYT7.js → task-handler-GAMGEHUW.js} +2 -2
- package/dist/cli/chunks/{task-handlers-DQZGOJNE.js → task-handlers-6CRDEELN.js} +3 -3
- package/dist/cli/chunks/{test-TPP53VVV.js → test-FNH67DBK.js} +4 -4
- package/dist/cli/chunks/{test-scheduling-WBV4UMQH.js → test-scheduling-NZA5SHK6.js} +3 -3
- package/dist/cli/chunks/{token-bootstrap-GIIDXHLC.js → token-bootstrap-CXKG55JD.js} +2 -2
- package/dist/cli/chunks/{token-usage-AKK37RB7.js → token-usage-M7WWEDJX.js} +2 -2
- package/dist/cli/chunks/{transformers-7MASPELS.js → transformers-2IFMCK6A.js} +2 -2
- package/dist/cli/chunks/{tree-sitter-wasm-parser-YZKD6UGB.js → tree-sitter-wasm-parser-NMNA6RJC.js} +2 -2
- package/dist/cli/chunks/{types-AZ3BTXDP.js → types-N7FWTOLD.js} +2 -2
- package/dist/cli/chunks/unified-memory-2Z2F446J.js +2 -0
- package/dist/cli/chunks/unified-memory-hnsw-A4EWYPJQ.js +2 -0
- package/dist/cli/chunks/unified-persistence-Z6N6JZFA.js +2 -0
- package/dist/cli/chunks/{upgrade-L7OTDKEK.js → upgrade-KDB5RGL7.js} +2 -2
- package/dist/cli/chunks/{validate-O3QVFIGP.js → validate-KMUV5FUA.js} +2 -2
- package/dist/cli/chunks/{validate-swarm-2UGBGLTX.js → validate-swarm-ANZWRCJU.js} +2 -2
- package/dist/cli/chunks/visual-security-GXYZV7KR.js +2 -0
- package/dist/cli/chunks/{web-tree-sitter-J75IYPRO.js → web-tree-sitter-SXXC4NMS.js} +2 -2
- package/dist/cli/chunks/{windsurf-installer-FQ5DBFCG.js → windsurf-installer-2LWSKMBU.js} +2 -2
- package/dist/cli/chunks/witness-chain-52PEIEGK.js +2 -0
- package/dist/cli/chunks/{witness-chain-I7TN4MXZ.js → witness-chain-JJMSJFZP.js} +2 -2
- package/dist/cli/chunks/{witness-chain-repair-D3NE3NQK.js → witness-chain-repair-OX7VFW6T.js} +2 -2
- package/dist/cli/chunks/{witness-chain-verifier-RU2WOP5M.js → witness-chain-verifier-QLSMXHAZ.js} +2 -2
- package/dist/cli/chunks/{witness-key-manager-IHQB2FR5.js → witness-key-manager-3DS4L7LE.js} +2 -2
- package/dist/cli/chunks/{workflow-6BWTNVV6.js → workflow-ARWAMHD3.js} +4 -4
- package/dist/cli/chunks/workflow-orchestrator-DORMQMG7.js +2 -0
- package/dist/cli/chunks/{wrappers-URVP25VU.js → wrappers-J6KGTUSJ.js} +2 -2
- package/dist/cli/commands/learning.js +3 -2
- package/dist/cli/commands/security.d.ts +16 -0
- package/dist/cli/commands/security.js +76 -9
- package/dist/cli/handlers/init-guard.d.ts +21 -1
- package/dist/cli/handlers/init-guard.js +51 -8
- package/dist/cli/handlers/init-handler.js +57 -56
- package/dist/cli/index.js +11 -0
- package/dist/cli/utils/ci-output.d.ts +5 -0
- package/dist/cli/utils/ci-output.js +8 -0
- package/dist/coordination/handlers/security-handlers.js +22 -6
- package/dist/coordination/protocols/defect-investigation.js +7 -1
- package/dist/coordination/protocols/security-audit.js +11 -0
- package/dist/coordination/result-saver.d.ts +9 -0
- package/dist/coordination/result-saver.js +34 -4
- package/dist/domains/coverage-analysis/collected-metrics.d.ts +2 -0
- package/dist/domains/coverage-analysis/collected-metrics.js +6 -0
- package/dist/domains/defect-intelligence/services/defect-predictor.js +9 -6
- package/dist/domains/quality-assessment/interfaces.d.ts +4 -0
- package/dist/domains/quality-assessment/quality-evidence.d.ts +1 -1
- package/dist/domains/quality-assessment/services/quality-analyzer.js +7 -5
- package/dist/domains/quality-assessment/services/quality-gate.js +12 -3
- package/dist/domains/security-compliance/dependency-advisory-engine.d.ts +52 -0
- package/dist/domains/security-compliance/dependency-advisory-engine.js +113 -0
- package/dist/domains/security-compliance/interfaces.d.ts +30 -0
- package/dist/domains/security-compliance/plugin.d.ts +7 -1
- package/dist/domains/security-compliance/plugin.js +19 -0
- package/dist/domains/security-compliance/services/scanners/dependency-resolver.d.ts +71 -0
- package/dist/domains/security-compliance/services/scanners/dependency-resolver.js +232 -0
- package/dist/domains/security-compliance/services/scanners/dependency-scanner.d.ts +21 -6
- package/dist/domains/security-compliance/services/scanners/dependency-scanner.js +142 -64
- package/dist/domains/security-compliance/services/scanners/lockfile-versions.d.ts +43 -0
- package/dist/domains/security-compliance/services/scanners/lockfile-versions.js +248 -0
- package/dist/domains/security-compliance/services/scanners/scanner-types.d.ts +30 -2
- package/dist/domains/security-compliance/services/security-auditor.d.ts +19 -6
- package/dist/domains/security-compliance/services/security-auditor.js +133 -92
- package/dist/domains/test-execution/services/retry-handler.js +17 -6
- package/dist/domains/test-execution/services/test-executor.d.ts +1 -0
- package/dist/domains/test-execution/services/test-executor.js +87 -7
- package/dist/kernel/shared-dirs.js +17 -5
- package/dist/mcp/bundle.js +874 -874
- package/dist/mcp/handlers/domain-handler-configs.d.ts +4 -0
- package/dist/mcp/handlers/domain-handler-configs.js +5 -1
- package/dist/mcp/protocol-server.js +2 -1
- package/dist/mcp/types.d.ts +6 -0
- package/dist/shared/security/index.d.ts +2 -2
- package/dist/shared/security/index.js +1 -1
- package/dist/shared/security/osv-client.d.ts +79 -132
- package/dist/shared/security/osv-client.js +344 -167
- package/dist/shared/security/osv-lookup.d.ts +124 -0
- package/dist/shared/security/osv-lookup.js +246 -0
- package/dist/shared/security/osv-types.d.ts +119 -0
- package/dist/shared/security/osv-types.js +6 -0
- package/dist/workers/interfaces.d.ts +6 -1
- package/dist/workers/namespaced-keys.d.ts +16 -0
- package/dist/workers/namespaced-keys.js +24 -0
- package/dist/workers/quality-daemon/persistent-memory.d.ts +1 -1
- package/dist/workers/quality-daemon/persistent-memory.js +2 -2
- package/dist/workers/worker-manager.js +5 -2
- package/dist/workers/workers/defect-predictor.d.ts +25 -8
- package/dist/workers/workers/defect-predictor.js +223 -216
- package/dist/workers/workers/performance-baseline.d.ts +24 -9
- package/dist/workers/workers/performance-baseline.js +187 -230
- package/dist/workers/workers/quality-gate.d.ts +11 -9
- package/dist/workers/workers/quality-gate.js +125 -267
- package/dist/workers/workers/security-scan-records.d.ts +111 -0
- package/dist/workers/workers/security-scan-records.js +128 -0
- package/dist/workers/workers/security-scan.d.ts +25 -7
- package/dist/workers/workers/security-scan.js +187 -164
- package/package.json +2 -2
- package/dist/cli/chunks/adapter-PP3XIXDV.js +0 -2
- package/dist/cli/chunks/aqe-learning-engine-VDUQJKKY.js +0 -2
- package/dist/cli/chunks/base-QSYWWPCE.js +0 -2
- package/dist/cli/chunks/browser-workflow-WXXPBSCM.js +0 -2
- package/dist/cli/chunks/chunk-45MVRQG4.js +0 -2
- package/dist/cli/chunks/chunk-5VZVMO7B.js +0 -3
- package/dist/cli/chunks/chunk-EECF4CMA.js +0 -2
- package/dist/cli/chunks/client-6XKSQ4JT.js +0 -2
- package/dist/cli/chunks/core-handlers-OJYW4Y6M.js +0 -2
- package/dist/cli/chunks/cross-domain-router-QVUPQ2SC.js +0 -2
- package/dist/cli/chunks/daemon-QBYTCIMH.js +0 -10
- package/dist/cli/chunks/dream-3UABDRZJ.js +0 -2
- package/dist/cli/chunks/file-discovery-ZFGZTKZ4.js +0 -2
- package/dist/cli/chunks/heartbeat-scheduler-MJ6MTPDF.js +0 -2
- package/dist/cli/chunks/hnsw-adapter-FQWJCFVW.js +0 -2
- package/dist/cli/chunks/hnsw-index-NJYKJUHC.js +0 -2
- package/dist/cli/chunks/hybrid-backend-SL7RFID7.js +0 -2
- package/dist/cli/chunks/impact-analyzer-5ZJTXPVC.js +0 -2
- package/dist/cli/chunks/init-handler-PCLYQUSB.js +0 -88
- package/dist/cli/chunks/init-wizard-MQMDSIOF.js +0 -2
- package/dist/cli/chunks/kernel-MEJ5GMRH.js +0 -2
- package/dist/cli/chunks/knowledge-graph-XUBZSEZE.js +0 -2
- package/dist/cli/chunks/llm-router-service-QZAPAEPX.js +0 -2
- package/dist/cli/chunks/load-test-OVXIQ3AF.js +0 -2
- package/dist/cli/chunks/memory-backend-TRPOMPK4.js +0 -2
- package/dist/cli/chunks/pattern-null-store-JWYBRBZG.js +0 -2
- package/dist/cli/chunks/project-root-VVSTHIP4.js +0 -2
- package/dist/cli/chunks/protocol-executor-PXZCLZD3.js +0 -2
- package/dist/cli/chunks/qe-reasoning-bank-42FRS5V3.js +0 -2
- package/dist/cli/chunks/queen-coordinator-UI3B7DI6.js +0 -2
- package/dist/cli/chunks/router-HYRPWLAY.js +0 -2
- package/dist/cli/chunks/routing-feedback-BPZ5R6F3.js +0 -2
- package/dist/cli/chunks/rvf-dual-writer-DEKDQ6KO.js +0 -2
- package/dist/cli/chunks/rvf-migration-adapter-L53VBS7I.js +0 -2
- package/dist/cli/chunks/rvf-native-adapter-I6RUGD2D.js +0 -2
- package/dist/cli/chunks/safe-db-KS65XDCP.js +0 -2
- package/dist/cli/chunks/schedule-KD2VN6GB.js +0 -2
- package/dist/cli/chunks/scheduler-ZH3RMUHY.js +0 -2
- package/dist/cli/chunks/security-PWQTGDRU.js +0 -13
- package/dist/cli/chunks/sqlite-persistence-6DTVME5D.js +0 -2
- package/dist/cli/chunks/unified-memory-FCX7NLFZ.js +0 -2
- package/dist/cli/chunks/unified-memory-hnsw-VU5QJK37.js +0 -2
- package/dist/cli/chunks/unified-persistence-FM376LGE.js +0 -2
- package/dist/cli/chunks/visual-security-EU7Y3X46.js +0 -2
- package/dist/cli/chunks/witness-chain-CSEBT52D.js +0 -2
- package/dist/cli/chunks/workflow-orchestrator-ALNKOM3N.js +0 -2
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
import { v4 as uuidv4 } from 'uuid';
|
|
6
6
|
import { ok, err } from '../../../../shared/types/index.js';
|
|
7
7
|
import { OSVClient } from '../../../../shared/security/index.js';
|
|
8
|
+
import { lookupKey } from '../../../../shared/security/osv-lookup.js';
|
|
8
9
|
import { toError } from '../../../../shared/error-utils.js';
|
|
9
|
-
import {
|
|
10
|
+
import { resolveDependencies, resolveFromRecord } from './dependency-resolver.js';
|
|
10
11
|
// ============================================================================
|
|
11
12
|
// Dependency Scanner Service
|
|
12
13
|
// ============================================================================
|
|
@@ -19,71 +20,48 @@ export class DependencyScanner {
|
|
|
19
20
|
memory;
|
|
20
21
|
osvClient;
|
|
21
22
|
activeScans;
|
|
22
|
-
constructor(config, memory, activeScans) {
|
|
23
|
+
constructor(config, memory, activeScans, osvClient) {
|
|
23
24
|
this.config = config;
|
|
24
25
|
this.memory = memory;
|
|
25
|
-
this.osvClient = new OSVClient({ enableCache: true });
|
|
26
|
+
this.osvClient = osvClient ?? new OSVClient({ enableCache: true });
|
|
26
27
|
this.activeScans = activeScans || new Map();
|
|
27
28
|
}
|
|
28
29
|
// ==========================================================================
|
|
29
30
|
// Public Methods
|
|
30
31
|
// ==========================================================================
|
|
31
32
|
/**
|
|
32
|
-
* Scan npm dependencies for known vulnerabilities using OSV
|
|
33
|
+
* Scan npm dependencies (`name -> spec`) for known vulnerabilities using OSV.
|
|
34
|
+
*
|
|
35
|
+
* #1049: a failed or partial advisory lookup is recorded and returned as
|
|
36
|
+
* `status: 'failed' | 'incomplete'`, `measured: false`, with the unchecked
|
|
37
|
+
* dependencies and the error, never as a clean scan. Findings for the
|
|
38
|
+
* dependencies that were checked are kept.
|
|
39
|
+
*
|
|
40
|
+
* Each dependency is checked at `lockedVersions[name]` when given and
|
|
41
|
+
* consistent with the spec, else only when its spec is an exact version; a
|
|
42
|
+
* range with no resolution is reported unchecked, never guessed.
|
|
33
43
|
*/
|
|
34
|
-
async scanDependencies(dependencies) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
try {
|
|
38
|
-
if (Object.keys(dependencies).length === 0) {
|
|
39
|
-
return err(new Error('No dependencies provided for scanning'));
|
|
40
|
-
}
|
|
41
|
-
this.activeScans.set(scanId, 'running');
|
|
42
|
-
// Query OSV for vulnerabilities
|
|
43
|
-
const osvVulns = await this.osvClient.scanNpmDependencies(dependencies);
|
|
44
|
-
// Convert OSV vulnerabilities to our format
|
|
45
|
-
const vulnerabilities = this.convertOSVVulnerabilities(osvVulns);
|
|
46
|
-
const scanDurationMs = Date.now() - startTime;
|
|
47
|
-
// Calculate unique vulnerable packages
|
|
48
|
-
const vulnerablePackageNames = new Set(osvVulns.map((v) => v.affectedPackage));
|
|
49
|
-
// Calculate summary
|
|
50
|
-
const summary = this.calculateSummary(vulnerabilities, Object.keys(dependencies).length, scanDurationMs);
|
|
51
|
-
// Store scan results
|
|
52
|
-
await this.storeScanResults(scanId, 'dependency', vulnerabilities, summary);
|
|
53
|
-
this.activeScans.set(scanId, 'completed');
|
|
54
|
-
return ok({
|
|
55
|
-
scanId,
|
|
56
|
-
vulnerabilities,
|
|
57
|
-
packagesScanned: Object.keys(dependencies).length,
|
|
58
|
-
vulnerablePackages: vulnerablePackageNames.size,
|
|
59
|
-
summary,
|
|
60
|
-
scanDurationMs,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
catch (error) {
|
|
64
|
-
this.activeScans.set(scanId, 'failed');
|
|
65
|
-
return err(toError(error));
|
|
44
|
+
async scanDependencies(dependencies, lockedVersions = {}) {
|
|
45
|
+
if (Object.keys(dependencies).length === 0) {
|
|
46
|
+
return err(new Error('No dependencies provided for scanning'));
|
|
66
47
|
}
|
|
48
|
+
return this.runScan({
|
|
49
|
+
dependencies: resolveFromRecord(dependencies, lockedVersions), lockfile: null, errors: [],
|
|
50
|
+
});
|
|
67
51
|
}
|
|
68
52
|
/**
|
|
69
|
-
* Scan a package.json
|
|
53
|
+
* Scan a package.json: its direct dependencies, at the versions the lockfile
|
|
54
|
+
* resolves. A manifest with no dependencies is a complete scan of nothing; a
|
|
55
|
+
* workspace root is never complete, since its members are not scanned (#1057).
|
|
70
56
|
*/
|
|
71
57
|
async scanPackageJson(packageJsonPath) {
|
|
72
58
|
try {
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
...(packageJson.devDependencies || {}),
|
|
80
|
-
...(packageJson.peerDependencies || {}),
|
|
81
|
-
...(packageJson.optionalDependencies || {}),
|
|
82
|
-
};
|
|
83
|
-
if (Object.keys(allDependencies).length === 0) {
|
|
84
|
-
return err(new Error('No dependencies found in package.json'));
|
|
85
|
-
}
|
|
86
|
-
return this.scanDependencies(allDependencies);
|
|
59
|
+
const resolution = await resolveDependencies(packageJsonPath);
|
|
60
|
+
return this.runScan({
|
|
61
|
+
dependencies: resolution.dependencies,
|
|
62
|
+
lockfile: resolution.lockfile,
|
|
63
|
+
errors: [...(resolution.error ? [resolution.error] : []), ...resolution.memberErrors],
|
|
64
|
+
});
|
|
87
65
|
}
|
|
88
66
|
catch (error) {
|
|
89
67
|
if (error instanceof SyntaxError) {
|
|
@@ -101,23 +79,104 @@ export class DependencyScanner {
|
|
|
101
79
|
// ==========================================================================
|
|
102
80
|
// Private Methods
|
|
103
81
|
// ==========================================================================
|
|
82
|
+
async runScan(plan) {
|
|
83
|
+
const scanId = uuidv4();
|
|
84
|
+
const startTime = Date.now();
|
|
85
|
+
try {
|
|
86
|
+
this.activeScans.set(scanId, 'running');
|
|
87
|
+
const toCheck = plan.dependencies.filter((d) => d.kind === 'check');
|
|
88
|
+
const queries = [...new Map(toCheck.map((d) => {
|
|
89
|
+
const q = { name: d.packageName, ecosystem: 'npm', version: d.version };
|
|
90
|
+
return [lookupKey(q), q];
|
|
91
|
+
})).values()];
|
|
92
|
+
const lookup = await this.osvClient.lookupBatch(queries);
|
|
93
|
+
const failedQueries = new Map(lookup.unchecked.map((u) => [lookupKey(u), u.reason]));
|
|
94
|
+
const vulnerabilities = [];
|
|
95
|
+
const uncheckedPackages = [];
|
|
96
|
+
const localPackages = [];
|
|
97
|
+
const vulnerablePackages = new Set();
|
|
98
|
+
let packagesChecked = 0;
|
|
99
|
+
const memberField = (d) => (d.member ? { member: d.member } : {});
|
|
100
|
+
for (const dep of plan.dependencies) {
|
|
101
|
+
if (dep.kind === 'local') {
|
|
102
|
+
localPackages.push({ name: dep.name, spec: dep.spec, reason: dep.reason ?? 'local package', ...memberField(dep) });
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (dep.kind === 'unchecked') {
|
|
106
|
+
uncheckedPackages.push({ name: dep.name, version: dep.spec, reason: dep.reason ?? 'not checked', ...memberField(dep),
|
|
107
|
+
...(dep.lockedVersion ? { lockedVersion: dep.lockedVersion } : {}) });
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const key = lookupKey({ name: dep.packageName, ecosystem: 'npm', version: dep.version });
|
|
111
|
+
const found = lookup.results.get(key);
|
|
112
|
+
if (!found) {
|
|
113
|
+
uncheckedPackages.push({ name: dep.name, version: dep.spec, reason: failedQueries.get(key) ?? 'advisory lookup did not return a result',
|
|
114
|
+
...memberField(dep), ...(dep.lockedVersion ? { lockedVersion: dep.lockedVersion } : {}) });
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
packagesChecked++;
|
|
118
|
+
if (found.length > 0)
|
|
119
|
+
vulnerablePackages.add(dep.packageName);
|
|
120
|
+
vulnerabilities.push(...this.convertOSVVulnerabilities(found, dep));
|
|
121
|
+
}
|
|
122
|
+
const requested = packagesChecked + uncheckedPackages.length;
|
|
123
|
+
// #1049 round 4: a planning error (malformed lockfile, a workspace root whose
|
|
124
|
+
// members are not scanned #1057) means something was not checked.
|
|
125
|
+
const allChecked = packagesChecked === requested && plan.errors.length === 0;
|
|
126
|
+
// `failed` = something was to be checked and nothing could be; nothing to check
|
|
127
|
+
// with a planning error (e.g. a workspace root with no own dependencies) is incomplete.
|
|
128
|
+
const status = allChecked ? 'complete'
|
|
129
|
+
: packagesChecked === 0 && requested > 0 ? 'failed' : 'incomplete';
|
|
130
|
+
const scanDurationMs = Date.now() - startTime;
|
|
131
|
+
const summary = this.calculateSummary(vulnerabilities, requested, scanDurationMs);
|
|
132
|
+
const error = status === 'complete' ? undefined
|
|
133
|
+
: describeLookupFailure([...plan.errors, ...lookup.errors], uncheckedPackages);
|
|
134
|
+
const result = {
|
|
135
|
+
scanId,
|
|
136
|
+
vulnerabilities,
|
|
137
|
+
packagesScanned: requested,
|
|
138
|
+
vulnerablePackages: vulnerablePackages.size,
|
|
139
|
+
summary,
|
|
140
|
+
scanDurationMs,
|
|
141
|
+
status,
|
|
142
|
+
measured: status === 'complete',
|
|
143
|
+
packagesChecked,
|
|
144
|
+
uncheckedPackages,
|
|
145
|
+
lockfile: plan.lockfile,
|
|
146
|
+
localPackages,
|
|
147
|
+
resolutionErrors: plan.errors,
|
|
148
|
+
scope: 'direct',
|
|
149
|
+
...(error ? { error } : {}),
|
|
150
|
+
};
|
|
151
|
+
await this.storeScanResults(result);
|
|
152
|
+
this.activeScans.set(scanId, status === 'complete' ? 'completed' : 'failed');
|
|
153
|
+
return ok(result);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
this.activeScans.set(scanId, 'failed');
|
|
157
|
+
return err(toError(error));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
104
160
|
/**
|
|
105
|
-
* Convert OSV vulnerabilities to our internal format
|
|
161
|
+
* Convert OSV vulnerabilities of one checked dependency to our internal format
|
|
106
162
|
*/
|
|
107
|
-
convertOSVVulnerabilities(osvVulns) {
|
|
163
|
+
convertOSVVulnerabilities(osvVulns, dep) {
|
|
164
|
+
const pkg = dep.packageName;
|
|
165
|
+
const label = pkg === dep.name ? pkg : `${dep.name} (${pkg})`;
|
|
108
166
|
return osvVulns.map((osv) => {
|
|
109
167
|
const location = {
|
|
110
|
-
file: 'package.json',
|
|
168
|
+
file: dep.member ? `${dep.member}/package.json` : 'package.json',
|
|
111
169
|
line: 1,
|
|
112
170
|
column: 1,
|
|
113
|
-
snippet: `"${
|
|
171
|
+
snippet: `"${dep.name}": "${dep.spec}"`,
|
|
172
|
+
dependency: { name: pkg, version: dep.version, ecosystem: 'npm' },
|
|
114
173
|
};
|
|
115
174
|
const remediation = {
|
|
116
175
|
description: osv.fixedVersions.length > 0
|
|
117
176
|
? `Update to version ${osv.fixedVersions[0]} or later`
|
|
118
177
|
: 'No fixed version available; consider alternative packages',
|
|
119
178
|
fixExample: osv.fixedVersions.length > 0
|
|
120
|
-
? `npm install ${
|
|
179
|
+
? `npm install ${pkg}@${osv.fixedVersions[0]}`
|
|
121
180
|
: undefined,
|
|
122
181
|
estimatedEffort: 'minor',
|
|
123
182
|
automatable: true,
|
|
@@ -125,7 +184,7 @@ export class DependencyScanner {
|
|
|
125
184
|
return {
|
|
126
185
|
id: uuidv4(),
|
|
127
186
|
cveId: osv.cveIds[0],
|
|
128
|
-
title: `${
|
|
187
|
+
title: `${label}: ${osv.summary.substring(0, 80)}`,
|
|
129
188
|
description: osv.details || osv.summary,
|
|
130
189
|
severity: this.mapOSVSeverity(osv.severity),
|
|
131
190
|
category: 'vulnerable-components',
|
|
@@ -167,16 +226,35 @@ export class DependencyScanner {
|
|
|
167
226
|
return summary;
|
|
168
227
|
}
|
|
169
228
|
/**
|
|
170
|
-
* Store scan
|
|
229
|
+
* Store the scan record read by the security-scan worker (#1043/#1049).
|
|
230
|
+
* Consumers must treat it as a measurement only when
|
|
231
|
+
* `measured === true && status === 'complete'`.
|
|
171
232
|
*/
|
|
172
|
-
async storeScanResults(
|
|
173
|
-
await this.memory.set(`security:scan:${scanId}`, {
|
|
174
|
-
scanId,
|
|
175
|
-
scanType,
|
|
176
|
-
|
|
177
|
-
|
|
233
|
+
async storeScanResults(result) {
|
|
234
|
+
await this.memory.set(`security:scan:${result.scanId}`, {
|
|
235
|
+
scanId: result.scanId,
|
|
236
|
+
scanType: 'dependency',
|
|
237
|
+
advisorySource: 'osv',
|
|
238
|
+
status: result.status,
|
|
239
|
+
measured: result.measured,
|
|
240
|
+
scope: result.scope ?? 'direct',
|
|
241
|
+
packagesRequested: result.packagesScanned,
|
|
242
|
+
packagesChecked: result.packagesChecked,
|
|
243
|
+
uncheckedPackages: result.uncheckedPackages,
|
|
244
|
+
localPackages: result.localPackages ?? [],
|
|
245
|
+
resolutionErrors: result.resolutionErrors ?? [],
|
|
246
|
+
lockfile: result.lockfile ?? null,
|
|
247
|
+
...(result.error ? { error: result.error } : {}),
|
|
248
|
+
vulnerabilities: result.vulnerabilities,
|
|
249
|
+
summary: result.summary,
|
|
178
250
|
timestamp: new Date().toISOString(),
|
|
179
251
|
}, { namespace: 'security-compliance', ttl: 86400 * 7 });
|
|
180
252
|
}
|
|
181
253
|
}
|
|
254
|
+
/** One bounded sentence naming why the advisory lookup is incomplete. */
|
|
255
|
+
function describeLookupFailure(errors, unchecked) {
|
|
256
|
+
const reasons = errors.length > 0 ? errors : [...new Set(unchecked.map((p) => p.reason))];
|
|
257
|
+
const what = unchecked.length > 0 ? `${unchecked.length} package(s)` : 'some dependencies';
|
|
258
|
+
return `Dependency advisories could not be checked for ${what}: ${reasons.slice(0, 3).join('; ')}`;
|
|
259
|
+
}
|
|
182
260
|
//# sourceMappingURL=dependency-scanner.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Lockfile index (#1049)
|
|
3
|
+
*
|
|
4
|
+
* A package.json spec is usually a range; advisories can only be matched
|
|
5
|
+
* against the version actually installed, which the lockfile records. These
|
|
6
|
+
* readers turn a lockfile into a per-importer view (the root is importer '',
|
|
7
|
+
* workspace members are their relative path, e.g. 'packages/a'):
|
|
8
|
+
*
|
|
9
|
+
* - recordedSpec: the spec the lockfile was generated for (npm v2/v3 and pnpm
|
|
10
|
+
* record it; used to detect a lockfile out of sync with package.json);
|
|
11
|
+
* - resolve: the installed version, whether it is a local/linked package, and
|
|
12
|
+
* the real package name behind an `npm:` alias.
|
|
13
|
+
*
|
|
14
|
+
* Supported: npm-shrinkwrap.json, package-lock.json (v1-v3), pnpm-lock.yaml
|
|
15
|
+
* (v5-v9, importers or single-project), yarn.lock (classic and berry).
|
|
16
|
+
*/
|
|
17
|
+
export declare const LOCKFILES: readonly ["npm-shrinkwrap.json", "package-lock.json", "pnpm-lock.yaml", "yarn.lock"];
|
|
18
|
+
export type LockfileName = typeof LOCKFILES[number];
|
|
19
|
+
/** What the lockfile installed for one dependency of one importer. */
|
|
20
|
+
export interface LockedEntry {
|
|
21
|
+
/** Installed version (absent for a local/linked package). */
|
|
22
|
+
version?: string;
|
|
23
|
+
/** A workspace / linked / local-directory package. */
|
|
24
|
+
local?: boolean;
|
|
25
|
+
/** The registry package behind an alias (`npm:<real>@…`), when it differs from the dependency name. */
|
|
26
|
+
realName?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface LockIndex {
|
|
29
|
+
readonly file: LockfileName;
|
|
30
|
+
/** Workspace member importers the lockfile knows (relative paths, '' excluded). */
|
|
31
|
+
members(): string[];
|
|
32
|
+
/**
|
|
33
|
+
* The spec the lockfile records for `name` in `importer`: a string, `undefined`
|
|
34
|
+
* when the importer does not list it, or `null` when this format records no specs.
|
|
35
|
+
*/
|
|
36
|
+
recordedSpec(importer: string, name: string): string | undefined | null;
|
|
37
|
+
resolve(importer: string, name: string, spec: string): LockedEntry | undefined;
|
|
38
|
+
/** Whether the lockfile knows this importer (the root '' always). */
|
|
39
|
+
hasImporter(importer: string): boolean;
|
|
40
|
+
}
|
|
41
|
+
/** Parse a lockfile's text; throws on malformed content. */
|
|
42
|
+
export declare function parseLockfile(file: LockfileName, raw: string): LockIndex;
|
|
43
|
+
//# sourceMappingURL=lockfile-versions.d.ts.map
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agentic QE v3 - Lockfile index (#1049)
|
|
3
|
+
*
|
|
4
|
+
* A package.json spec is usually a range; advisories can only be matched
|
|
5
|
+
* against the version actually installed, which the lockfile records. These
|
|
6
|
+
* readers turn a lockfile into a per-importer view (the root is importer '',
|
|
7
|
+
* workspace members are their relative path, e.g. 'packages/a'):
|
|
8
|
+
*
|
|
9
|
+
* - recordedSpec: the spec the lockfile was generated for (npm v2/v3 and pnpm
|
|
10
|
+
* record it; used to detect a lockfile out of sync with package.json);
|
|
11
|
+
* - resolve: the installed version, whether it is a local/linked package, and
|
|
12
|
+
* the real package name behind an `npm:` alias.
|
|
13
|
+
*
|
|
14
|
+
* Supported: npm-shrinkwrap.json, package-lock.json (v1-v3), pnpm-lock.yaml
|
|
15
|
+
* (v5-v9, importers or single-project), yarn.lock (classic and berry).
|
|
16
|
+
*/
|
|
17
|
+
import { safeJsonParse } from '../../../../shared/safe-json.js';
|
|
18
|
+
export const LOCKFILES = ['npm-shrinkwrap.json', 'package-lock.json', 'pnpm-lock.yaml', 'yarn.lock'];
|
|
19
|
+
const DEP_FIELDS = ['dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies'];
|
|
20
|
+
/** Parse a lockfile's text; throws on malformed content. */
|
|
21
|
+
export function parseLockfile(file, raw) {
|
|
22
|
+
const text = raw.replace(/^\uFEFF/, ''); // a leading BOM is not "malformed"
|
|
23
|
+
// #1049 round 4: content that is not a lockfile of this format is an error,
|
|
24
|
+
// never an empty lockfile (which would read as "nothing locked").
|
|
25
|
+
if (file === 'pnpm-lock.yaml') {
|
|
26
|
+
if (!/^lockfileVersion:/m.test(text))
|
|
27
|
+
throw new Error('not a pnpm lockfile (no lockfileVersion)');
|
|
28
|
+
return pnpmIndex(text);
|
|
29
|
+
}
|
|
30
|
+
if (file === 'yarn.lock') {
|
|
31
|
+
if (!/^# yarn lockfile v1\b|^__metadata:/m.test(text))
|
|
32
|
+
throw new Error('not a yarn lockfile (no "# yarn lockfile v1" or __metadata header)');
|
|
33
|
+
return yarnIndex(text);
|
|
34
|
+
}
|
|
35
|
+
return npmIndex(file, text);
|
|
36
|
+
}
|
|
37
|
+
function npmIndex(file, text) {
|
|
38
|
+
const lock = safeJsonParse(text);
|
|
39
|
+
if (!lock || typeof lock !== 'object' || Array.isArray(lock))
|
|
40
|
+
throw new Error('not a JSON object');
|
|
41
|
+
if (typeof lock.lockfileVersion !== 'number') {
|
|
42
|
+
throw new Error('not an npm lockfile (no numeric lockfileVersion)');
|
|
43
|
+
}
|
|
44
|
+
const packages = lock.packages;
|
|
45
|
+
const prefix = (importer) => (importer ? `${importer}/` : '');
|
|
46
|
+
return {
|
|
47
|
+
file,
|
|
48
|
+
members: () => packages ? Object.keys(packages).filter((k) => k !== '' && !k.includes('node_modules/')) : [],
|
|
49
|
+
hasImporter: (importer) => importer === '' || !!packages?.[importer],
|
|
50
|
+
recordedSpec(importer, name) {
|
|
51
|
+
if (!packages)
|
|
52
|
+
return null; // v1 records no specs
|
|
53
|
+
const pkg = packages[importer];
|
|
54
|
+
if (!pkg)
|
|
55
|
+
return undefined;
|
|
56
|
+
for (const field of DEP_FIELDS) {
|
|
57
|
+
const v = pkg[field]?.[name];
|
|
58
|
+
if (typeof v === 'string')
|
|
59
|
+
return v;
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
},
|
|
63
|
+
resolve(importer, name) {
|
|
64
|
+
if (!packages) {
|
|
65
|
+
const v = lock.dependencies?.[name]?.version;
|
|
66
|
+
if (typeof v !== 'string')
|
|
67
|
+
return undefined;
|
|
68
|
+
const alias = /^npm:((?:@[^/@]+\/)?[^@]+)@(.+)$/.exec(v);
|
|
69
|
+
return alias ? { version: alias[2], realName: alias[1] } : { version: v };
|
|
70
|
+
}
|
|
71
|
+
const entry = packages[`${prefix(importer)}node_modules/${name}`] ?? packages[`node_modules/${name}`];
|
|
72
|
+
if (!entry)
|
|
73
|
+
return undefined;
|
|
74
|
+
if (entry.link === true)
|
|
75
|
+
return { local: true };
|
|
76
|
+
const realName = typeof entry.name === 'string' && entry.name !== name ? entry.name : undefined;
|
|
77
|
+
return typeof entry.version === 'string' ? { version: entry.version, ...(realName ? { realName } : {}) } : undefined;
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// ============================================================================
|
|
82
|
+
// pnpm (pnpm-lock.yaml)
|
|
83
|
+
// ============================================================================
|
|
84
|
+
const unquote = (s) => s.trim().replace(/^['"]|['"]$/g, '');
|
|
85
|
+
const indentOf = (line) => line.length - line.trimStart().length;
|
|
86
|
+
/** Read the dependency sections of one importer block (lines [start, end), sections at `base`). */
|
|
87
|
+
function pnpmDeps(lines, start, end, base) {
|
|
88
|
+
const deps = new Map();
|
|
89
|
+
const specifiers = new Map();
|
|
90
|
+
let section = null;
|
|
91
|
+
for (let i = start; i < end; i++) {
|
|
92
|
+
const line = lines[i];
|
|
93
|
+
if (!line.trim() || line.trimStart().startsWith('#'))
|
|
94
|
+
continue;
|
|
95
|
+
const ind = indentOf(line);
|
|
96
|
+
if (ind === base) {
|
|
97
|
+
const head = line.trim();
|
|
98
|
+
section = /^(dependencies|devDependencies|optionalDependencies):\s*$/.test(head) ? 'deps'
|
|
99
|
+
: /^specifiers:\s*$/.test(head) ? 'specifiers' : null;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (!section || ind !== base + 2)
|
|
103
|
+
continue;
|
|
104
|
+
const m = splitKeyValue(line.trim());
|
|
105
|
+
if (!m)
|
|
106
|
+
continue;
|
|
107
|
+
const name = unquote(m[1]);
|
|
108
|
+
if (section === 'specifiers') {
|
|
109
|
+
specifiers.set(name, unquote(m[2]));
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const dep = {};
|
|
113
|
+
if (m[2]) {
|
|
114
|
+
dep.version = unquote(m[2]);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
for (let j = i + 1; j < end && (lines[j].trim() === '' || indentOf(lines[j]) > ind); j++) {
|
|
118
|
+
const kv = splitKeyValue(lines[j].trim());
|
|
119
|
+
if (kv && (kv[1] === 'specifier' || kv[1] === 'version') && kv[2])
|
|
120
|
+
dep[kv[1]] = unquote(kv[2]);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
deps.set(name, dep);
|
|
124
|
+
}
|
|
125
|
+
for (const [name, spec] of specifiers) {
|
|
126
|
+
const dep = deps.get(name);
|
|
127
|
+
if (dep && dep.specifier === undefined)
|
|
128
|
+
dep.specifier = spec;
|
|
129
|
+
}
|
|
130
|
+
return deps;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* `key: value` split at the first colon (non-empty key), the value without its
|
|
134
|
+
* leading whitespace. Linear string code instead of /^(.+?):\s*(.*)$/, whose
|
|
135
|
+
* adjacent quantifiers backtrack polynomially (CodeQL js/polynomial-redos).
|
|
136
|
+
* Index 0 is the whole line, as in a RegExp match.
|
|
137
|
+
*/
|
|
138
|
+
function splitKeyValue(line) {
|
|
139
|
+
const colon = line.indexOf(':');
|
|
140
|
+
if (colon <= 0)
|
|
141
|
+
return null;
|
|
142
|
+
let start = colon + 1;
|
|
143
|
+
while (start < line.length && /\s/.test(line[start]))
|
|
144
|
+
start++;
|
|
145
|
+
return [line, line.slice(0, colon), line.slice(start)];
|
|
146
|
+
}
|
|
147
|
+
/** `s` up to (not including) the first `ch`; linear, unlike /ch.*$/. */
|
|
148
|
+
function cutAt(s, ch) {
|
|
149
|
+
const i = s.indexOf(ch);
|
|
150
|
+
return i < 0 ? s : s.slice(0, i);
|
|
151
|
+
}
|
|
152
|
+
/** A pnpm alias target: a valid npm package name (optionally scoped), then "@" or "/" and a version. */
|
|
153
|
+
const PNPM_ALIAS = /^(?:npm:|\/)?((?:@[a-zA-Z0-9~-][a-zA-Z0-9._~-]*\/)?[a-zA-Z0-9~-][a-zA-Z0-9._~-]*)[@/](\d\S*)$/;
|
|
154
|
+
function pnpmIndex(text) {
|
|
155
|
+
const lines = text.split(/\r?\n/);
|
|
156
|
+
const importers = new Map();
|
|
157
|
+
const importersAt = lines.findIndex((l) => /^importers:\s*$/.test(l));
|
|
158
|
+
if (importersAt >= 0) {
|
|
159
|
+
let end = lines.findIndex((l, i) => i > importersAt && l.trim() !== '' && indentOf(l) === 0);
|
|
160
|
+
if (end < 0)
|
|
161
|
+
end = lines.length;
|
|
162
|
+
for (let i = importersAt + 1; i < end; i++) {
|
|
163
|
+
const line = lines[i];
|
|
164
|
+
if (indentOf(line) !== 2 || !line.trimEnd().endsWith(':'))
|
|
165
|
+
continue;
|
|
166
|
+
const key = unquote(line.trim().slice(0, -1));
|
|
167
|
+
// Scan forward from this importer (a findIndex from line 0 per importer was quadratic).
|
|
168
|
+
let next = i + 1;
|
|
169
|
+
while (next < end && (lines[next].trim() === '' || indentOf(lines[next]) > 2))
|
|
170
|
+
next++;
|
|
171
|
+
importers.set(key === '.' ? '' : key, pnpmDeps(lines, i + 1, next, 4));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
importers.set('', pnpmDeps(lines, 0, lines.length, 0));
|
|
176
|
+
}
|
|
177
|
+
const parseVersion = (raw) => {
|
|
178
|
+
const v = cutAt(raw, '(').trim();
|
|
179
|
+
if (v.startsWith('link:') || v.startsWith('file:') || v.startsWith('workspace:'))
|
|
180
|
+
return { local: true };
|
|
181
|
+
// A plain version, with a peer suffix: v5 "16.0.0_react@16.0.0" / "18.2.0_@types+react@18.0.0",
|
|
182
|
+
// v6+ "16.0.0(react@16.0.0)" (already cut at "("). Never an alias (#1049 scope-cut re-check).
|
|
183
|
+
if (/^\d/.test(v))
|
|
184
|
+
return { version: cutAt(v, '_') };
|
|
185
|
+
// An alias: v5 "/name/1.2.3", v6 "/name@1.2.3", v9 "name@1.2.3", or "npm:name@1.2.3".
|
|
186
|
+
const alias = PNPM_ALIAS.exec(v);
|
|
187
|
+
if (alias)
|
|
188
|
+
return { version: cutAt(alias[2], '_'), realName: alias[1] };
|
|
189
|
+
return { version: cutAt(v, '_') };
|
|
190
|
+
};
|
|
191
|
+
return {
|
|
192
|
+
file: 'pnpm-lock.yaml',
|
|
193
|
+
members: () => [...importers.keys()].filter((k) => k !== ''),
|
|
194
|
+
hasImporter: (importer) => importer === '' || importers.has(importer),
|
|
195
|
+
recordedSpec(importer, name) {
|
|
196
|
+
const deps = importers.get(importer);
|
|
197
|
+
if (!deps)
|
|
198
|
+
return undefined;
|
|
199
|
+
const dep = deps.get(name);
|
|
200
|
+
if (!dep)
|
|
201
|
+
return undefined;
|
|
202
|
+
return dep.specifier ?? null;
|
|
203
|
+
},
|
|
204
|
+
resolve(importer, name) {
|
|
205
|
+
const dep = importers.get(importer)?.get(name);
|
|
206
|
+
return dep?.version ? parseVersion(dep.version) : undefined;
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
// ============================================================================
|
|
211
|
+
// yarn (yarn.lock, classic and berry)
|
|
212
|
+
// ============================================================================
|
|
213
|
+
function yarnIndex(text) {
|
|
214
|
+
const entries = new Map();
|
|
215
|
+
const lines = text.split(/\r?\n/);
|
|
216
|
+
for (let i = 0; i < lines.length; i++) {
|
|
217
|
+
const header = lines[i];
|
|
218
|
+
if (!header || /^\s|^#/.test(header) || !header.trimEnd().endsWith(':'))
|
|
219
|
+
continue;
|
|
220
|
+
let version = '';
|
|
221
|
+
let resolution = '';
|
|
222
|
+
for (let j = i + 1; j < lines.length && /^\s/.test(lines[j]); j++) {
|
|
223
|
+
const v = /^\s+version:?\s+"?([^"\s]+)"?\s*$/.exec(lines[j]);
|
|
224
|
+
if (v && !version)
|
|
225
|
+
version = v[1];
|
|
226
|
+
const r = /^\s+resolution:\s+"?([^"\s]+)"?\s*$/.exec(lines[j]);
|
|
227
|
+
if (r)
|
|
228
|
+
resolution = r[1];
|
|
229
|
+
}
|
|
230
|
+
if (!version)
|
|
231
|
+
continue;
|
|
232
|
+
const local = version === '0.0.0-use.local' || /@(workspace|link|portal|file):/.test(resolution);
|
|
233
|
+
const realName = /^((?:@[^/@]+\/)?[^@]+)@npm:/.exec(resolution)?.[1];
|
|
234
|
+
for (const raw of header.trimEnd().slice(0, -1).split(',')) {
|
|
235
|
+
const key = unquote(raw);
|
|
236
|
+
entries.set(key, local ? { local: true } : { version, ...(realName && !key.startsWith(`${realName}@`) ? { realName } : {}) });
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
file: 'yarn.lock',
|
|
241
|
+
members: () => [],
|
|
242
|
+
hasImporter: () => true,
|
|
243
|
+
// yarn.lock is matched by `name@spec`, so a changed spec simply finds no entry.
|
|
244
|
+
recordedSpec: () => null,
|
|
245
|
+
resolve: (_importer, name, spec) => entries.get(`${name}@${spec}`) ?? entries.get(`${name}@npm:${spec}`),
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=lockfile-versions.js.map
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Common types, interfaces, and patterns used across all scanner modules
|
|
4
4
|
*/
|
|
5
5
|
import type { MemoryBackend } from '@kernel/interfaces.js';
|
|
6
|
-
import type { Vulnerability, VulnerabilitySeverity, VulnerabilityCategory, VulnerabilityLocation, RemediationAdvice, ScanSummary, SecurityCoverage, ScanStatus, SASTResult, DASTResult, DASTOptions, AuthCredentials, RuleSet, FalsePositiveCheck } from '../../interfaces.js';
|
|
6
|
+
import type { Vulnerability, VulnerabilitySeverity, VulnerabilityCategory, VulnerabilityLocation, RemediationAdvice, ScanSummary, SecurityCoverage, ScanStatus, SASTResult, DASTResult, DASTOptions, AuthCredentials, RuleSet, FalsePositiveCheck, UncheckedDependency, LocalDependency } from '../../interfaces.js';
|
|
7
7
|
import type { HybridRouter, ChatResponse } from '@shared/llm/index.js';
|
|
8
8
|
/**
|
|
9
9
|
* Combined security scanner configuration
|
|
@@ -31,16 +31,44 @@ export interface SecurityScannerDependencies {
|
|
|
31
31
|
llmRouter?: HybridRouter;
|
|
32
32
|
}
|
|
33
33
|
export declare const DEFAULT_CONFIG: SecurityScannerConfig;
|
|
34
|
+
/**
|
|
35
|
+
* Completeness of a dependency advisory scan (#1049).
|
|
36
|
+
* - complete: every dependency was checked; the findings (or none) are a measurement.
|
|
37
|
+
* - incomplete: some dependencies were checked (their findings are real), others not.
|
|
38
|
+
* - failed: no dependency could be checked. Never read as "0 vulnerabilities".
|
|
39
|
+
*/
|
|
40
|
+
export type DependencyScanStatus = 'complete' | 'incomplete' | 'failed';
|
|
34
41
|
/**
|
|
35
42
|
* Dependency scan result
|
|
36
43
|
*/
|
|
37
44
|
export interface DependencyScanResult {
|
|
38
45
|
readonly scanId: string;
|
|
39
46
|
readonly vulnerabilities: Vulnerability[];
|
|
47
|
+
/** Dependencies submitted to the scan (checked or not). */
|
|
40
48
|
readonly packagesScanned: number;
|
|
41
49
|
readonly vulnerablePackages: number;
|
|
42
50
|
readonly summary: ScanSummary;
|
|
43
51
|
readonly scanDurationMs: number;
|
|
52
|
+
readonly status: DependencyScanStatus;
|
|
53
|
+
/** True only when status is 'complete'. */
|
|
54
|
+
readonly measured: boolean;
|
|
55
|
+
/** Dependencies whose advisories were actually checked. */
|
|
56
|
+
readonly packagesChecked: number;
|
|
57
|
+
readonly uncheckedPackages: UncheckedDependency[];
|
|
58
|
+
/** Lockfile the checked versions were resolved from (path relative to package.json), or null when none was used. */
|
|
59
|
+
readonly lockfile?: string | null;
|
|
60
|
+
/** Local workspace / linked packages: not OSV subjects, never make the scan incomplete. */
|
|
61
|
+
readonly localPackages?: LocalDependency[];
|
|
62
|
+
/**
|
|
63
|
+
* Why the scan cannot be complete beyond individual packages: a malformed
|
|
64
|
+
* lockfile, or a workspace root whose members are not scanned (#1057).
|
|
65
|
+
* Non-empty means the scan is not complete.
|
|
66
|
+
*/
|
|
67
|
+
readonly resolutionErrors?: string[];
|
|
68
|
+
/** Only the direct dependencies of the scanned package.json are checked. */
|
|
69
|
+
readonly scope?: 'direct';
|
|
70
|
+
/** Why the scan is incomplete/failed; absent when complete. */
|
|
71
|
+
readonly error?: string;
|
|
44
72
|
}
|
|
45
73
|
/**
|
|
46
74
|
* Full scan result combining SAST and DAST
|
|
@@ -89,5 +117,5 @@ export interface MutableScanSummary {
|
|
|
89
117
|
totalFiles: number;
|
|
90
118
|
scanDurationMs: number;
|
|
91
119
|
}
|
|
92
|
-
export type { Vulnerability, VulnerabilitySeverity, VulnerabilityCategory, VulnerabilityLocation, RemediationAdvice, ScanSummary, SecurityCoverage, ScanStatus, SASTResult, DASTResult, DASTOptions, AuthCredentials, RuleSet, FalsePositiveCheck, MemoryBackend, HybridRouter, ChatResponse, };
|
|
120
|
+
export type { Vulnerability, VulnerabilitySeverity, VulnerabilityCategory, VulnerabilityLocation, RemediationAdvice, ScanSummary, SecurityCoverage, ScanStatus, SASTResult, DASTResult, DASTOptions, AuthCredentials, RuleSet, FalsePositiveCheck, UncheckedDependency, LocalDependency, MemoryBackend, HybridRouter, ChatResponse, };
|
|
93
121
|
//# sourceMappingURL=scanner-types.d.ts.map
|