@maycombhq/atticus 2.0.0-beta.22 → 2.0.0-beta.24
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/dist/bin.js +12 -7
- package/dist/{chunk-J2JAKCIW.js → chunk-25CUJJTP.js} +511 -291
- package/dist/chunk-26AB2WNW.js +62 -0
- package/dist/{chunk-VBTP56CE.js → chunk-2ITYURTR.js} +9 -8
- package/dist/{chunk-6ZJ5A7AF.js → chunk-2JHE75RW.js} +13 -11
- package/dist/{chunk-QFWA2DPH.js → chunk-37UTWGU4.js} +8 -6
- package/dist/{chunk-VW62D6QE.js → chunk-3BEGKSDW.js} +14 -12
- package/dist/{chunk-3RM4UK6W.js → chunk-3FGQFDS4.js} +20 -18
- package/dist/{chunk-23XVSEV5.js → chunk-3NS4RS3C.js} +20 -18
- package/dist/{chunk-FSMSFDLD.js → chunk-3TGX4SJ3.js} +10 -7
- package/dist/{chunk-7JITZFJC.js → chunk-3UMKLB6P.js} +7 -5
- package/dist/chunk-3VS7RNEB.js +96 -0
- package/dist/{chunk-AJYXNTNZ.js → chunk-3XCCT2GR.js} +167 -42
- package/dist/{chunk-XERYFDB5.js → chunk-3XZRYQWU.js} +38 -34
- package/dist/{chunk-FUJM6RTF.js → chunk-432FGEVB.js} +9 -7
- package/dist/{chunk-SFUP7TTO.js → chunk-44QUCNPH.js} +7 -5
- package/dist/{chunk-O5PXQR67.js → chunk-4CS3PMIM.js} +15 -13
- package/dist/{chunk-RGERPOIV.js → chunk-4DCIUKIE.js} +22 -12
- package/dist/{chunk-RLDGWLQ7.js → chunk-4DX4DIND.js} +9 -7
- package/dist/chunk-4MNMOUU7.js +108 -0
- package/dist/{chunk-SLXZOMA6.js → chunk-4RKIOUPA.js} +9 -7
- package/dist/{chunk-AJQ72EBM.js → chunk-532HDXMM.js} +9 -7
- package/dist/{chunk-CADWLE2T.js → chunk-5EIKOU7L.js} +6 -4
- package/dist/{chunk-CQDGOPGH.js → chunk-5FPAKAGE.js} +7 -5
- package/dist/{chunk-IVBOQAGB.js → chunk-5FUFVNXB.js} +27 -3
- package/dist/{chunk-UUU4CLJG.js → chunk-5MKV4TV6.js} +5 -1
- package/dist/{chunk-ZQXZ2SES.js → chunk-5ORLKITZ.js} +23 -21
- package/dist/{chunk-OHVTTOPS.js → chunk-5PSKLTBR.js} +3 -3
- package/dist/{chunk-RUGXBPWI.js → chunk-5QF5W5P2.js} +10 -10
- package/dist/{chunk-BPK5P77O.js → chunk-5Z7L2TSR.js} +3 -3
- package/dist/{chunk-L27SV425.js → chunk-66DWUSNY.js} +22 -20
- package/dist/{chunk-JAVI7JSP.js → chunk-6FIYEB7M.js} +25 -22
- package/dist/{chunk-VY72R2XZ.js → chunk-6OZAQPU5.js} +532 -358
- package/dist/{chunk-AFWUDXEM.js → chunk-6TNQO76I.js} +34 -17
- package/dist/{chunk-WF7B67YE.js → chunk-6UTD5RQH.js} +18 -16
- package/dist/{chunk-HNM2YQT2.js → chunk-775FMPUB.js} +7 -7
- package/dist/{chunk-7ASNL4Q4.js → chunk-77AZRGWE.js} +19 -16
- package/dist/{chunk-WKUJ3KPV.js → chunk-7HWCEDPX.js} +7 -5
- package/dist/{chunk-G6X77UJZ.js → chunk-7U46TCRZ.js} +25 -22
- package/dist/{chunk-O45HFTFS.js → chunk-A3NUZJFI.js} +4 -2
- package/dist/{chunk-UPOY4YSQ.js → chunk-A4VDFIMR.js} +14 -12
- package/dist/{chunk-EMRIQUND.js → chunk-A53IYUCR.js} +87 -29
- package/dist/{chunk-S4PMJU6H.js → chunk-A6ZG3UOS.js} +108 -50
- package/dist/{chunk-PMUAJGLI.js → chunk-AAY6VPPO.js} +18 -16
- package/dist/{chunk-MG4ZL5RW.js → chunk-ABDE5IRC.js} +18 -16
- package/dist/{chunk-T6DQR5TV.js → chunk-AM7PYKVP.js} +15 -13
- package/dist/{chunk-SFSPGFCV.js → chunk-ANUMIPF6.js} +22 -20
- package/dist/{chunk-VTZMAJ3W.js → chunk-ASFRT33J.js} +11 -9
- package/dist/{chunk-7FTTA3HD.js → chunk-AWDCVZYO.js} +9 -7
- package/dist/{chunk-KFAVQZSX.js → chunk-B63NWU3P.js} +14 -12
- package/dist/{chunk-YYY3AZFE.js → chunk-BBZ6UKN3.js} +16 -5
- package/dist/{chunk-Q4K5WB2W.js → chunk-BFQ5IKQA.js} +12 -10
- package/dist/{chunk-ZFL7NY4F.js → chunk-BLVFHN3C.js} +73 -42
- package/dist/{chunk-MO6P2JZH.js → chunk-BQXAHIZ6.js} +10 -8
- package/dist/{chunk-Y2EQNWKV.js → chunk-BTS56NV7.js} +91 -41
- package/dist/{chunk-UGUP3ZM6.js → chunk-BWYW533C.js} +18 -16
- package/dist/{chunk-O7FDLW7L.js → chunk-BYKWWSXL.js} +14 -12
- package/dist/chunk-C7BB6IQT.js +147 -0
- package/dist/{chunk-JLUCKAEL.js → chunk-CCQWQFOT.js} +19 -17
- package/dist/{chunk-SYV5LHML.js → chunk-CCQZN6W3.js} +35 -33
- package/dist/{chunk-UCROWG2D.js → chunk-CFSBBLDD.js} +28 -25
- package/dist/{chunk-EIPTLPFC.js → chunk-CFSHLQPK.js} +26 -24
- package/dist/{chunk-2IIMFOPM.js → chunk-CI4D6VSU.js} +20 -18
- package/dist/{chunk-66PPNOON.js → chunk-CKRPMRFQ.js} +28 -25
- package/dist/{chunk-IUPG3UKI.js → chunk-CNF2EZ6S.js} +191 -125
- package/dist/chunk-CTJHEG6A.js +97 -0
- package/dist/{chunk-DOBQKHIF.js → chunk-CU7ZK7KP.js} +30 -29
- package/dist/{chunk-745DAZ4L.js → chunk-CZ75S2EZ.js} +886 -313
- package/dist/{chunk-LGFL54FP.js → chunk-D5CJEKZI.js} +11 -4
- package/dist/{chunk-PBPBMP2B.js → chunk-D5ZC7IMC.js} +5 -3
- package/dist/{chunk-LZ7NUC62.js → chunk-D63NU53X.js} +20 -18
- package/dist/{chunk-BO4KX37X.js → chunk-DCQSPSXU.js} +28 -23
- package/dist/{chunk-WXFLMQSR.js → chunk-DCRZ3OQ7.js} +8 -6
- package/dist/chunk-DD2AXECF.js +41 -0
- package/dist/{chunk-4EURQWQD.js → chunk-DF6DPCW2.js} +16 -14
- package/dist/{chunk-53T4O55J.js → chunk-DH3EQMIA.js} +5 -3
- package/dist/{chunk-ZX57KSEQ.js → chunk-DIXA74N7.js} +5 -3
- package/dist/{chunk-6ZGLAACW.js → chunk-DIYNRYXW.js} +2 -2
- package/dist/chunk-DYDNW4O6.js +52 -0
- package/dist/{chunk-P2V7QW4D.js → chunk-E7YDJH6B.js} +16 -14
- package/dist/chunk-EEKQI3U4.js +45 -0
- package/dist/{chunk-GZY6RUZ6.js → chunk-EHF2MBGR.js} +9 -4
- package/dist/chunk-EHXDB3SA.js +25 -0
- package/dist/{chunk-PJSJPMJI.js → chunk-ENZ3PI7L.js} +3 -3
- package/dist/{chunk-E3ISYXO3.js → chunk-EPQQ2XVM.js} +16 -14
- package/dist/{chunk-7IGKHZ4Z.js → chunk-ESJALLOK.js} +222 -213
- package/dist/chunk-ETQSQ2EC.js +33 -0
- package/dist/{chunk-MFR5OPBD.js → chunk-EUMXLSW5.js} +14 -6
- package/dist/{chunk-BTY3HZBO.js → chunk-F63F4NKT.js} +18 -16
- package/dist/{chunk-ZFFYNRIO.js → chunk-FDL2JOLB.js} +26 -22
- package/dist/{chunk-5SJZW52K.js → chunk-FFDVAV56.js} +24 -22
- package/dist/chunk-FFYOZ7PF.js +27 -0
- package/dist/{chunk-RXPJMEOW.js → chunk-FGW5TLGM.js} +24 -19
- package/dist/{chunk-UPS2DGFC.js → chunk-FL53R4SW.js} +1 -1
- package/dist/chunk-FYWLB7PO.js +38 -0
- package/dist/{chunk-FFLNS6VP.js → chunk-G3W7GNEP.js} +24 -18
- package/dist/chunk-G3ZFEHCX.js +925 -0
- package/dist/{chunk-YHCMZC2J.js → chunk-G67GOK4S.js} +10 -8
- package/dist/{chunk-2F4CYZKJ.js → chunk-GCMDDVIE.js} +14 -9
- package/dist/{chunk-QKUJMING.js → chunk-GFYVVTKH.js} +10 -8
- package/dist/chunk-GJVCBTSO.js +20722 -0
- package/dist/{chunk-VCTWPLAO.js → chunk-GKZDHXC2.js} +8 -8
- package/dist/{chunk-5BD2KYLE.js → chunk-GQFUEUC7.js} +18 -16
- package/dist/chunk-GQPP4P2E.js +33 -0
- package/dist/{chunk-42SIDKEU.js → chunk-GS7N3RFG.js} +51 -32
- package/dist/{chunk-LJXMYKZJ.js → chunk-GXQYEIYM.js} +7 -5
- package/dist/{chunk-VNU26RCO.js → chunk-H5EQOSTC.js} +43 -33
- package/dist/{chunk-W7VWI2YH.js → chunk-H7KERB6Q.js} +7 -5
- package/dist/{chunk-OUBGGKDU.js → chunk-HGDBM3A5.js} +5 -3
- package/dist/{chunk-JENSEMXF.js → chunk-HI7ADE4E.js} +1 -1
- package/dist/{chunk-CXJ6FUKN.js → chunk-HNPKCRCE.js} +1010 -330
- package/dist/{chunk-FPJPLKDW.js → chunk-HRHXTLUM.js} +40 -16
- package/dist/{chunk-57TDNMI3.js → chunk-HRYI22QU.js} +17 -15
- package/dist/{chunk-LO6P2VYG.js → chunk-HWNFFCGB.js} +5 -3
- package/dist/{chunk-XI2LCCYQ.js → chunk-HXFZX2BI.js} +12 -8
- package/dist/{chunk-H7KM7LZE.js → chunk-HYHV2P3G.js} +16 -13
- package/dist/{chunk-X3WY6MN3.js → chunk-IB66ZLDN.js} +10 -8
- package/dist/{chunk-3NFFJL5D.js → chunk-IJQHBK76.js} +1 -1
- package/dist/{chunk-LQJPN536.js → chunk-IK6LHW3E.js} +6 -4
- package/dist/{chunk-DCZWQLYT.js → chunk-IOHRX4KF.js} +26 -21
- package/dist/{chunk-2GF7OLF3.js → chunk-IRXZKKCG.js} +21 -15
- package/dist/{chunk-Z5IA3WDR.js → chunk-IUBBEU6O.js} +160 -81
- package/dist/{chunk-W62H2XSO.js → chunk-IWPO5AUT.js} +29 -26
- package/dist/{chunk-BEVTIBRH.js → chunk-J4K4C4T5.js} +31 -15
- package/dist/{chunk-WERM6KPJ.js → chunk-JCEYOSST.js} +14 -6
- package/dist/{chunk-HYU5VLGA.js → chunk-JCG2EBNB.js} +1 -1
- package/dist/{chunk-UNAGJYET.js → chunk-JFBVIMGY.js} +14 -12
- package/dist/chunk-JJ4SCGRJ.js +43 -0
- package/dist/{chunk-2Q5EDGEO.js → chunk-JLYH2QOE.js} +7 -5
- package/dist/{chunk-X4CXA2IL.js → chunk-JMH6TCZJ.js} +23 -21
- package/dist/{chunk-6PPOWY5E.js → chunk-JUHZBZPZ.js} +17 -13
- package/dist/{chunk-GUX3PTYM.js → chunk-JVMNEI7B.js} +3 -3
- package/dist/chunk-JYJMIAFS.js +44 -0
- package/dist/{chunk-34S2WGOB.js → chunk-KIY2WCN7.js} +7 -3
- package/dist/chunk-KVVNAUIG.js +66 -0
- package/dist/{chunk-M32BLWDH.js → chunk-KYO5HT4G.js} +14 -12
- package/dist/chunk-L27KUL5B.js +38 -0
- package/dist/chunk-L3PIN47C.js +18 -0
- package/dist/{chunk-IH2XURVQ.js → chunk-L6Z6TMIK.js} +5 -5
- package/dist/{chunk-E6ZIEVOI.js → chunk-LAGZBQHK.js} +16 -13
- package/dist/chunk-LBG4GMOR.js +68 -0
- package/dist/{chunk-UF4GLFBX.js → chunk-LDKP7OWQ.js} +33 -24
- package/dist/{chunk-ZQ7SKESZ.js → chunk-LELM7X5H.js} +13 -11
- package/dist/{chunk-INQHESFB.js → chunk-LIB6AUZS.js} +6 -4
- package/dist/{chunk-H5HBGNXU.js → chunk-LIQWFDOZ.js} +6 -4
- package/dist/{chunk-TYQBFTBR.js → chunk-LKUTBQ2Y.js} +8 -6
- package/dist/{chunk-7BR7IPOH.js → chunk-LOCJHNZI.js} +10 -8
- package/dist/{chunk-SQV37XO2.js → chunk-LTIXFLYE.js} +6 -6
- package/dist/{chunk-3NWDLGG6.js → chunk-M3RWF7MC.js} +33 -29
- package/dist/chunk-MA6UK7GX.js +42 -0
- package/dist/{chunk-ISUAAMGS.js → chunk-MCE74XMF.js} +25 -16
- package/dist/{chunk-EGQRREQH.js → chunk-MDTAZ6NE.js} +37 -24
- package/dist/{chunk-ZZK56BLP.js → chunk-MMOMKHAX.js} +6 -4
- package/dist/{chunk-P32RUW3B.js → chunk-MOWUP33K.js} +49 -15
- package/dist/{chunk-UOR2DTHH.js → chunk-MPATOMY5.js} +18 -14
- package/dist/{chunk-LNBQOP7D.js → chunk-MQFSEGTU.js} +23 -21
- package/dist/{chunk-2Q56PQPS.js → chunk-MT3FNSXO.js} +4 -4
- package/dist/{chunk-FZOJFH7Q.js → chunk-MUY5MAGM.js} +15 -12
- package/dist/{chunk-7DOR27HL.js → chunk-MVXMISNA.js} +9 -7
- package/dist/{chunk-CX4RZ2KS.js → chunk-MWN7CBVL.js} +5 -3
- package/dist/{chunk-BXYMYEJ4.js → chunk-MZWM73S2.js} +18 -17
- package/dist/chunk-NBZ7RKX3.js +46 -0
- package/dist/{chunk-EPCJQQWD.js → chunk-NC56V6KQ.js} +6 -4
- package/dist/{chunk-7UOMVMFG.js → chunk-NN6AXKFX.js} +17 -15
- package/dist/{chunk-BIGDQDHD.js → chunk-NOU5IBLM.js} +6 -4
- package/dist/{chunk-LFGTYX5U.js → chunk-NQDHRT2H.js} +20 -18
- package/dist/{chunk-KDNTAPLX.js → chunk-NTEPBOAF.js} +6 -4
- package/dist/{chunk-LYBNHMVZ.js → chunk-NTOPAOBY.js} +3 -3
- package/dist/{chunk-R44CYFPV.js → chunk-NX5IPHI3.js} +19 -16
- package/dist/{chunk-GCWRWSU7.js → chunk-O4ZWZZZT.js} +6 -4
- package/dist/chunk-OCU5S2XG.js +36 -0
- package/dist/{chunk-SU74NDMQ.js → chunk-OKSRK2LJ.js} +19 -17
- package/dist/{chunk-XD75VZIH.js → chunk-OSWOIFRQ.js} +9 -7
- package/dist/{chunk-PKBHS4AA.js → chunk-OSZTENIA.js} +54 -21
- package/dist/{chunk-NDCF4R6S.js → chunk-OTUBMKSG.js} +10 -8
- package/dist/{chunk-THDMSZ3R.js → chunk-OYKNPZCV.js} +2837 -693
- package/dist/{chunk-ZQ3ON2VQ.js → chunk-OYTSRNSZ.js} +8 -6
- package/dist/chunk-OYZ64UMQ.js +67 -0
- package/dist/{chunk-UF4AZOZB.js → chunk-PB3NCPRF.js} +10 -8
- package/dist/chunk-PIPJZIJE.js +47 -0
- package/dist/{chunk-2RLKFUUL.js → chunk-PIPYJTIL.js} +27 -24
- package/dist/{chunk-MZCGSXVR.js → chunk-PUMNCWHJ.js} +15 -13
- package/dist/{chunk-X5F3Q5LV.js → chunk-PZBNDFZ7.js} +35 -25
- package/dist/chunk-Q2ULHBCJ.js +59 -0
- package/dist/{chunk-ZJFRMSJT.js → chunk-Q5QSWV2R.js} +14 -12
- package/dist/{chunk-Q2TECDIT.js → chunk-QFDPX6C4.js} +2886 -20703
- package/dist/{chunk-WG5U3F5V.js → chunk-QGBS4GMS.js} +14 -12
- package/dist/{chunk-BTGPE6CR.js → chunk-QIDSEHJA.js} +17 -15
- package/dist/{chunk-Q6DFNVRJ.js → chunk-QJ3AYXVO.js} +14 -12
- package/dist/{chunk-EBL2R3YG.js → chunk-QK6CGRKK.js} +6 -4
- package/dist/{chunk-S7FCV7S5.js → chunk-QOC3Q4UU.js} +1 -1
- package/dist/{chunk-JJF6HALY.js → chunk-QPLNB2BM.js} +5 -3
- package/dist/chunk-QVF4KYIO.js +71 -0
- package/dist/{chunk-6OJQOPUN.js → chunk-QXXEO4TF.js} +5 -3
- package/dist/{chunk-F3P7N7SF.js → chunk-QYFNVQLK.js} +1 -1
- package/dist/{chunk-6MUGR4LS.js → chunk-R6CJOMPC.js} +106 -29
- package/dist/{chunk-BDKC6H5P.js → chunk-ROWZYQOI.js} +9 -7
- package/dist/{chunk-2MMCFP5C.js → chunk-RQAMZVWW.js} +10 -8
- package/dist/chunk-RQSUFGU2.js +55 -0
- package/dist/{chunk-SDKLKB6I.js → chunk-RRKM3GJA.js} +38 -28
- package/dist/{chunk-OHNCWBKF.js → chunk-RSHVSXPJ.js} +7 -5
- package/dist/chunk-RSKMV3VC.js +22 -0
- package/dist/{chunk-U76OWS3Q.js → chunk-RU5W7JJQ.js} +25 -23
- package/dist/{chunk-63YRMR6J.js → chunk-RYY554OA.js} +7 -5
- package/dist/{chunk-5NMKONLP.js → chunk-SGYQORAD.js} +7 -3
- package/dist/{chunk-JA5FI3QV.js → chunk-SLGUSFOD.js} +3 -3
- package/dist/{chunk-M3NANSDZ.js → chunk-SUAHNYNQ.js} +17 -15
- package/dist/{chunk-QAXW2N3B.js → chunk-SUYC5NP6.js} +34 -34
- package/dist/{chunk-FFTRTL6R.js → chunk-SWSGRRNO.js} +6 -4
- package/dist/{chunk-UWOJLHFT.js → chunk-SYLXQNPC.js} +38 -24
- package/dist/chunk-T24TBI7F.js +54 -0
- package/dist/chunk-T2HXLDY3.js +55 -0
- package/dist/{chunk-O4GXGGBX.js → chunk-T5NH5L7A.js} +16 -13
- package/dist/{chunk-KXITGYLF.js → chunk-TAR6T2RE.js} +4 -2
- package/dist/chunk-TBQHBOFF.js +324 -0
- package/dist/{chunk-LKOR5UET.js → chunk-TKE6ZJMM.js} +26 -24
- package/dist/chunk-TKEXS74L.js +52 -0
- package/dist/{chunk-J3IOLXWM.js → chunk-TXYMNKGM.js} +16 -14
- package/dist/{chunk-IDKCWSM5.js → chunk-U2JTTRKS.js} +401 -115
- package/dist/{chunk-TNR75OXT.js → chunk-U37ZOYJJ.js} +11 -8
- package/dist/{chunk-7MJSQTL5.js → chunk-U57VLY6X.js} +23 -21
- package/dist/{chunk-BHT7QK4G.js → chunk-U66RQUFC.js} +6 -4
- package/dist/chunk-UCFNHK5L.js +50 -0
- package/dist/{chunk-IFKEI4SA.js → chunk-UI6KNLSO.js} +31 -11
- package/dist/{chunk-7GJS6DNX.js → chunk-UKRJ2ISN.js} +13 -3
- package/dist/chunk-UWJOM457.js +232 -0
- package/dist/{chunk-D73UEXYW.js → chunk-UXO25YBN.js} +3 -3
- package/dist/chunk-VE2T5URA.js +51 -0
- package/dist/{chunk-C3RY6KU6.js → chunk-W4EG25TI.js} +513 -172
- package/dist/{chunk-O66DM6DJ.js → chunk-WAAPMZWO.js} +6 -4
- package/dist/{chunk-R7NYHMUU.js → chunk-WECCLSYY.js} +4884 -3669
- package/dist/chunk-WQDJGNJQ.js +45 -0
- package/dist/{chunk-UWMJKX5U.js → chunk-WWSCJBF6.js} +14 -12
- package/dist/{chunk-N3XIYPU3.js → chunk-X7HFXXTZ.js} +16 -13
- package/dist/chunk-X7XVMYIL.js +5 -0
- package/dist/{chunk-NR2UJWOC.js → chunk-XERIHPBF.js} +12 -9
- package/dist/{chunk-JRBFANFE.js → chunk-XKNISZ6N.js} +21 -18
- package/dist/{chunk-PPD7HTDP.js → chunk-XNH5ZWIA.js} +20 -18
- package/dist/{chunk-7IOWA5D5.js → chunk-XNW3EDCY.js} +13 -3
- package/dist/{chunk-2LGRMVCA.js → chunk-XPXOKHNZ.js} +13 -11
- package/dist/{chunk-ZJXLNDH4.js → chunk-XXRBAJ36.js} +14 -12
- package/dist/{chunk-EHA7RMZ3.js → chunk-YA2IJJ6N.js} +8 -6
- package/dist/{chunk-LGBMTVNT.js → chunk-YB5AKYVQ.js} +7 -5
- package/dist/{chunk-JB5LINEM.js → chunk-YDDLVBQ4.js} +3 -3
- package/dist/{chunk-PAQ2AS5E.js → chunk-YF6N45QN.js} +1 -1
- package/dist/{chunk-WMTRHUI5.js → chunk-YHWX5LPT.js} +23 -21
- package/dist/{chunk-KQGURXFU.js → chunk-YLZNTVZR.js} +36 -13
- package/dist/{chunk-NY2XSR5K.js → chunk-YUJTOALL.js} +118 -18
- package/dist/{chunk-VZALIKIF.js → chunk-Z5YDTIWQ.js} +19 -16
- package/dist/{chunk-LDLL7LB3.js → chunk-ZCU2UY47.js} +24 -22
- package/dist/{chunk-OWNCM4ZN.js → chunk-ZIAYNHHE.js} +197 -17
- package/dist/{chunk-WJF2CS6M.js → chunk-ZJ2W2RDE.js} +7 -5
- package/dist/{chunk-REWWDVQB.js → chunk-ZRQHSMPK.js} +6 -4
- package/dist/{chunk-O7XLYEFA.js → chunk-ZSD75FYI.js} +57 -23
- package/dist/chunk-ZSNNF26J.js +220 -0
- package/dist/{chunk-BQ4SQQC6.js → chunk-ZX6RAGE6.js} +11 -9
- package/dist/files.json +583 -515
- package/dist/packages/sdk/npm/index.js +6428 -4882
- package/dist/packages/ui/dist/assets/{elk-api-CIf-0gz5.js → elk-api--rH6Kdl4.js} +2 -2
- package/dist/packages/ui/dist/assets/index-Bf2immpE.css +1 -0
- package/dist/packages/ui/dist/assets/index-CH4nGIW3.js +62 -0
- package/dist/packages/ui/dist/index.html +2 -2
- package/package.json +6 -6
- package/dist/chunk-2SKB4O2E.js +0 -59
- package/dist/chunk-4U276ICE.js +0 -39
- package/dist/chunk-6H3Z5JHH.js +0 -64
- package/dist/chunk-AFZ3QA6W.js +0 -47
- package/dist/chunk-AVTBS4OW.js +0 -49
- package/dist/chunk-C4R4JLHE.js +0 -40
- package/dist/chunk-CBGGOQWU.js +0 -82
- package/dist/chunk-CMDXGQTS.js +0 -47
- package/dist/chunk-DLOBCJL6.js +0 -48
- package/dist/chunk-GIW4ZVDB.js +0 -39
- package/dist/chunk-IP74LCOQ.js +0 -57
- package/dist/chunk-IPHHDDC6.js +0 -45
- package/dist/chunk-KJXD4PNL.js +0 -50
- package/dist/chunk-KN5BXMWN.js +0 -44
- package/dist/chunk-MFHL5URL.js +0 -31
- package/dist/chunk-NXJ5URP6.js +0 -51
- package/dist/chunk-OMI6FPPN.js +0 -43
- package/dist/chunk-ONUPY3H6.js +0 -53
- package/dist/chunk-OTLDSZDV.js +0 -69
- package/dist/chunk-PSOFBQWB.js +0 -42
- package/dist/chunk-T4YPZIQN.js +0 -36
- package/dist/chunk-TUULXQRW.js +0 -420
- package/dist/chunk-WNKPRSGI.js +0 -36
- package/dist/packages/ui/dist/assets/index-CoK_Dl0D.js +0 -47
- package/dist/packages/ui/dist/assets/index-Dw20IRhQ.css +0 -1
- package/dist/{chunk-24XLDU72.js → chunk-PXMV2LLY.js} +3 -3
|
@@ -5,30 +5,31 @@ var __atticusUrl = (p) => new URL("./" + p, import.meta.url).href;
|
|
|
5
5
|
var __atticusPath = (p) => __atticusFileURLToPath(__atticusUrl(p));
|
|
6
6
|
import {
|
|
7
7
|
readOpenApiDocument
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-5FPAKAGE.js";
|
|
9
9
|
import {
|
|
10
10
|
globToRegExp
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-IJQHBK76.js";
|
|
12
12
|
import {
|
|
13
13
|
DECLARED_TOPIC,
|
|
14
|
-
DEFAULT_CONVENTIONS,
|
|
15
14
|
Fact,
|
|
16
15
|
FactId,
|
|
17
16
|
JOINED_BY_AI,
|
|
17
|
+
JOINED_BY_BASE_PATH,
|
|
18
18
|
JOINED_BY_PERSON,
|
|
19
19
|
JOINED_TO_SHARED_MAP,
|
|
20
|
+
JOIN_GUESS_FLAGS,
|
|
20
21
|
JOIN_HOW_FLAGS,
|
|
21
22
|
LINK_EVIDENCE_NOT_GAPS,
|
|
22
23
|
MOCK_FILE,
|
|
23
|
-
NEVER_CHECKED_STEPS,
|
|
24
24
|
SHARED_MAP_EVIDENCE,
|
|
25
25
|
citedFiles,
|
|
26
26
|
claimOnLines,
|
|
27
27
|
clusterServiceAddress,
|
|
28
28
|
decodeText,
|
|
29
|
+
dependencyLinkId,
|
|
29
30
|
factIdPart,
|
|
30
31
|
forwardSlashes,
|
|
31
|
-
|
|
32
|
+
hasSecretShape,
|
|
32
33
|
isBinaryText,
|
|
33
34
|
isLfsPointer,
|
|
34
35
|
isPatternPath,
|
|
@@ -36,8 +37,7 @@ import {
|
|
|
36
37
|
lineNamesClaim,
|
|
37
38
|
linksFor,
|
|
38
39
|
listRepoFilesSync,
|
|
39
|
-
|
|
40
|
-
notDeviceName,
|
|
40
|
+
looksLikeSecret,
|
|
41
41
|
noteProblem,
|
|
42
42
|
partsBuildWord,
|
|
43
43
|
partsNamePath,
|
|
@@ -48,9 +48,16 @@ import {
|
|
|
48
48
|
redactSecrets,
|
|
49
49
|
staleCite,
|
|
50
50
|
toCanonicalYaml,
|
|
51
|
-
tokenUnits
|
|
51
|
+
tokenUnits
|
|
52
|
+
} from "./chunk-GJVCBTSO.js";
|
|
53
|
+
import {
|
|
54
|
+
DEFAULT_CONVENTIONS,
|
|
55
|
+
NEVER_CHECKED_STEPS,
|
|
56
|
+
gatewayBundleTest,
|
|
57
|
+
normalizePath,
|
|
58
|
+
notDeviceName,
|
|
52
59
|
underFolders
|
|
53
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-QFDPX6C4.js";
|
|
54
61
|
|
|
55
62
|
// packages/verify/dist/source.js
|
|
56
63
|
import { lstatSync, readFileSync, realpathSync, statSync } from "node:fs";
|
|
@@ -166,6 +173,269 @@ function tooBigToRead(source, path) {
|
|
|
166
173
|
return n !== void 0 && n > MAX_SOURCE_BYTES;
|
|
167
174
|
}
|
|
168
175
|
|
|
176
|
+
// packages/verify/dist/build-coords.js
|
|
177
|
+
var POM = /(^|\/)pom\.xml$|\.pom$/i;
|
|
178
|
+
var GRADLE_BUILD = /(^|\/)build\.gradle(\.kts)?$/i;
|
|
179
|
+
var GRADLE_SETTINGS = /(^|\/)settings\.gradle(\.kts)?$/i;
|
|
180
|
+
var isPomFile = (p) => POM.test(p.replace(/\\/g, "/"));
|
|
181
|
+
var isGradleFile = (p) => GRADLE_BUILD.test(p.replace(/\\/g, "/")) || GRADLE_SETTINGS.test(p.replace(/\\/g, "/"));
|
|
182
|
+
var isBuildFile = (p) => isPomFile(p) || isGradleFile(p);
|
|
183
|
+
var TAG = /<(\/?)([A-Za-z_][\w.:-]*)([^>]*?)(\/?)>/g;
|
|
184
|
+
function pomCoordinates(lines) {
|
|
185
|
+
const out = { dependencies: [] };
|
|
186
|
+
const stack = [];
|
|
187
|
+
let inComment = false;
|
|
188
|
+
const names = () => stack.map((f) => f.name);
|
|
189
|
+
lines.forEach((raw, i) => {
|
|
190
|
+
const n = i + 1;
|
|
191
|
+
let line = "";
|
|
192
|
+
let rest = raw;
|
|
193
|
+
while (rest.length) {
|
|
194
|
+
if (inComment) {
|
|
195
|
+
const end = rest.indexOf("-->");
|
|
196
|
+
if (end < 0)
|
|
197
|
+
break;
|
|
198
|
+
rest = rest.slice(end + 3);
|
|
199
|
+
inComment = false;
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
const start = rest.indexOf("<!--");
|
|
203
|
+
if (start < 0) {
|
|
204
|
+
line += rest;
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
line += rest.slice(0, start);
|
|
208
|
+
rest = rest.slice(start + 4);
|
|
209
|
+
inComment = true;
|
|
210
|
+
}
|
|
211
|
+
let last = 0;
|
|
212
|
+
for (const m of line.matchAll(TAG)) {
|
|
213
|
+
const text = line.slice(last, m.index);
|
|
214
|
+
last = m.index + m[0].length;
|
|
215
|
+
const top2 = stack[stack.length - 1];
|
|
216
|
+
if (top2 && text.trim() && !top2.text) {
|
|
217
|
+
top2.text = text.trim();
|
|
218
|
+
top2.textLine = n;
|
|
219
|
+
}
|
|
220
|
+
if (m[2].startsWith("?") || m[0].startsWith("<!"))
|
|
221
|
+
continue;
|
|
222
|
+
const close = m[1] === "/";
|
|
223
|
+
const selfClosing = m[4] === "/";
|
|
224
|
+
if (!close) {
|
|
225
|
+
if (top2)
|
|
226
|
+
top2.children = true;
|
|
227
|
+
if (selfClosing)
|
|
228
|
+
continue;
|
|
229
|
+
stack.push({ name: m[2], leaves: /* @__PURE__ */ new Map(), children: false, text: "", textLine: n });
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
const at = names().lastIndexOf(m[2]);
|
|
233
|
+
if (at < 0)
|
|
234
|
+
continue;
|
|
235
|
+
while (stack.length > at + 1)
|
|
236
|
+
stack.pop();
|
|
237
|
+
const done = stack.pop();
|
|
238
|
+
const parent = stack[stack.length - 1];
|
|
239
|
+
if (!done.children && done.text && parent)
|
|
240
|
+
parent.leaves.set(done.name, { value: done.text, line: done.textLine });
|
|
241
|
+
const path = [...names(), done.name];
|
|
242
|
+
if (done.name === "dependency") {
|
|
243
|
+
out.dependencies.push({
|
|
244
|
+
...done.leaves.get("groupId") ? { group: done.leaves.get("groupId") } : {},
|
|
245
|
+
...done.leaves.get("artifactId") ? { artifact: done.leaves.get("artifactId") } : {},
|
|
246
|
+
...done.leaves.get("version") ? { version: done.leaves.get("version") } : {},
|
|
247
|
+
...done.leaves.get("scope") ? { scope: done.leaves.get("scope") } : {},
|
|
248
|
+
managed: path.includes("dependencyManagement"),
|
|
249
|
+
plugin: path.includes("plugin") || path.includes("extension")
|
|
250
|
+
});
|
|
251
|
+
} else if (done.name === "parent" && path.length === 2 && path[0] === "project") {
|
|
252
|
+
if (done.leaves.get("groupId"))
|
|
253
|
+
out.parentGroup = done.leaves.get("groupId");
|
|
254
|
+
if (done.leaves.get("artifactId"))
|
|
255
|
+
out.parentArtifact = done.leaves.get("artifactId");
|
|
256
|
+
if (done.leaves.get("version"))
|
|
257
|
+
out.parentVersion = done.leaves.get("version");
|
|
258
|
+
} else if (done.name === "project" && path.length === 1) {
|
|
259
|
+
if (done.leaves.get("groupId"))
|
|
260
|
+
out.group = done.leaves.get("groupId");
|
|
261
|
+
if (done.leaves.get("artifactId"))
|
|
262
|
+
out.artifact = done.leaves.get("artifactId");
|
|
263
|
+
if (done.leaves.get("version"))
|
|
264
|
+
out.version = done.leaves.get("version");
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
const top = stack[stack.length - 1];
|
|
268
|
+
const tail = line.slice(last);
|
|
269
|
+
if (top && tail.trim() && !top.text) {
|
|
270
|
+
top.text = tail.trim();
|
|
271
|
+
top.textLine = n;
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
return out;
|
|
275
|
+
}
|
|
276
|
+
var QUOTED = `(['"])([^'"\\s]+)\\`;
|
|
277
|
+
var GRADLE_DEP = new RegExp(`^\\s*([A-Za-z][\\w]*)\\s*\\(?\\s*(?:(platform|enforcedPlatform)\\s*\\(\\s*)?${QUOTED}3`);
|
|
278
|
+
var GRADLE_MAP_DEP = /^\s*([A-Za-z]\w*)\s*\(?\s*group\s*[:=]\s*(['"])([^'"]+)\2\s*,\s*name\s*[:=]\s*(['"])([^'"]+)\4(?:\s*,\s*version\s*[:=]\s*(['"])([^'"]+)\6)?/;
|
|
279
|
+
var NOT_A_CONFIGURATION = /* @__PURE__ */ new Set(["id", "apply", "plugin", "include", "classpath", "group"]);
|
|
280
|
+
function scopeOfConfiguration(c, platform) {
|
|
281
|
+
if (platform)
|
|
282
|
+
return "import";
|
|
283
|
+
if (/^test/i.test(c))
|
|
284
|
+
return "test";
|
|
285
|
+
if (/^(compileOnly|annotationProcessor|kapt|compileOnlyApi)$/i.test(c))
|
|
286
|
+
return "provided";
|
|
287
|
+
if (/^runtimeOnly$/i.test(c))
|
|
288
|
+
return "runtime";
|
|
289
|
+
return "compile";
|
|
290
|
+
}
|
|
291
|
+
function gradleDependencyOn(line) {
|
|
292
|
+
const map = GRADLE_MAP_DEP.exec(line);
|
|
293
|
+
if (map && !NOT_A_CONFIGURATION.has(map[1]))
|
|
294
|
+
return {
|
|
295
|
+
configuration: map[1],
|
|
296
|
+
group: map[3],
|
|
297
|
+
name: map[5],
|
|
298
|
+
...map[7] ? { version: map[7] } : {},
|
|
299
|
+
scope: scopeOfConfiguration(map[1], false)
|
|
300
|
+
};
|
|
301
|
+
const m = GRADLE_DEP.exec(line);
|
|
302
|
+
if (!m || NOT_A_CONFIGURATION.has(m[1]))
|
|
303
|
+
return void 0;
|
|
304
|
+
const parts = m[4].split(":");
|
|
305
|
+
if (parts.length < 2 || !parts[0] || !parts[1])
|
|
306
|
+
return void 0;
|
|
307
|
+
return {
|
|
308
|
+
configuration: m[1],
|
|
309
|
+
group: parts[0],
|
|
310
|
+
name: parts[1],
|
|
311
|
+
...parts[2] ? { version: parts[2] } : {},
|
|
312
|
+
scope: scopeOfConfiguration(m[1], !!m[2])
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
function gradleGroupOn(line) {
|
|
316
|
+
return /^\s*(?:project\.)?group\s*=?\s*(['"])([^'"]+)\1\s*$/.exec(line)?.[2];
|
|
317
|
+
}
|
|
318
|
+
function gradleNameOn(line) {
|
|
319
|
+
return /^\s*(?:rootProject\.name|archivesBaseName|(?:base\.)?archivesName(?:\.set)?)\s*[=(]?\s*(['"])([^'"]+)\1\s*\)?\s*$/.exec(line)?.[2];
|
|
320
|
+
}
|
|
321
|
+
var PROJECT_GROUP = /^\$\{(project\.|pom\.)?groupId\}$/;
|
|
322
|
+
var citedLine = (f, file, line) => f.cite.file === file && f.cite.line === line || (f.cite.with ?? []).some((p) => p.file === file && p.line === line);
|
|
323
|
+
function buildCoordinatesProblem(f, linesOf2) {
|
|
324
|
+
const file = f.cite.file;
|
|
325
|
+
const label = `${f.kind} ${f.id}`;
|
|
326
|
+
const lines = linesOf2(file);
|
|
327
|
+
if (!lines)
|
|
328
|
+
return void 0;
|
|
329
|
+
const where = `${file}:${f.cite.line}`;
|
|
330
|
+
if (isPomFile(file))
|
|
331
|
+
return pomProblem(f, label, where, pomCoordinates(lines));
|
|
332
|
+
if (isGradleFile(file))
|
|
333
|
+
return gradleProblem(f, label, where, lines, linesOf2);
|
|
334
|
+
return `${label} cites ${file}, which is no build file Atticus reads coordinates from: cite the pom.xml, build.gradle or settings.gradle line that writes them`;
|
|
335
|
+
}
|
|
336
|
+
function pomProblem(f, label, where, pom) {
|
|
337
|
+
const line = f.cite.line;
|
|
338
|
+
const file = f.cite.file;
|
|
339
|
+
if (f.kind === "artifact") {
|
|
340
|
+
if (pom.artifact?.line !== line) {
|
|
341
|
+
const dep2 = pom.dependencies.find((d) => d.artifact?.line === line);
|
|
342
|
+
const what = dep2 ? `a dependency's <artifactId> (${dep2.artifact.value})` : pom.parentArtifact?.line === line ? `the <parent>'s <artifactId> (${pom.parentArtifact.value})` : "not the project's own <artifactId>";
|
|
343
|
+
return `${label} says ${where} is the coordinates the build publishes, and that line is ${what}${pom.artifact ? `: the project's own is at line ${pom.artifact.line}` : ""}`;
|
|
344
|
+
}
|
|
345
|
+
if (pom.artifact.value !== f.name)
|
|
346
|
+
return `${label} names "${f.name}", and ${where} writes the project's artifactId as "${pom.artifact.value}"`;
|
|
347
|
+
const group2 = pom.group ?? pom.parentGroup;
|
|
348
|
+
if (!group2)
|
|
349
|
+
return `${label} names group "${f.group}", and ${file} writes no groupId of the project or its <parent>`;
|
|
350
|
+
if (group2.value !== f.group)
|
|
351
|
+
return `${label} names group "${f.group}", and ${file}:${group2.line} writes "${group2.value}"${pom.group ? "" : " (the <parent>'s, which the project inherits)"}`;
|
|
352
|
+
if (!citedLine(f, file, group2.line))
|
|
353
|
+
return `${label}: the group is written at ${file}:${group2.line}${pom.group ? "" : " (the <parent>'s)"}; cite that line in cite.with`;
|
|
354
|
+
return void 0;
|
|
355
|
+
}
|
|
356
|
+
const dep = pom.dependencies.find((d) => d.artifact?.line === line);
|
|
357
|
+
if (!dep) {
|
|
358
|
+
const what = pom.artifact?.line === line ? "the project's own <artifactId>" : pom.parentArtifact?.line === line ? "the <parent>'s <artifactId>" : "no dependency's <artifactId>";
|
|
359
|
+
return `${label} says ${where} declares a dependency, and that line is ${what}: cite the <artifactId> line of the <dependency> in <dependencies>`;
|
|
360
|
+
}
|
|
361
|
+
if (dep.managed)
|
|
362
|
+
return `${label} cites ${where}, a <dependencyManagement> entry, which only pins a version: cite the dependency where <dependencies> declares it`;
|
|
363
|
+
if (dep.plugin)
|
|
364
|
+
return `${label} cites ${where}, a dependency of a build plugin, not of the component: leave it out`;
|
|
365
|
+
if (dep.artifact.value !== f.name)
|
|
366
|
+
return `${label} names "${f.name}", and ${where} declares "${dep.artifact.value}"`;
|
|
367
|
+
if (!dep.group)
|
|
368
|
+
return `${label}: the <dependency> at ${where} writes no <groupId>`;
|
|
369
|
+
const ownGroup = pom.group ?? pom.parentGroup;
|
|
370
|
+
const group = PROJECT_GROUP.test(dep.group.value) ? ownGroup : dep.group;
|
|
371
|
+
if (!group || group.value !== f.group)
|
|
372
|
+
return `${label} names group "${f.group}", and the <dependency> at ${where} writes "${dep.group.value}"${group && group !== dep.group ? ` (${group.value})` : ""}`;
|
|
373
|
+
if (!citedLine(f, file, dep.group.line))
|
|
374
|
+
return `${label}: the dependency's group is written at ${file}:${dep.group.line}; cite that line in cite.with`;
|
|
375
|
+
const declared = dep.scope?.value ?? "compile";
|
|
376
|
+
if (declared !== (f.scope ?? "compile"))
|
|
377
|
+
return `${label} says scope ${f.scope ?? "compile"}, and the <dependency> at ${where} declares ${declared}${dep.scope ? ` (${file}:${dep.scope.line})` : ""}`;
|
|
378
|
+
return void 0;
|
|
379
|
+
}
|
|
380
|
+
function gradleProblem(f, label, where, lines, linesOf2) {
|
|
381
|
+
const text = lines[f.cite.line - 1] ?? "";
|
|
382
|
+
if (f.kind === "dependency") {
|
|
383
|
+
const d = gradleDependencyOn(text);
|
|
384
|
+
if (!d)
|
|
385
|
+
return `${label} says ${where} declares a dependency, and that line declares none: cite the line in dependencies { } that names it`;
|
|
386
|
+
if (d.group !== f.group || d.name !== f.name)
|
|
387
|
+
return `${label} names "${f.group}:${f.name}", and ${where} declares "${d.group}:${d.name}"`;
|
|
388
|
+
if (d.scope !== (f.scope ?? "compile"))
|
|
389
|
+
return `${label} says scope ${f.scope ?? "compile"}, and ${where} declares it with ${d.configuration} (${d.scope})`;
|
|
390
|
+
return void 0;
|
|
391
|
+
}
|
|
392
|
+
const name = gradleNameOn(text);
|
|
393
|
+
if (name === void 0)
|
|
394
|
+
return `${label} says ${where} is the coordinates the build publishes, and that line sets no project name: cite rootProject.name in settings.gradle, or archivesBaseName`;
|
|
395
|
+
if (name !== f.name)
|
|
396
|
+
return `${label} names "${f.name}", and ${where} sets "${name}"`;
|
|
397
|
+
const parts = [{ file: f.cite.file, line: f.cite.line }, ...f.cite.with ?? []];
|
|
398
|
+
const groups = parts.flatMap((p) => {
|
|
399
|
+
const g2 = gradleGroupOn(linesOf2(p.file)?.[p.line - 1] ?? "");
|
|
400
|
+
return g2 === void 0 ? [] : [{ ...p, group: g2 }];
|
|
401
|
+
});
|
|
402
|
+
if (!groups.length)
|
|
403
|
+
return `${label}: no line it cites sets the group; cite the build.gradle line that does (group = '${f.group}') in cite.with`;
|
|
404
|
+
const g = groups[0];
|
|
405
|
+
if (g.group !== f.group)
|
|
406
|
+
return `${label} names group "${f.group}", and ${g.file}:${g.line} sets "${g.group}"`;
|
|
407
|
+
return void 0;
|
|
408
|
+
}
|
|
409
|
+
function buildUnrecorded(files, linesOf2, kept) {
|
|
410
|
+
const cited = new Set(kept.filter((f) => f.kind === "artifact" || f.kind === "dependency").map((f) => `${f.cite.file}:${f.cite.line}`));
|
|
411
|
+
const out = [];
|
|
412
|
+
const add = (file, line, kind, c) => {
|
|
413
|
+
if (!cited.has(`${file}:${line}`))
|
|
414
|
+
out.push({ cite: `${file}:${line}`, kind, coordinates: c });
|
|
415
|
+
};
|
|
416
|
+
for (const file of [...files].sort()) {
|
|
417
|
+
const lines = linesOf2(file);
|
|
418
|
+
if (!lines)
|
|
419
|
+
continue;
|
|
420
|
+
if (isPomFile(file)) {
|
|
421
|
+
const pom = pomCoordinates(lines);
|
|
422
|
+
const group = pom.group ?? pom.parentGroup;
|
|
423
|
+
if (pom.artifact)
|
|
424
|
+
add(file, pom.artifact.line, "artifact", `${group?.value ?? "?"}:${pom.artifact.value}`);
|
|
425
|
+
for (const d of pom.dependencies)
|
|
426
|
+
if (!d.managed && !d.plugin && d.artifact)
|
|
427
|
+
add(file, d.artifact.line, "dependency", `${d.group?.value ?? "?"}:${d.artifact.value}`);
|
|
428
|
+
} else if (GRADLE_BUILD.test(file.replace(/\\/g, "/"))) {
|
|
429
|
+
lines.forEach((l, i) => {
|
|
430
|
+
const d = gradleDependencyOn(l);
|
|
431
|
+
if (d && d.scope !== "import")
|
|
432
|
+
add(file, i + 1, "dependency", `${d.group}:${d.name}`);
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return out;
|
|
437
|
+
}
|
|
438
|
+
|
|
169
439
|
// packages/verify/dist/frameworks.js
|
|
170
440
|
var FRAMEWORKS = [
|
|
171
441
|
"spring",
|
|
@@ -618,7 +888,7 @@ function applyCorrections(facts, corrections) {
|
|
|
618
888
|
const p = outsidePairingFor(as, corrections);
|
|
619
889
|
if (!p)
|
|
620
890
|
return f;
|
|
621
|
-
if (over && over.at > p.at && over.
|
|
891
|
+
if (over && over.set?.to !== void 0 && (over.at > p.at || !!p.ai && !over.ai))
|
|
622
892
|
return f;
|
|
623
893
|
const fixed = correctedFact(f, { ...p, action: "edit", set: { to: p.link.system } });
|
|
624
894
|
if (typeof fixed === "string") {
|
|
@@ -1530,201 +1800,67 @@ function pageRouteMatches(file, lines, exists, path) {
|
|
|
1530
1800
|
const route = pageRouteOf(file, lines, exists);
|
|
1531
1801
|
if (route === void 0)
|
|
1532
1802
|
return false;
|
|
1533
|
-
const
|
|
1534
|
-
return
|
|
1803
|
+
const norm2 = (p) => normalizePath(p.replace(/\{([^}:?]*)[^}]*\}/g, "{$1}")).toLowerCase() || "/";
|
|
1804
|
+
return norm2(route) === norm2(path);
|
|
1535
1805
|
}
|
|
1536
1806
|
|
|
1537
|
-
// packages/verify/dist/
|
|
1538
|
-
var
|
|
1539
|
-
var
|
|
1540
|
-
var
|
|
1541
|
-
var
|
|
1542
|
-
var
|
|
1543
|
-
var
|
|
1544
|
-
var
|
|
1545
|
-
var
|
|
1546
|
-
var
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
}
|
|
1559
|
-
|
|
1560
|
-
var ENTRY_POINT_DIR = /(^|\/)(controllers?|routes|routers|handlers|endpoints|listeners|consumers)\//i;
|
|
1561
|
-
var ENTRY_POINT_PART = /[._-](controller|resolver|handlers?|router|routes?|consumer|listener|subscriber|endpoints?)\.[^/.]+$/i;
|
|
1562
|
-
function isEntryPointFile(path) {
|
|
1563
|
-
if (!CODE.test(path) || readingRank(path) === 5 || isModelFile(path))
|
|
1564
|
-
return false;
|
|
1565
|
-
return ENTRY_POINT_NAME.test(stem(path)) || ENTRY_POINT_DIR.test(path) || ENTRY_POINT_PART.test(path);
|
|
1566
|
-
}
|
|
1567
|
-
function isRootFile(path) {
|
|
1568
|
-
if (!CODE.test(path) || readingRank(path) === 5 || isModelFile(path))
|
|
1569
|
-
return false;
|
|
1570
|
-
return readingRank(path) === 2 || isEntryPointFile(path) || ROOT_PART.test(path) || CLIENT_NAME.test(stem(path)) || CLIENT_DIR.test(path);
|
|
1571
|
-
}
|
|
1572
|
-
var DECLARES = /\b(?:class|record|interface|struct|enum|object)\s+([A-Za-z_][A-Za-z0-9_]*)|^\s*(?:export\s+)?(?:declare\s+)?type\s+([A-Za-z_][A-Za-z0-9_]*)/gm;
|
|
1573
|
-
var IDENT = /[A-Za-z_][A-Za-z0-9_]*/g;
|
|
1574
|
-
function declaredTypes(path, text) {
|
|
1575
|
-
const out = [];
|
|
1576
|
-
const s = stem(path);
|
|
1577
|
-
if (/^[A-Z][A-Za-z0-9_]*$/.test(s))
|
|
1578
|
-
out.push(s);
|
|
1579
|
-
for (const m of text.matchAll(DECLARES)) {
|
|
1580
|
-
const n = m[1] ?? m[2];
|
|
1581
|
-
if (n && !out.includes(n))
|
|
1582
|
-
out.push(n);
|
|
1583
|
-
}
|
|
1584
|
-
return out;
|
|
1585
|
-
}
|
|
1586
|
-
function identifiers(text) {
|
|
1587
|
-
return [...new Set(text.match(IDENT) ?? [])];
|
|
1588
|
-
}
|
|
1589
|
-
var NOT_REACHED_WHY = "model classes no entry point, call or field fact reaches (ADR 0169): left out of the read; atticus map <repo> --models all reads them";
|
|
1590
|
-
function reachableModels(o) {
|
|
1591
|
-
const texts = /* @__PURE__ */ new Map();
|
|
1592
|
-
const textOf = (p) => {
|
|
1593
|
-
if (!texts.has(p))
|
|
1594
|
-
texts.set(p, o.read(p) ?? "");
|
|
1595
|
-
return texts.get(p);
|
|
1596
|
-
};
|
|
1597
|
-
const ordered = readingOrder(o.paths);
|
|
1598
|
-
const models = ordered.filter((p) => isModelFile(p, textOf(p))).sort();
|
|
1599
|
-
const isModel = new Set(models);
|
|
1600
|
-
const byName = /* @__PURE__ */ new Map();
|
|
1601
|
-
const declared = /* @__PURE__ */ new Map();
|
|
1602
|
-
for (const p of models) {
|
|
1603
|
-
const names = declaredTypes(p, textOf(p));
|
|
1604
|
-
declared.set(p, names);
|
|
1605
|
-
for (const n of names)
|
|
1606
|
-
byName.set(n, [...byName.get(n) ?? [], p]);
|
|
1607
|
-
}
|
|
1608
|
-
const known = new Set(o.paths);
|
|
1609
|
-
const roots = [];
|
|
1610
|
-
const addRoot = (p) => {
|
|
1611
|
-
if (known.has(p) && !isModel.has(p) && !roots.includes(p))
|
|
1612
|
-
roots.push(p);
|
|
1613
|
-
};
|
|
1614
|
-
const facts = o.facts ?? [];
|
|
1615
|
-
const entries = o.from === "entries";
|
|
1616
|
-
const calls2 = new Set(facts.filter((f) => f.kind === "call").map((f) => f.id));
|
|
1617
|
-
for (const f of facts)
|
|
1618
|
-
if (f.kind === "entry" || f.kind === "call" && !entries)
|
|
1619
|
-
for (const p of citedFiles(f))
|
|
1620
|
-
addRoot(p);
|
|
1621
|
-
for (const p of ordered)
|
|
1622
|
-
if (entries ? isEntryPointFile(p) : isRootFile(p))
|
|
1623
|
-
addRoot(p);
|
|
1624
|
-
const reached = /* @__PURE__ */ new Map();
|
|
1625
|
-
const queue = [];
|
|
1626
|
-
const reach = (names, from, own = []) => {
|
|
1627
|
-
for (const n of names) {
|
|
1628
|
-
if (own.includes(n))
|
|
1629
|
-
continue;
|
|
1630
|
-
for (const p of byName.get(n) ?? []) {
|
|
1631
|
-
const r = reached.get(p);
|
|
1632
|
-
if (r) {
|
|
1633
|
-
if (r.from === from && !r.types.includes(n))
|
|
1634
|
-
r.types.push(n);
|
|
1635
|
-
continue;
|
|
1636
|
-
}
|
|
1637
|
-
reached.set(p, { path: p, types: [n], from });
|
|
1638
|
-
queue.push(p);
|
|
1639
|
-
}
|
|
1807
|
+
// packages/verify/dist/secrets.js
|
|
1808
|
+
var CONFIG_FILE = /\.(ya?ml|properties|json|xml|config|env|ini|toml|conf|cfg)$|(^|\/)\.env(\.[^/]*)?$|(^|\/)credentials?$/i;
|
|
1809
|
+
var isConfigFile = (path) => CONFIG_FILE.test(path.replace(/\\/g, "/"));
|
|
1810
|
+
var PLACEHOLDER = /^(<[^>]*>|\*+|x{3,}|changeme|change-me|secret|password|todo|tbd|none|null|nil|dummy|example|sample|test|redacted|your[-_ ].*)$/i;
|
|
1811
|
+
var KEY_VALUE = /^\s*(?:-\s+)?(?:export\s+)?["']?([A-Za-z0-9_.\-[\]]+)["']?\s*[:=]\s*(.*?)\s*,?\s*$/;
|
|
1812
|
+
var XML_ELEMENT = /<([A-Za-z_][\w.-]*)>([^<]+)<\/\1>/g;
|
|
1813
|
+
var XML_NAMED = /\b(?:key|name)\s*=\s*"([^"]+)"\s+value\s*=\s*"([^"]*)"/g;
|
|
1814
|
+
var CONNECTION_PAIR = /(?:^|[;"'])\s*([A-Za-z][A-Za-z0-9 _.-]*?)\s*=\s*([^;"'<>\s][^;"'<>]*)/g;
|
|
1815
|
+
var TOKEN_VALUE_KEY = /^(value|val)$/i;
|
|
1816
|
+
var TOKEN_NAME = /^\s*"(xpath|name|key)"\s*:\s*"([^"]+)"/;
|
|
1817
|
+
function isReference(value) {
|
|
1818
|
+
return /^(vault|env|secret|ref|arn|kms|sm|gcp-sm|azure-kv|classpath\*?|file):/i.test(value) || /\$\{|\{\{/.test(value) || /^(~|\.{1,2})?\/[\w.\-/]+$/.test(value) || /^[\w.-]+(\/[\w.-]+)+\.[A-Za-z0-9]{1,10}$/.test(value);
|
|
1819
|
+
}
|
|
1820
|
+
var unquote = (v) => v.replace(/\s+#.*$/, "").replace(/^["']|["']$/g, "").trim();
|
|
1821
|
+
function tokenKeyNear(lines, i) {
|
|
1822
|
+
for (const step of [-1, 1])
|
|
1823
|
+
for (let j = i + step; j >= 0 && j < lines.length && Math.abs(j - i) <= 4; j += step) {
|
|
1824
|
+
const l = lines[j];
|
|
1825
|
+
const m = TOKEN_NAME.exec(l);
|
|
1826
|
+
if (m)
|
|
1827
|
+
return m[2];
|
|
1828
|
+
if (/[{}]/.test(l))
|
|
1829
|
+
break;
|
|
1640
1830
|
}
|
|
1641
|
-
|
|
1642
|
-
for (const p of roots)
|
|
1643
|
-
reach(identifiers(textOf(p)), p);
|
|
1644
|
-
for (const f of facts) {
|
|
1645
|
-
for (const p of citedFiles(f))
|
|
1646
|
-
if (isModel.has(p) && !reached.has(p)) {
|
|
1647
|
-
reached.set(p, { path: p, types: [...(declared.get(p) ?? []).slice(0, 1)], from: f.id });
|
|
1648
|
-
queue.push(p);
|
|
1649
|
-
}
|
|
1650
|
-
if (f.kind === "field" && !(entries && calls2.has(f.owner)))
|
|
1651
|
-
reach(identifiers([f.type ?? "", f.transform === "message type" ? f.name : ""].join(" ")), f.id);
|
|
1652
|
-
}
|
|
1653
|
-
const rooted = roots.length > 0 || reached.size > 0;
|
|
1654
|
-
if (!rooted)
|
|
1655
|
-
return {
|
|
1656
|
-
rooted,
|
|
1657
|
-
roots,
|
|
1658
|
-
reached: models.map((p) => ({ path: p, types: declared.get(p) ?? [], from: "" })),
|
|
1659
|
-
notReached: [],
|
|
1660
|
-
models: models.length
|
|
1661
|
-
};
|
|
1662
|
-
for (let i = 0; i < queue.length; i++) {
|
|
1663
|
-
const p = queue[i];
|
|
1664
|
-
reach(identifiers(textOf(p)), p, declared.get(p));
|
|
1665
|
-
}
|
|
1666
|
-
return {
|
|
1667
|
-
rooted,
|
|
1668
|
-
roots,
|
|
1669
|
-
reached: queue.map((p) => reached.get(p)),
|
|
1670
|
-
notReached: models.filter((p) => !reached.has(p)),
|
|
1671
|
-
models: models.length
|
|
1672
|
-
};
|
|
1673
|
-
}
|
|
1674
|
-
|
|
1675
|
-
// packages/verify/dist/method.js
|
|
1676
|
-
var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
1677
|
-
function wordsOf(line) {
|
|
1678
|
-
return line.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").toLowerCase().split(/[^a-z]+/).filter(Boolean);
|
|
1679
|
-
}
|
|
1680
|
-
function methodOnLines(method, lines) {
|
|
1681
|
-
const m = method.toLowerCase();
|
|
1682
|
-
return lines.some((l) => wordsOf(l).includes(m));
|
|
1831
|
+
return void 0;
|
|
1683
1832
|
}
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
function chainOf(file, line) {
|
|
1687
|
-
const at = (n) => file?.[n - 1];
|
|
1688
|
-
const cited = at(line);
|
|
1689
|
-
if (cited === void 0)
|
|
1833
|
+
function liveSecretsIn(file, lines) {
|
|
1834
|
+
if (!isConfigFile(file))
|
|
1690
1835
|
return [];
|
|
1691
|
-
const out = [
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1836
|
+
const out = [];
|
|
1837
|
+
lines.forEach((text, i) => {
|
|
1838
|
+
if (/^\s*(#|\/\/|;|<!--)/.test(text))
|
|
1839
|
+
return;
|
|
1840
|
+
const pairs = [];
|
|
1841
|
+
const kv = KEY_VALUE.exec(text);
|
|
1842
|
+
if (kv) {
|
|
1843
|
+
const key = TOKEN_VALUE_KEY.test(kv[1]) ? tokenKeyNear(lines, i) ?? kv[1] : kv[1];
|
|
1844
|
+
pairs.push({ key, value: unquote(kv[2]) });
|
|
1845
|
+
}
|
|
1846
|
+
for (const m of text.matchAll(XML_ELEMENT))
|
|
1847
|
+
pairs.push({ key: m[1], value: m[2].trim() });
|
|
1848
|
+
for (const m of text.matchAll(XML_NAMED))
|
|
1849
|
+
pairs.push({ key: m[1], value: m[2].trim() });
|
|
1850
|
+
if (text.includes(";"))
|
|
1851
|
+
for (const m of text.matchAll(CONNECTION_PAIR))
|
|
1852
|
+
pairs.push({ key: m[1].trim(), value: m[2].trim() });
|
|
1853
|
+
const named = pairs.find(({ key, value }) => value && !PLACEHOLDER.test(value) && // a key with a nested map under it, or an encrypted value (`{cipher}…`), sets nothing here
|
|
1854
|
+
!/^[{[]/.test(value) && !isReference(value) && looksLikeSecret(key, value));
|
|
1855
|
+
if (named) {
|
|
1856
|
+
out.push({ file, line: i + 1, key: named.key });
|
|
1857
|
+
return;
|
|
1858
|
+
}
|
|
1859
|
+
if (hasSecretShape(text))
|
|
1860
|
+
out.push({ file, line: i + 1, key: pairs[0]?.key ?? "(token)" });
|
|
1861
|
+
});
|
|
1700
1862
|
return out;
|
|
1701
1863
|
}
|
|
1702
|
-
function methodUnseenOf(f, lines, factOf) {
|
|
1703
|
-
if (f.kind !== "entry" && f.kind !== "call")
|
|
1704
|
-
return void 0;
|
|
1705
|
-
if (!f.method || !HTTP_METHODS.has(f.method.toUpperCase()))
|
|
1706
|
-
return void 0;
|
|
1707
|
-
const at = (file, line) => lines(file)?.[line - 1];
|
|
1708
|
-
const route = f.kind === "call" && f.from ? factOf?.(f.from) : void 0;
|
|
1709
|
-
const forwards = route?.kind === "entry" && route.method?.toUpperCase() === f.method.toUpperCase();
|
|
1710
|
-
const looked = [
|
|
1711
|
-
...chainOf(lines(f.cite.file), f.cite.line),
|
|
1712
|
-
at(f.cite.file, f.cite.line + 1),
|
|
1713
|
-
...(f.cite.with ?? []).map((p) => at(p.file, p.line)),
|
|
1714
|
-
...forwards ? [at(route.cite.file, route.cite.line), at(route.cite.file, route.cite.line + 1)] : []
|
|
1715
|
-
].filter((l) => l !== void 0);
|
|
1716
|
-
if (methodOnLines(f.method, looked))
|
|
1717
|
-
return void 0;
|
|
1718
|
-
const cite2 = `${f.cite.file}:${f.cite.line}`;
|
|
1719
|
-
const method = f.method.toUpperCase();
|
|
1720
|
-
return {
|
|
1721
|
-
id: f.id,
|
|
1722
|
-
kind: f.kind,
|
|
1723
|
-
method,
|
|
1724
|
-
cite: cite2,
|
|
1725
|
-
message: `${f.id} claims ${method}, which neither ${cite2}, the chain it is in, the next line, a cite.with line nor the route it forwards writes`
|
|
1726
|
-
};
|
|
1727
|
-
}
|
|
1728
1864
|
|
|
1729
1865
|
// packages/verify/dist/skipped.js
|
|
1730
1866
|
function notReadForSkipped(path, rules = DEFAULT_READ_RULES) {
|
|
@@ -1744,10 +1880,10 @@ var NOT_TOPIC_LAST = new Set("com org net io dev app ai co uk de fr in jp us eu
|
|
|
1744
1880
|
var NOT_TOPIC_FIRST = new Set("com org net io java javax jakarta android androidx kotlin kotlinx scala sun microsoft system google apache spring springframework management server logging hibernate jdk www".split(" "));
|
|
1745
1881
|
var DOTTED_TOPIC = /^[a-z][a-z0-9_-]*(\.[a-z][a-z0-9_-]*){2,}$/;
|
|
1746
1882
|
var SEPARATED_NAME = /^[A-Za-z][A-Za-z0-9_]*([._:-][A-Za-z0-9_]+)+$/;
|
|
1747
|
-
var
|
|
1748
|
-
var
|
|
1883
|
+
var QUOTED2 = /(["'`])((?:\\.|(?!\1)[^\\\n])*)\1/g;
|
|
1884
|
+
var KEY_VALUE2 = /^\s*-?\s*["']?([A-Za-z0-9_.\-[\]]+)["']?\s*[:=]\s*([^\s"'#]+)\s*$/;
|
|
1749
1885
|
var ELEMENT_TEXT = /<([A-Za-z][\w:.-]*)[^>]*>([^<\s]+)<\/\1>/g;
|
|
1750
|
-
var
|
|
1886
|
+
var wordsOf = (line) => line.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").toLowerCase().split(/[^a-z]+/).filter(Boolean);
|
|
1751
1887
|
var TOPIC_WORDS = /* @__PURE__ */ new Set([
|
|
1752
1888
|
"topic",
|
|
1753
1889
|
"topics",
|
|
@@ -1761,7 +1897,7 @@ var TOPIC_WORDS = /* @__PURE__ */ new Set([
|
|
|
1761
1897
|
"exchanges"
|
|
1762
1898
|
]);
|
|
1763
1899
|
var topicContext = (line) => {
|
|
1764
|
-
const w =
|
|
1900
|
+
const w = wordsOf(line);
|
|
1765
1901
|
return w.some((x) => TOPIC_WORDS.has(x)) || w.join(" ").includes("routing key");
|
|
1766
1902
|
};
|
|
1767
1903
|
var BUILD_KEY_WORDS = new Set("scm git gitlab github bitbucket repository repositories repo registry mirror mirrors nexus artifactory snapshot snapshots distribution maven npm nuget pypi sonar sonarqube jenkins ci".split(" "));
|
|
@@ -1772,7 +1908,7 @@ var keysBefore = (prefix) => [
|
|
|
1772
1908
|
...[...prefix.matchAll(/["']?([A-Za-z][\w.-]*)["']?\s*[:=]/g)].map((m) => m[1]),
|
|
1773
1909
|
...[...prefix.matchAll(/\b([A-Za-z]\w*)\s*\{/g)].map((m) => m[1])
|
|
1774
1910
|
];
|
|
1775
|
-
var isBuildUrl = (u, prefix) => /\.git\/?$/i.test(u) || /\bscm:\w+:$/i.test(prefix) || keysBefore(prefix).some((k) =>
|
|
1911
|
+
var isBuildUrl = (u, prefix) => /\.git\/?$/i.test(u) || /\bscm:\w+:$/i.test(prefix) || keysBefore(prefix).some((k) => wordsOf(k).some((w) => BUILD_KEY_WORDS.has(w)));
|
|
1776
1912
|
var HEADER_ARG = /header\w*\s*(?:\.\s*\w+\s*)?\(\s*(?:(?:value|name)\s*=\s*)?$/i;
|
|
1777
1913
|
var isHeaderName = (s, prefix) => /^x-/i.test(s) || HEADER_ARG.test(prefix.replace(/["'`]$/, ""));
|
|
1778
1914
|
var cleanUrl = (u) => u.replace(/[.:]+$/, "").replace(/^([a-z0-9+.-]+:\/\/)[^/@\s]+@/i, "$1<redacted>@");
|
|
@@ -1863,11 +1999,11 @@ function candidatesIn(path, lines) {
|
|
|
1863
1999
|
add("url", u);
|
|
1864
2000
|
urls.push(m[0]);
|
|
1865
2001
|
}
|
|
1866
|
-
const strings2 = [...code2.matchAll(
|
|
2002
|
+
const strings2 = [...code2.matchAll(QUOTED2)].map((m) => ({
|
|
1867
2003
|
s: m[2],
|
|
1868
2004
|
before: code2.slice(0, m.index + 1)
|
|
1869
2005
|
}));
|
|
1870
|
-
const kv =
|
|
2006
|
+
const kv = KEY_VALUE2.exec(code2);
|
|
1871
2007
|
if (kv)
|
|
1872
2008
|
strings2.push({ s: kv[2], before: "" });
|
|
1873
2009
|
for (const m of code2.matchAll(ELEMENT_TEXT))
|
|
@@ -1880,125 +2016,537 @@ function candidatesIn(path, lines) {
|
|
|
1880
2016
|
add("path", p);
|
|
1881
2017
|
continue;
|
|
1882
2018
|
}
|
|
1883
|
-
const t = topicOf(s, context);
|
|
1884
|
-
if (t && !isHeaderName(t, before))
|
|
1885
|
-
add("topic", t);
|
|
1886
|
-
}
|
|
1887
|
-
});
|
|
1888
|
-
return out;
|
|
1889
|
-
}
|
|
1890
|
-
var cleanUrlIn = (line) => line.replace(/\b([a-z0-9+.-]+:\/\/)[^/@\s"'`]+@/gi, "$1<redacted>@");
|
|
1891
|
-
var normPath = (p) => normalizePath(p.replace(/(^|\/)%[sd](?=\/|$)/g, "$1{}"));
|
|
1892
|
-
function indexFacts(facts) {
|
|
1893
|
-
const at = /* @__PURE__ */ new Set();
|
|
1894
|
-
const strings2 = /* @__PURE__ */ new Set();
|
|
1895
|
-
const walk = (v) => {
|
|
1896
|
-
if (typeof v === "string") {
|
|
1897
|
-
if (v.length >= 3)
|
|
1898
|
-
strings2.add(v);
|
|
1899
|
-
return;
|
|
1900
|
-
}
|
|
1901
|
-
if (Array.isArray(v))
|
|
1902
|
-
return v.forEach(walk);
|
|
1903
|
-
if (v && typeof v === "object") {
|
|
1904
|
-
const o = v;
|
|
1905
|
-
if (typeof o.file === "string" && typeof o.line === "number")
|
|
1906
|
-
at.add(`${o.file}:${o.line}`);
|
|
1907
|
-
Object.values(o).forEach(walk);
|
|
2019
|
+
const t = topicOf(s, context);
|
|
2020
|
+
if (t && !isHeaderName(t, before))
|
|
2021
|
+
add("topic", t);
|
|
2022
|
+
}
|
|
2023
|
+
});
|
|
2024
|
+
return out;
|
|
2025
|
+
}
|
|
2026
|
+
var cleanUrlIn = (line) => line.replace(/\b([a-z0-9+.-]+:\/\/)[^/@\s"'`]+@/gi, "$1<redacted>@");
|
|
2027
|
+
var normPath = (p) => normalizePath(p.replace(/(^|\/)%[sd](?=\/|$)/g, "$1{}"));
|
|
2028
|
+
function indexFacts(facts) {
|
|
2029
|
+
const at = /* @__PURE__ */ new Set();
|
|
2030
|
+
const strings2 = /* @__PURE__ */ new Set();
|
|
2031
|
+
const walk = (v) => {
|
|
2032
|
+
if (typeof v === "string") {
|
|
2033
|
+
if (v.length >= 3)
|
|
2034
|
+
strings2.add(v);
|
|
2035
|
+
return;
|
|
2036
|
+
}
|
|
2037
|
+
if (Array.isArray(v))
|
|
2038
|
+
return v.forEach(walk);
|
|
2039
|
+
if (v && typeof v === "object") {
|
|
2040
|
+
const o = v;
|
|
2041
|
+
if (typeof o.file === "string" && typeof o.line === "number")
|
|
2042
|
+
at.add(`${o.file}:${o.line}`);
|
|
2043
|
+
Object.values(o).forEach(walk);
|
|
2044
|
+
}
|
|
2045
|
+
};
|
|
2046
|
+
facts.forEach(walk);
|
|
2047
|
+
const paths = /* @__PURE__ */ new Set();
|
|
2048
|
+
for (const s of strings2) {
|
|
2049
|
+
if (/\s/.test(s))
|
|
2050
|
+
continue;
|
|
2051
|
+
const u = /^[a-z0-9+.-]+:\/\/[^/]+(\/.*)?$/i.exec(s);
|
|
2052
|
+
const p = u ? u[1] : s.includes("/") ? s : void 0;
|
|
2053
|
+
if (p && p.length > 1)
|
|
2054
|
+
paths.add(`${normPath(p)}/`);
|
|
2055
|
+
}
|
|
2056
|
+
return { at, strings: [...strings2].map((s) => s.toLowerCase()), paths: [...paths] };
|
|
2057
|
+
}
|
|
2058
|
+
function factsCover(file, c, ix) {
|
|
2059
|
+
if ([c.line - 1, c.line, c.line + 1].some((n) => ix.at.has(`${file}:${n}`)))
|
|
2060
|
+
return true;
|
|
2061
|
+
if (c.kind === "path") {
|
|
2062
|
+
const p = `${normPath(c.value)}/`;
|
|
2063
|
+
return ix.paths.some((f) => f.includes(p));
|
|
2064
|
+
}
|
|
2065
|
+
const v = c.value.toLowerCase().replace(/\/+$/, "");
|
|
2066
|
+
return ix.strings.some((s) => s.includes(v));
|
|
2067
|
+
}
|
|
2068
|
+
var skippedOf = (file, c) => ({
|
|
2069
|
+
cite: `${file}:${c.line}`,
|
|
2070
|
+
kind: c.kind,
|
|
2071
|
+
value: c.value,
|
|
2072
|
+
text: c.text
|
|
2073
|
+
});
|
|
2074
|
+
var SPEC_MARK = /^\s*["']?(openapi|swagger)["']?\s*:/m;
|
|
2075
|
+
var SPEC_EXT = /\.(ya?ml|json)$/i;
|
|
2076
|
+
function specOpsUncoveredIn(file, text, facts) {
|
|
2077
|
+
if (!SPEC_EXT.test(file) || !SPEC_MARK.test(text.slice(0, 4e3)))
|
|
2078
|
+
return void 0;
|
|
2079
|
+
let doc;
|
|
2080
|
+
try {
|
|
2081
|
+
doc = readOpenApiDocument(text);
|
|
2082
|
+
} catch {
|
|
2083
|
+
return void 0;
|
|
2084
|
+
}
|
|
2085
|
+
if (!doc || !doc.operations.length)
|
|
2086
|
+
return void 0;
|
|
2087
|
+
const server = (() => {
|
|
2088
|
+
const s = doc.servers[0];
|
|
2089
|
+
if (!s)
|
|
2090
|
+
return "";
|
|
2091
|
+
const p = /^[a-z0-9+.-]+:\/\/[^/]+(\/.*)?$/i.exec(s)?.[1] ?? (s.startsWith("/") ? s : "");
|
|
2092
|
+
return p.replace(/\/+$/, "");
|
|
2093
|
+
})();
|
|
2094
|
+
const entries = facts.filter((f) => f.kind === "entry");
|
|
2095
|
+
const atLines = /* @__PURE__ */ new Set();
|
|
2096
|
+
for (const e of entries)
|
|
2097
|
+
for (const k of indexFacts([e]).at)
|
|
2098
|
+
atLines.add(k);
|
|
2099
|
+
const out = [];
|
|
2100
|
+
for (const op of doc.operations) {
|
|
2101
|
+
const lines = [op.methodLine, op.line].filter((n) => n !== void 0);
|
|
2102
|
+
if (lines.some((n) => [n - 1, n, n + 1].some((x) => atLines.has(`${file}:${x}`))))
|
|
2103
|
+
continue;
|
|
2104
|
+
const method = op.method.toUpperCase();
|
|
2105
|
+
const own = normPath(op.path);
|
|
2106
|
+
const full = normPath(`${server}${op.path}`);
|
|
2107
|
+
const covered = entries.some((e) => {
|
|
2108
|
+
if (e.method && e.method.toUpperCase() !== method)
|
|
2109
|
+
return false;
|
|
2110
|
+
const p = normPath(e.path);
|
|
2111
|
+
return p === own || p === full || p.endsWith(own) || p.split("/").length > 2 && own.endsWith(p);
|
|
2112
|
+
});
|
|
2113
|
+
if (covered)
|
|
2114
|
+
continue;
|
|
2115
|
+
const opId = op.node?.get?.("operationId");
|
|
2116
|
+
const line = op.methodLine ?? op.line ?? 1;
|
|
2117
|
+
out.push({
|
|
2118
|
+
spec: file,
|
|
2119
|
+
method,
|
|
2120
|
+
path: op.path,
|
|
2121
|
+
...typeof opId === "string" ? { operationId: opId } : {},
|
|
2122
|
+
cite: `${file}:${line}`,
|
|
2123
|
+
message: `${file}:${line} declares ${method} ${op.path}${typeof opId === "string" ? ` (${opId})` : ""}, which no entry covers`
|
|
2124
|
+
});
|
|
2125
|
+
}
|
|
2126
|
+
return out;
|
|
2127
|
+
}
|
|
2128
|
+
var REVIEWED_HOLDS_SHOWN = 5;
|
|
2129
|
+
function reviewedHoldsOf(r, skipped) {
|
|
2130
|
+
const n = skipped.length;
|
|
2131
|
+
const first = skipped.slice(0, 3).map((s) => `${s.cite} (${s.value})`);
|
|
2132
|
+
return {
|
|
2133
|
+
path: r.path,
|
|
2134
|
+
why: r.why,
|
|
2135
|
+
count: n,
|
|
2136
|
+
skipped: skipped.slice(0, REVIEWED_HOLDS_SHOWN),
|
|
2137
|
+
message: `${r.line !== void 0 ? `line ${r.line}: ` : ""}${r.path} is reviewed as holding nothing to record, but ${n} ${n === 1 ? "line in it writes" : "lines in it write"} a path, URL or topic: ${first.join(", ")}${n > 3 ? ` and ${n - 3} more` : ""}`
|
|
2138
|
+
};
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
// packages/verify/dist/settings-path.js
|
|
2142
|
+
var SETTINGS_FILE = /\.(ya?ml|properties|json|xml|config|conf|ini|toml|cfg|env)$|(^|\/)\.env(\.[^/]*)?$/i;
|
|
2143
|
+
var isSettingsFile = (path) => SETTINGS_FILE.test(path);
|
|
2144
|
+
var isYaml = (path) => /\.ya?ml$/i.test(path);
|
|
2145
|
+
var isProperties = (path) => /\.properties$/i.test(path);
|
|
2146
|
+
var escape = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2147
|
+
var YAML_KEY = /^(["']?)([^\s"'#:{}[\],&*!|>][^"'#:]*?)\1\s*:(?:\s+(.*))?$/;
|
|
2148
|
+
function yamlLine(text) {
|
|
2149
|
+
if (!text.trim() || /^\s*#/.test(text) || /^\s*(---|\.\.\.)\s*$/.test(text))
|
|
2150
|
+
return void 0;
|
|
2151
|
+
const lead = /^ */.exec(text)[0].length;
|
|
2152
|
+
const dash = /^ *-(\s+|$)/.exec(text);
|
|
2153
|
+
const col = dash ? dash[0].length : lead;
|
|
2154
|
+
const body = text.slice(col);
|
|
2155
|
+
const m = YAML_KEY.exec(body.trimEnd());
|
|
2156
|
+
const rest = m?.[3]?.trim();
|
|
2157
|
+
return {
|
|
2158
|
+
lead,
|
|
2159
|
+
col,
|
|
2160
|
+
item: !!dash,
|
|
2161
|
+
key: m?.[2]?.trim(),
|
|
2162
|
+
// a comment or an anchor after the key sets nothing
|
|
2163
|
+
rest: rest && !/^[#&]/.test(rest) ? rest : void 0
|
|
2164
|
+
};
|
|
2165
|
+
}
|
|
2166
|
+
function yamlPathAt(lines, line) {
|
|
2167
|
+
const at = yamlLine(lines[line - 1] ?? "");
|
|
2168
|
+
if (!at?.key)
|
|
2169
|
+
return void 0;
|
|
2170
|
+
const path = [at.key];
|
|
2171
|
+
let col = at.item ? at.lead : at.col;
|
|
2172
|
+
for (let j = line - 2; j >= 0 && col > 0; j--) {
|
|
2173
|
+
const l = lines[j];
|
|
2174
|
+
if (/^\s*(---|\.\.\.)\s*$/.test(l))
|
|
2175
|
+
break;
|
|
2176
|
+
const y = yamlLine(l);
|
|
2177
|
+
if (!y)
|
|
2178
|
+
continue;
|
|
2179
|
+
if (y.item && y.col === col) {
|
|
2180
|
+
col = y.lead;
|
|
2181
|
+
continue;
|
|
2182
|
+
}
|
|
2183
|
+
if (y.col >= col)
|
|
2184
|
+
continue;
|
|
2185
|
+
if (!y.key || y.rest)
|
|
2186
|
+
return void 0;
|
|
2187
|
+
path.unshift(y.key);
|
|
2188
|
+
col = y.lead;
|
|
2189
|
+
}
|
|
2190
|
+
if (col > 0)
|
|
2191
|
+
return void 0;
|
|
2192
|
+
return path.flatMap((k) => k.split("."));
|
|
2193
|
+
}
|
|
2194
|
+
function yamlChildren(lines, line) {
|
|
2195
|
+
const at = yamlLine(lines[line - 1] ?? "");
|
|
2196
|
+
if (!at?.key)
|
|
2197
|
+
return [];
|
|
2198
|
+
const out = [];
|
|
2199
|
+
let childCol;
|
|
2200
|
+
for (let j = line; j < lines.length; j++) {
|
|
2201
|
+
const y = yamlLine(lines[j]);
|
|
2202
|
+
if (!y)
|
|
2203
|
+
continue;
|
|
2204
|
+
if (y.lead <= at.col)
|
|
2205
|
+
break;
|
|
2206
|
+
childCol ??= y.col;
|
|
2207
|
+
if (y.col < childCol)
|
|
2208
|
+
break;
|
|
2209
|
+
if (y.col === childCol && y.key && !y.item)
|
|
2210
|
+
out.push(y.key);
|
|
2211
|
+
}
|
|
2212
|
+
return out;
|
|
2213
|
+
}
|
|
2214
|
+
function propertiesKeyAt(lines, line) {
|
|
2215
|
+
const l = lines[line - 1] ?? "";
|
|
2216
|
+
if (/^\s*[#!]/.test(l))
|
|
2217
|
+
return void 0;
|
|
2218
|
+
return /^\s*((?:\\.|[^\s=:\\])+)\s*[=:\s]/.exec(l)?.[1];
|
|
2219
|
+
}
|
|
2220
|
+
var sameSegs = (a, b) => a.length === b.length && a.every((s, i) => s === b[i]);
|
|
2221
|
+
var keySegments = (key) => key.trim().split(".").map((s) => s.replace(/\[[^\]]*\]$/, "")).filter(Boolean);
|
|
2222
|
+
var fieldNames = (seg) => [
|
|
2223
|
+
seg,
|
|
2224
|
+
seg.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase())
|
|
2225
|
+
];
|
|
2226
|
+
var CONFIG_PROPS = /@ConfigurationProperties\s*\(\s*(?:(?:prefix|value)\s*=\s*)?"([^"]+)"/;
|
|
2227
|
+
function helperBuildsKey(key, cite2, linesOf2) {
|
|
2228
|
+
if (isSettingsFile(cite2.file))
|
|
2229
|
+
return false;
|
|
2230
|
+
const segs = keySegments(key);
|
|
2231
|
+
if (segs.length < 2 || segs.join(".") !== key.trim())
|
|
2232
|
+
return false;
|
|
2233
|
+
const last = segs[segs.length - 1];
|
|
2234
|
+
const prefix = segs.slice(0, -1);
|
|
2235
|
+
const line = linesOf2(cite2.file)?.[cite2.line - 1];
|
|
2236
|
+
if (line === void 0)
|
|
2237
|
+
return false;
|
|
2238
|
+
const code2 = isCommentLine(line) ? line : line.replace(/\/\*.*?\*\//g, "").replace(/(^|\s)\/\/.*$/, "");
|
|
2239
|
+
if (!new RegExp(`(^|[^A-Za-z0-9_$-])${escape(last)}($|[^A-Za-z0-9_$-])`).test(code2))
|
|
2240
|
+
return false;
|
|
2241
|
+
const parts = cite2.with ?? [];
|
|
2242
|
+
const files = [...new Set(parts.map((p) => p.file))];
|
|
2243
|
+
return files.some((file) => {
|
|
2244
|
+
const ls = linesOf2(file);
|
|
2245
|
+
if (!ls)
|
|
2246
|
+
return false;
|
|
2247
|
+
const here = parts.filter((p) => p.file === file);
|
|
2248
|
+
if (isYaml(file))
|
|
2249
|
+
return here.some((p) => {
|
|
2250
|
+
const at = yamlPathAt(ls, p.line);
|
|
2251
|
+
if (!at)
|
|
2252
|
+
return false;
|
|
2253
|
+
if (sameSegs(at, segs))
|
|
2254
|
+
return true;
|
|
2255
|
+
return sameSegs(at, prefix) && yamlChildren(ls, p.line).includes(last);
|
|
2256
|
+
});
|
|
2257
|
+
if (isProperties(file))
|
|
2258
|
+
return here.some((p) => propertiesKeyAt(ls, p.line) === segs.join("."));
|
|
2259
|
+
if (isSettingsFile(file))
|
|
2260
|
+
return false;
|
|
2261
|
+
return here.some((p) => {
|
|
2262
|
+
const m = CONFIG_PROPS.exec(ls[p.line - 1] ?? "");
|
|
2263
|
+
if (!m)
|
|
2264
|
+
return false;
|
|
2265
|
+
const pre = m[1].split(".");
|
|
2266
|
+
if (pre.length > prefix.length || !pre.every((s, i) => s === prefix[i]))
|
|
2267
|
+
return false;
|
|
2268
|
+
return prefix.slice(pre.length).every((seg) => here.some((q) => q.line > p.line && q.line <= p.line + 40 && fieldNames(seg).some((n) => new RegExp(`(^|[^A-Za-z0-9_$])${escape(n)}($|[^A-Za-z0-9_$])`).test(ls[q.line - 1] ?? ""))));
|
|
2269
|
+
});
|
|
2270
|
+
});
|
|
2271
|
+
}
|
|
2272
|
+
var norm = (s) => s.replace(/[‘’‚'"“”„`]/g, "").replace(/\s+/g, " ").trim();
|
|
2273
|
+
function enclosingObject(lines, line) {
|
|
2274
|
+
let depth = 0;
|
|
2275
|
+
let start = -1;
|
|
2276
|
+
for (let j = line - 1; j >= 0; j--) {
|
|
2277
|
+
const l = lines[j];
|
|
2278
|
+
for (let k = l.length - 1; k >= 0; k--) {
|
|
2279
|
+
if (l[k] === "}" && j !== line - 1)
|
|
2280
|
+
depth++;
|
|
2281
|
+
if (l[k] === "{") {
|
|
2282
|
+
if (depth === 0) {
|
|
2283
|
+
start = j;
|
|
2284
|
+
break;
|
|
2285
|
+
}
|
|
2286
|
+
depth--;
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
if (start >= 0)
|
|
2290
|
+
break;
|
|
2291
|
+
}
|
|
2292
|
+
if (start < 0)
|
|
2293
|
+
return void 0;
|
|
2294
|
+
depth = 0;
|
|
2295
|
+
for (let j = start; j < lines.length; j++) {
|
|
2296
|
+
for (const ch of lines[j]) {
|
|
2297
|
+
if (ch === "{")
|
|
2298
|
+
depth++;
|
|
2299
|
+
if (ch === "}" && --depth === 0)
|
|
2300
|
+
return lines.slice(start, j + 1);
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
return void 0;
|
|
2304
|
+
}
|
|
2305
|
+
function configLineProblem(f, linesOf2, listed2) {
|
|
2306
|
+
const lines = linesOf2(f.cite.file);
|
|
2307
|
+
if (!lines)
|
|
2308
|
+
return void 0;
|
|
2309
|
+
const at = lines[f.cite.line - 1] ?? "";
|
|
2310
|
+
const where = `${f.cite.file}:${f.cite.line}`;
|
|
2311
|
+
const segs = keySegments(f.key);
|
|
2312
|
+
const value = f.value === void 0 ? void 0 : norm(f.value);
|
|
2313
|
+
const has = (l) => value !== void 0 && norm(l).includes(value);
|
|
2314
|
+
if (f.key.trim().startsWith("/") && /(^|\/)config\.json$/i.test(f.cite.file)) {
|
|
2315
|
+
const dir = f.cite.file.replace(/[^/]*$/, "");
|
|
2316
|
+
if (!listed2().some((p) => p.startsWith(`${dir}apiproxy/`)))
|
|
2317
|
+
return `config ${where} is a config.json beside no gateway bundle (no ${dir}apiproxy/); a token's setting is read only from the bundle's own`;
|
|
2318
|
+
const obj = enclosingObject(lines, f.cite.line);
|
|
2319
|
+
const xpathRe = new RegExp(`"xpath"\\s*:\\s*"${escape(f.key.trim())}"`);
|
|
2320
|
+
if (!obj || !obj.some((l) => xpathRe.test(l)))
|
|
2321
|
+
return `the token at ${where} has no "xpath" of ${f.key}`;
|
|
2322
|
+
if (value !== void 0 && !obj.some((l) => /"value"\s*:/.test(l) && has(l)))
|
|
2323
|
+
return `the token at ${where} sets no such value; cite the token whose "value" it is`;
|
|
2324
|
+
return void 0;
|
|
2325
|
+
}
|
|
2326
|
+
if (isYaml(f.cite.file)) {
|
|
2327
|
+
const y = yamlLine(at);
|
|
2328
|
+
const path = yamlPathAt(lines, f.cite.line);
|
|
2329
|
+
if (y?.key && path && segs.length && keySegments(y.key).at(-1) === segs.at(-1)) {
|
|
2330
|
+
const tail = path.slice(path.length - segs.length);
|
|
2331
|
+
if (path.length < segs.length || !sameSegs(tail, segs))
|
|
2332
|
+
return `${where} sets ${path.join(".")}, not ${f.key}: the key's parents are not the lines above it`;
|
|
2333
|
+
if (value !== void 0 && y.rest && !/^[|>]/.test(y.rest)) {
|
|
2334
|
+
if (!has(y.rest))
|
|
2335
|
+
return `${where} sets ${y.key} to something other than the value claimed`;
|
|
2336
|
+
return void 0;
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
if (isProperties(f.cite.file)) {
|
|
2341
|
+
const k = propertiesKeyAt(lines, f.cite.line);
|
|
2342
|
+
if (k && k.split(".").at(-1) === segs.at(-1)) {
|
|
2343
|
+
if (k !== segs.join(".") && !k.endsWith(`.${segs.join(".")}`))
|
|
2344
|
+
return `${where} sets ${k}, not ${f.key}`;
|
|
2345
|
+
if (value !== void 0) {
|
|
2346
|
+
if (!has(at.slice(at.indexOf(k) + k.length)))
|
|
2347
|
+
return `${where} sets ${k} to something other than the value claimed`;
|
|
2348
|
+
return void 0;
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
if (value === void 0 || value === "")
|
|
2353
|
+
return void 0;
|
|
2354
|
+
const near = [f.cite.line - 1, f.cite.line, f.cite.line + 1].map((n) => lines[n - 1] ?? "");
|
|
2355
|
+
const partLines = (f.cite.with ?? []).map((p) => linesOf2(p.file)?.[p.line - 1] ?? "");
|
|
2356
|
+
if (![...near, ...partLines].some(has))
|
|
2357
|
+
return `${where} (or the line either side) and its parts don't write the value claimed`;
|
|
2358
|
+
return void 0;
|
|
2359
|
+
}
|
|
2360
|
+
|
|
2361
|
+
// packages/verify/dist/reachable.js
|
|
2362
|
+
var CODE = /\.(java|kt|kts|scala|groovy|cs|vb|fs|py|rb|go|rs|php|swift|ts|tsx|js|mjs|cjs|dart)$/i;
|
|
2363
|
+
var MODEL_DIR = /(^|\/)(models?|dtos?|payloads?|schemas?|pojos?|beans|viewmodels?)\//i;
|
|
2364
|
+
var MODEL_NAME = /(dto|request|response|payload|model|body)$/i;
|
|
2365
|
+
var MODEL_PART = /[._-](dto|model|schema|payload|request|response)\.[^/.]+$/i;
|
|
2366
|
+
var MAPS_TABLE = /@Entity\b|@Table\b|@Document\b|\[Table\(|__tablename__|models\.Model\b|@Entity\(|\bgorm\.Model\b/;
|
|
2367
|
+
var ROOT_PART = /[._-](controller|resolver|gateway|handlers?|router|routes?|consumer|listener|subscriber|client|publisher|producer|endpoints?)\.[^/.]+$/i;
|
|
2368
|
+
var CLIENT_NAME = /(client|gateway|publisher|producer|sender|feign|proxy|connector)$/i;
|
|
2369
|
+
var CLIENT_DIR = /(^|\/)(clients?|gateways?|integrations?|publishers?|producers?|outbound)\//i;
|
|
2370
|
+
var base = (path) => path.slice(path.lastIndexOf("/") + 1);
|
|
2371
|
+
var stem = (path) => {
|
|
2372
|
+
const b = base(path);
|
|
2373
|
+
const dot = b.indexOf(".");
|
|
2374
|
+
return dot > 0 ? b.slice(0, dot) : b;
|
|
2375
|
+
};
|
|
2376
|
+
function isModelFile(path, text) {
|
|
2377
|
+
if (!CODE.test(path) || readingRank(path) === 5)
|
|
2378
|
+
return false;
|
|
2379
|
+
if (!MODEL_DIR.test(path) && !MODEL_NAME.test(stem(path)) && !MODEL_PART.test(path))
|
|
2380
|
+
return false;
|
|
2381
|
+
return text === void 0 || !MAPS_TABLE.test(text);
|
|
2382
|
+
}
|
|
2383
|
+
var ENTRY_POINT_NAME = /(controller|resource|router|routes?|handlers?|listener|consumer|subscriber|endpoints?|servlet|webhook|resolver)$/i;
|
|
2384
|
+
var ENTRY_POINT_DIR = /(^|\/)(controllers?|routes|routers|handlers|endpoints|listeners|consumers)\//i;
|
|
2385
|
+
var ENTRY_POINT_PART = /[._-](controller|resolver|handlers?|router|routes?|consumer|listener|subscriber|endpoints?)\.[^/.]+$/i;
|
|
2386
|
+
function isEntryPointFile(path) {
|
|
2387
|
+
if (!CODE.test(path) || readingRank(path) === 5 || isModelFile(path))
|
|
2388
|
+
return false;
|
|
2389
|
+
return ENTRY_POINT_NAME.test(stem(path)) || ENTRY_POINT_DIR.test(path) || ENTRY_POINT_PART.test(path);
|
|
2390
|
+
}
|
|
2391
|
+
function isRootFile(path) {
|
|
2392
|
+
if (!CODE.test(path) || readingRank(path) === 5 || isModelFile(path))
|
|
2393
|
+
return false;
|
|
2394
|
+
return readingRank(path) === 2 || isEntryPointFile(path) || ROOT_PART.test(path) || CLIENT_NAME.test(stem(path)) || CLIENT_DIR.test(path);
|
|
2395
|
+
}
|
|
2396
|
+
var DECLARES = /\b(?:class|record|interface|struct|enum|object)\s+([A-Za-z_][A-Za-z0-9_]*)|^\s*(?:export\s+)?(?:declare\s+)?type\s+([A-Za-z_][A-Za-z0-9_]*)/gm;
|
|
2397
|
+
var IDENT = /[A-Za-z_][A-Za-z0-9_]*/g;
|
|
2398
|
+
function declaredTypes(path, text) {
|
|
2399
|
+
const out = [];
|
|
2400
|
+
const s = stem(path);
|
|
2401
|
+
if (/^[A-Z][A-Za-z0-9_]*$/.test(s))
|
|
2402
|
+
out.push(s);
|
|
2403
|
+
for (const m of text.matchAll(DECLARES)) {
|
|
2404
|
+
const n = m[1] ?? m[2];
|
|
2405
|
+
if (n && !out.includes(n))
|
|
2406
|
+
out.push(n);
|
|
2407
|
+
}
|
|
2408
|
+
return out;
|
|
2409
|
+
}
|
|
2410
|
+
function identifiers(text) {
|
|
2411
|
+
return [...new Set(text.match(IDENT) ?? [])];
|
|
2412
|
+
}
|
|
2413
|
+
var NOT_REACHED_WHY = "model classes no entry point, call or field fact reaches (ADR 0169): left out of the read; atticus map <repo> --models all reads them";
|
|
2414
|
+
function reachableModels(o) {
|
|
2415
|
+
const texts = /* @__PURE__ */ new Map();
|
|
2416
|
+
const textOf = (p) => {
|
|
2417
|
+
if (!texts.has(p))
|
|
2418
|
+
texts.set(p, o.read(p) ?? "");
|
|
2419
|
+
return texts.get(p);
|
|
2420
|
+
};
|
|
2421
|
+
const ordered = readingOrder(o.paths);
|
|
2422
|
+
const models = ordered.filter((p) => isModelFile(p, textOf(p))).sort();
|
|
2423
|
+
const isModel = new Set(models);
|
|
2424
|
+
const byName = /* @__PURE__ */ new Map();
|
|
2425
|
+
const declared = /* @__PURE__ */ new Map();
|
|
2426
|
+
for (const p of models) {
|
|
2427
|
+
const names = declaredTypes(p, textOf(p));
|
|
2428
|
+
declared.set(p, names);
|
|
2429
|
+
for (const n of names)
|
|
2430
|
+
byName.set(n, [...byName.get(n) ?? [], p]);
|
|
2431
|
+
}
|
|
2432
|
+
const known = new Set(o.paths);
|
|
2433
|
+
const roots = [];
|
|
2434
|
+
const addRoot = (p) => {
|
|
2435
|
+
if (known.has(p) && !isModel.has(p) && !roots.includes(p))
|
|
2436
|
+
roots.push(p);
|
|
2437
|
+
};
|
|
2438
|
+
const facts = o.facts ?? [];
|
|
2439
|
+
const entries = o.from === "entries";
|
|
2440
|
+
const calls2 = new Set(facts.filter((f) => f.kind === "call").map((f) => f.id));
|
|
2441
|
+
for (const f of facts)
|
|
2442
|
+
if (f.kind === "entry" || f.kind === "call" && !entries)
|
|
2443
|
+
for (const p of citedFiles(f))
|
|
2444
|
+
addRoot(p);
|
|
2445
|
+
for (const p of ordered)
|
|
2446
|
+
if (entries ? isEntryPointFile(p) : isRootFile(p))
|
|
2447
|
+
addRoot(p);
|
|
2448
|
+
const reached = /* @__PURE__ */ new Map();
|
|
2449
|
+
const queue = [];
|
|
2450
|
+
const reach = (names, from, own = []) => {
|
|
2451
|
+
for (const n of names) {
|
|
2452
|
+
if (own.includes(n))
|
|
2453
|
+
continue;
|
|
2454
|
+
for (const p of byName.get(n) ?? []) {
|
|
2455
|
+
const r = reached.get(p);
|
|
2456
|
+
if (r) {
|
|
2457
|
+
if (r.from === from && !r.types.includes(n))
|
|
2458
|
+
r.types.push(n);
|
|
2459
|
+
continue;
|
|
2460
|
+
}
|
|
2461
|
+
reached.set(p, { path: p, types: [n], from });
|
|
2462
|
+
queue.push(p);
|
|
2463
|
+
}
|
|
1908
2464
|
}
|
|
1909
2465
|
};
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
for (const
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
2466
|
+
for (const p of roots)
|
|
2467
|
+
reach(identifiers(textOf(p)), p);
|
|
2468
|
+
for (const f of facts) {
|
|
2469
|
+
for (const p of citedFiles(f))
|
|
2470
|
+
if (isModel.has(p) && !reached.has(p)) {
|
|
2471
|
+
reached.set(p, { path: p, types: [...(declared.get(p) ?? []).slice(0, 1)], from: f.id });
|
|
2472
|
+
queue.push(p);
|
|
2473
|
+
}
|
|
2474
|
+
if (f.kind === "field" && !(entries && calls2.has(f.owner)))
|
|
2475
|
+
reach(identifiers([f.type ?? "", f.transform === "message type" ? f.name : ""].join(" ")), f.id);
|
|
1919
2476
|
}
|
|
1920
|
-
|
|
2477
|
+
const rooted = roots.length > 0 || reached.size > 0;
|
|
2478
|
+
if (!rooted)
|
|
2479
|
+
return {
|
|
2480
|
+
rooted,
|
|
2481
|
+
roots,
|
|
2482
|
+
reached: models.map((p) => ({ path: p, types: declared.get(p) ?? [], from: "" })),
|
|
2483
|
+
notReached: [],
|
|
2484
|
+
models: models.length
|
|
2485
|
+
};
|
|
2486
|
+
for (let i = 0; i < queue.length; i++) {
|
|
2487
|
+
const p = queue[i];
|
|
2488
|
+
reach(identifiers(textOf(p)), p, declared.get(p));
|
|
2489
|
+
}
|
|
2490
|
+
return {
|
|
2491
|
+
rooted,
|
|
2492
|
+
roots,
|
|
2493
|
+
reached: queue.map((p) => reached.get(p)),
|
|
2494
|
+
notReached: models.filter((p) => !reached.has(p)),
|
|
2495
|
+
models: models.length
|
|
2496
|
+
};
|
|
1921
2497
|
}
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
2498
|
+
|
|
2499
|
+
// packages/verify/dist/method.js
|
|
2500
|
+
var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
2501
|
+
function wordsOf2(line) {
|
|
2502
|
+
return line.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").toLowerCase().split(/[^a-z]+/).filter(Boolean);
|
|
2503
|
+
}
|
|
2504
|
+
function methodOnLines(method, lines) {
|
|
2505
|
+
const m = method.toLowerCase();
|
|
2506
|
+
return lines.some((l) => wordsOf2(l).includes(m));
|
|
2507
|
+
}
|
|
2508
|
+
var CHAIN_LINES = 8;
|
|
2509
|
+
var CONTINUES = /^\s*\??\./;
|
|
2510
|
+
function chainOf(file, line) {
|
|
2511
|
+
const at = (n) => file?.[n - 1];
|
|
2512
|
+
const cited = at(line);
|
|
2513
|
+
if (cited === void 0)
|
|
2514
|
+
return [];
|
|
2515
|
+
const out = [cited];
|
|
2516
|
+
for (let n = line, k = 0; k < CHAIN_LINES && CONTINUES.test(at(n) ?? ""); k++, n--) {
|
|
2517
|
+
const above = at(n - 1);
|
|
2518
|
+
if (above === void 0)
|
|
2519
|
+
break;
|
|
2520
|
+
out.push(above);
|
|
1928
2521
|
}
|
|
1929
|
-
|
|
1930
|
-
|
|
2522
|
+
for (let n = line + 1, k = 0; k < CHAIN_LINES && CONTINUES.test(at(n) ?? ""); k++, n++)
|
|
2523
|
+
out.push(at(n));
|
|
2524
|
+
return out;
|
|
1931
2525
|
}
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
kind: c.kind,
|
|
1935
|
-
value: c.value,
|
|
1936
|
-
text: c.text
|
|
1937
|
-
});
|
|
1938
|
-
var SPEC_MARK = /^\s*["']?(openapi|swagger)["']?\s*:/m;
|
|
1939
|
-
var SPEC_EXT = /\.(ya?ml|json)$/i;
|
|
1940
|
-
function specOpsUncoveredIn(file, text, facts) {
|
|
1941
|
-
if (!SPEC_EXT.test(file) || !SPEC_MARK.test(text.slice(0, 4e3)))
|
|
2526
|
+
function methodUnseenOf(f, lines, factOf) {
|
|
2527
|
+
if (f.kind !== "entry" && f.kind !== "call")
|
|
1942
2528
|
return void 0;
|
|
1943
|
-
|
|
1944
|
-
try {
|
|
1945
|
-
doc = readOpenApiDocument(text);
|
|
1946
|
-
} catch {
|
|
2529
|
+
if (!f.method || !HTTP_METHODS.has(f.method.toUpperCase()))
|
|
1947
2530
|
return void 0;
|
|
1948
|
-
|
|
1949
|
-
|
|
2531
|
+
const at = (file, line) => lines(file)?.[line - 1];
|
|
2532
|
+
const route = f.kind === "call" && f.from ? factOf?.(f.from) : void 0;
|
|
2533
|
+
const forwards = route?.kind === "entry" && route.method?.toUpperCase() === f.method.toUpperCase();
|
|
2534
|
+
const looked = [
|
|
2535
|
+
...chainOf(lines(f.cite.file), f.cite.line),
|
|
2536
|
+
at(f.cite.file, f.cite.line + 1),
|
|
2537
|
+
...(f.cite.with ?? []).map((p) => at(p.file, p.line)),
|
|
2538
|
+
...forwards ? [at(route.cite.file, route.cite.line), at(route.cite.file, route.cite.line + 1)] : []
|
|
2539
|
+
].filter((l) => l !== void 0);
|
|
2540
|
+
if (methodOnLines(f.method, looked))
|
|
1950
2541
|
return void 0;
|
|
1951
|
-
const
|
|
1952
|
-
|
|
1953
|
-
if (!s)
|
|
1954
|
-
return "";
|
|
1955
|
-
const p = /^[a-z0-9+.-]+:\/\/[^/]+(\/.*)?$/i.exec(s)?.[1] ?? (s.startsWith("/") ? s : "");
|
|
1956
|
-
return p.replace(/\/+$/, "");
|
|
1957
|
-
})();
|
|
1958
|
-
const entries = facts.filter((f) => f.kind === "entry");
|
|
1959
|
-
const atLines = /* @__PURE__ */ new Set();
|
|
1960
|
-
for (const e of entries)
|
|
1961
|
-
for (const k of indexFacts([e]).at)
|
|
1962
|
-
atLines.add(k);
|
|
1963
|
-
const out = [];
|
|
1964
|
-
for (const op of doc.operations) {
|
|
1965
|
-
const lines = [op.methodLine, op.line].filter((n) => n !== void 0);
|
|
1966
|
-
if (lines.some((n) => [n - 1, n, n + 1].some((x) => atLines.has(`${file}:${x}`))))
|
|
1967
|
-
continue;
|
|
1968
|
-
const method = op.method.toUpperCase();
|
|
1969
|
-
const own = normPath(op.path);
|
|
1970
|
-
const full = normPath(`${server}${op.path}`);
|
|
1971
|
-
const covered = entries.some((e) => {
|
|
1972
|
-
if (e.method && e.method.toUpperCase() !== method)
|
|
1973
|
-
return false;
|
|
1974
|
-
const p = normPath(e.path);
|
|
1975
|
-
return p === own || p === full || p.endsWith(own) || p.split("/").length > 2 && own.endsWith(p);
|
|
1976
|
-
});
|
|
1977
|
-
if (covered)
|
|
1978
|
-
continue;
|
|
1979
|
-
const opId = op.node?.get?.("operationId");
|
|
1980
|
-
const line = op.methodLine ?? op.line ?? 1;
|
|
1981
|
-
out.push({
|
|
1982
|
-
spec: file,
|
|
1983
|
-
method,
|
|
1984
|
-
path: op.path,
|
|
1985
|
-
...typeof opId === "string" ? { operationId: opId } : {},
|
|
1986
|
-
cite: `${file}:${line}`,
|
|
1987
|
-
message: `${file}:${line} declares ${method} ${op.path}${typeof opId === "string" ? ` (${opId})` : ""}, which no entry covers`
|
|
1988
|
-
});
|
|
1989
|
-
}
|
|
1990
|
-
return out;
|
|
1991
|
-
}
|
|
1992
|
-
var REVIEWED_HOLDS_SHOWN = 5;
|
|
1993
|
-
function reviewedHoldsOf(r, skipped) {
|
|
1994
|
-
const n = skipped.length;
|
|
1995
|
-
const first = skipped.slice(0, 3).map((s) => `${s.cite} (${s.value})`);
|
|
2542
|
+
const cite2 = `${f.cite.file}:${f.cite.line}`;
|
|
2543
|
+
const method = f.method.toUpperCase();
|
|
1996
2544
|
return {
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
message: `${
|
|
2545
|
+
id: f.id,
|
|
2546
|
+
kind: f.kind,
|
|
2547
|
+
method,
|
|
2548
|
+
cite: cite2,
|
|
2549
|
+
message: `${f.id} claims ${method}, which neither ${cite2}, the chain it is in, the next line, a cite.with line nor the route it forwards writes`
|
|
2002
2550
|
};
|
|
2003
2551
|
}
|
|
2004
2552
|
|
|
@@ -2076,9 +2624,12 @@ var repoModule = (exposes) => {
|
|
|
2076
2624
|
const m = /^([^/]+)\/([^/]+)$/.exec(exposes.trim());
|
|
2077
2625
|
return m ? { repo: m[1], module: m[2] } : void 0;
|
|
2078
2626
|
};
|
|
2627
|
+
var PLACEHOLDER_KEY = /^\$\{([A-Za-z_][A-Za-z0-9_.-]*)\}$/;
|
|
2079
2628
|
var routeOrWord = (v) => v.includes("/") ? { kind: "route", value: v } : { kind: "word", value: v };
|
|
2080
2629
|
function claimsOf(f) {
|
|
2081
2630
|
switch (f.kind) {
|
|
2631
|
+
// A call whose path is a setting's placeholder a helper puts together is checked apart
|
|
2632
|
+
// (`helperBuildsKey`): its bare key is never a claim, or a settings line would be a call.
|
|
2082
2633
|
case "entry":
|
|
2083
2634
|
case "call":
|
|
2084
2635
|
return [routeOrWord(f.path)];
|
|
@@ -2117,6 +2668,14 @@ function claimsOf(f) {
|
|
|
2117
2668
|
// ADR 0180: the signal the type rests on, as written on its line.
|
|
2118
2669
|
case "component":
|
|
2119
2670
|
return [{ kind: "word", value: f.cite.value }];
|
|
2671
|
+
// ADR 0192: the coordinates as the build file writes them on the line (the name, or a
|
|
2672
|
+
// Gradle line's whole `group:name:version`); `buildCoordinatesProblem` reads the rest.
|
|
2673
|
+
case "artifact":
|
|
2674
|
+
case "dependency":
|
|
2675
|
+
return [
|
|
2676
|
+
{ kind: "word", value: f.cite.value },
|
|
2677
|
+
{ kind: "word", value: f.name }
|
|
2678
|
+
];
|
|
2120
2679
|
}
|
|
2121
2680
|
}
|
|
2122
2681
|
var sameCommit = (a, b) => a.startsWith(b) || b.startsWith(a);
|
|
@@ -2295,6 +2854,11 @@ async function verifyFacts(o) {
|
|
|
2295
2854
|
code: "claim-not-on-line",
|
|
2296
2855
|
message: `${label} claims ${claims.map((c) => `"${c.value}"`).join(" or ")}, which ${where} (or the line either side)${parts.length ? " and its parts" : ""} does not name${parts.length || !withHint ? "" : "; if it is put together from other lines (a base URL, a prefix, a context path), cite them in cite.with"}`
|
|
2297
2856
|
};
|
|
2857
|
+
if (claims && parts.length && isCommentLine(lines[cite2.line - 1] ?? "") && !/(^|\/)_redirects$/.test(cite2.file))
|
|
2858
|
+
return {
|
|
2859
|
+
code: "claim-in-comment",
|
|
2860
|
+
message: `${label} cites ${where}, which is a comment; cite the code that does it`
|
|
2861
|
+
};
|
|
2298
2862
|
if (claims && !parts.length) {
|
|
2299
2863
|
const naming = [cite2.line - 1, cite2.line, cite2.line + 1].map((n) => lines[n - 1]).filter((l) => l !== void 0 && claims.some((c) => lineNamesClaim(l, c)));
|
|
2300
2864
|
if (naming.length && !/(^|\/)_redirects$/.test(cite2.file) && naming.every(isCommentLine))
|
|
@@ -2342,7 +2906,16 @@ async function verifyFacts(o) {
|
|
|
2342
2906
|
problem(f, "wrong-commit", `${label} was read at ${f.commit}, not at ${o.commit}; read it again`);
|
|
2343
2907
|
continue;
|
|
2344
2908
|
}
|
|
2345
|
-
add(f, checkCite(f.cite, claimsOf(f), label, true, f.kind === "entry" || f.kind === "call" ? (ls, n) => apigeePassThrough({ kind: f.kind, forwards: f.kind === "call" && !!f.from }, f.cite.file, ls, n, f.path)
|
|
2909
|
+
add(f, checkCite(f.cite, claimsOf(f), label, true, f.kind === "entry" || f.kind === "call" ? (ls, n) => apigeePassThrough({ kind: f.kind, forwards: f.kind === "call" && !!f.from }, f.cite.file, ls, n, f.path) || // A path written as a setting's placeholder that no line writes whole (ADR 0172,
|
|
2910
|
+
// beta.24): a helper puts the key together (a `@ConfigurationProperties` prefix, a
|
|
2911
|
+
// map field, the name passed to a lookup). The cited line is code naming the key's
|
|
2912
|
+
// last segment, and one file among the parts proves the rest of the key nests so.
|
|
2913
|
+
f.kind === "call" && PLACEHOLDER_KEY.test(f.path.trim()) && helperBuildsKey(PLACEHOLDER_KEY.exec(f.path.trim())[1], f.cite, linesOf2) : void 0));
|
|
2914
|
+
if (f.kind === "config" && !found.has(f.id)) {
|
|
2915
|
+
const bad = configLineProblem(f, linesOf2, listed2);
|
|
2916
|
+
if (bad)
|
|
2917
|
+
problem(f, "claim-not-on-line", `${label}: ${bad}`);
|
|
2918
|
+
}
|
|
2346
2919
|
if (f.kind === "entry" && f.authCite)
|
|
2347
2920
|
add(f, checkCite({ ...f.authCite }, [{ kind: "word", value: f.authCite.value }], `${label} authCite${f.auth ? ` (auth ${f.auth})` : ""}`, false));
|
|
2348
2921
|
if (f.kind === "entry" && f.authCite && f.auth) {
|
|
@@ -2433,6 +3006,13 @@ async function verifyFacts(o) {
|
|
|
2433
3006
|
if (f.version !== void 0)
|
|
2434
3007
|
add(f, checkCite(f.cite, [{ kind: "word", value: f.version }], `${label} version`, false));
|
|
2435
3008
|
}
|
|
3009
|
+
if ((f.kind === "artifact" || f.kind === "dependency") && !found.has(f.id)) {
|
|
3010
|
+
const bad = buildCoordinatesProblem(f, linesOf2);
|
|
3011
|
+
if (bad)
|
|
3012
|
+
problem(f, "build-coordinates", bad);
|
|
3013
|
+
else if (f.version !== void 0)
|
|
3014
|
+
add(f, checkCite(f.cite, [{ kind: "word", value: f.version }], `${label} version`, false));
|
|
3015
|
+
}
|
|
2436
3016
|
if (f.kind === "flow") {
|
|
2437
3017
|
f.steps.forEach((s, i) => add(f, checkCite(s.cite, stepClaims(s.kind, s.cite.value), `${label} step ${i + 1}`)));
|
|
2438
3018
|
f.errors.forEach((e, i) => add(f, checkCite(e.cite, [routeOrWord(e.cite.value)], `${label} error ${i + 1}`)));
|
|
@@ -2553,8 +3133,18 @@ async function verifyFacts(o) {
|
|
|
2553
3133
|
const excludeRes = (o.exclude ?? []).map(globToRegExp);
|
|
2554
3134
|
const sources = [];
|
|
2555
3135
|
const excluded = [];
|
|
3136
|
+
const secrets = [];
|
|
2556
3137
|
for (const p of o.source.list()) {
|
|
2557
3138
|
o.room?.();
|
|
3139
|
+
if (isSecretPath(p)) {
|
|
3140
|
+
if (insideRepo(p) && isConfigFile(p) && !rules.notProduct.test(p) && !tooBigToRead(o.source, p)) {
|
|
3141
|
+
const text = o.source.read(p);
|
|
3142
|
+
const ls2 = text === void 0 ? void 0 : text.replace(/\r\n?/g, "\n").split("\n");
|
|
3143
|
+
if (ls2 && !binaryLines(ls2))
|
|
3144
|
+
secrets.push(...liveSecretsIn(p, ls2));
|
|
3145
|
+
}
|
|
3146
|
+
continue;
|
|
3147
|
+
}
|
|
2558
3148
|
if (!isSourceFile(p, "", void 0, rules) || tooBigToRead(o.source, p))
|
|
2559
3149
|
continue;
|
|
2560
3150
|
const ls = readLines(p) ?? [""];
|
|
@@ -2562,8 +3152,10 @@ async function verifyFacts(o) {
|
|
|
2562
3152
|
continue;
|
|
2563
3153
|
if (excludeRes.some((re) => re.test(p)))
|
|
2564
3154
|
excluded.push(p);
|
|
2565
|
-
else
|
|
3155
|
+
else {
|
|
2566
3156
|
sources.push(p);
|
|
3157
|
+
secrets.push(...liveSecretsIn(p, ls));
|
|
3158
|
+
}
|
|
2567
3159
|
}
|
|
2568
3160
|
const touched = new Set(o.routed ?? []);
|
|
2569
3161
|
for (const f of accepted)
|
|
@@ -2664,6 +3256,7 @@ async function verifyFacts(o) {
|
|
|
2664
3256
|
const held = files.flatMap(skippedIn);
|
|
2665
3257
|
return held.length ? [reviewedHoldsOf(entry, held)] : [];
|
|
2666
3258
|
});
|
|
3259
|
+
const unrecorded = buildUnrecorded([...touched].filter((p) => isBuildFile(p) && insideRepo(p) && !isSecretPath(p)), (p) => linesOf2(p), accepted);
|
|
2667
3260
|
return {
|
|
2668
3261
|
accepted,
|
|
2669
3262
|
// a rejected fact goes back as it was read, at its own commit, even one that was carried
|
|
@@ -2677,6 +3270,7 @@ async function verifyFacts(o) {
|
|
|
2677
3270
|
ratio
|
|
2678
3271
|
},
|
|
2679
3272
|
redacted,
|
|
3273
|
+
secrets: secrets.sort((a, b) => a.file < b.file ? -1 : a.file > b.file ? 1 : a.line - b.line),
|
|
2680
3274
|
quotesDropped,
|
|
2681
3275
|
carried: accepted.flatMap((f) => carriedFrom.has(f.id) ? [{ id: f.id, from: carriedFrom.get(f.id) }] : []),
|
|
2682
3276
|
corrections: { applied: corrected.applied, stale: corrected.stale },
|
|
@@ -2689,7 +3283,8 @@ async function verifyFacts(o) {
|
|
|
2689
3283
|
skipped,
|
|
2690
3284
|
reviewedHolds,
|
|
2691
3285
|
specOpsUncovered,
|
|
2692
|
-
frameworkGaps: frameworkGaps(accepted, rules.frameworks)
|
|
3286
|
+
frameworkGaps: frameworkGaps(accepted, rules.frameworks),
|
|
3287
|
+
...unrecorded.length ? { buildUnrecorded: unrecorded } : {}
|
|
2693
3288
|
};
|
|
2694
3289
|
}
|
|
2695
3290
|
|
|
@@ -4446,8 +5041,25 @@ var LENS_KINDS = {
|
|
|
4446
5041
|
infrastructure: /* @__PURE__ */ new Set(["estate", "system", "repo", "component", "deployment", "environment"])
|
|
4447
5042
|
};
|
|
4448
5043
|
var LENS_EDGES = {
|
|
4449
|
-
architecture: /* @__PURE__ */ new Set([
|
|
4450
|
-
|
|
5044
|
+
architecture: /* @__PURE__ */ new Set([
|
|
5045
|
+
"calls",
|
|
5046
|
+
"publishes",
|
|
5047
|
+
"subscribes",
|
|
5048
|
+
"uses",
|
|
5049
|
+
"depends-on",
|
|
5050
|
+
"reads",
|
|
5051
|
+
"writes"
|
|
5052
|
+
]),
|
|
5053
|
+
repo: /* @__PURE__ */ new Set([
|
|
5054
|
+
"calls",
|
|
5055
|
+
"publishes",
|
|
5056
|
+
"subscribes",
|
|
5057
|
+
"uses",
|
|
5058
|
+
"depends-on",
|
|
5059
|
+
"reads",
|
|
5060
|
+
"writes",
|
|
5061
|
+
"references"
|
|
5062
|
+
]),
|
|
4451
5063
|
data: /* @__PURE__ */ new Set(["reads", "writes", "references"]),
|
|
4452
5064
|
integration: /* @__PURE__ */ new Set(["calls", "publishes", "subscribes"]),
|
|
4453
5065
|
infrastructure: /* @__PURE__ */ new Set(["deployed-to"])
|
|
@@ -4510,30 +5122,57 @@ var HOW_OF_FLAG = {
|
|
|
4510
5122
|
"joined-by-name": "named",
|
|
4511
5123
|
"joined-by-repo": "repo",
|
|
4512
5124
|
"joined-by-host": "host",
|
|
5125
|
+
// beta.24: a call whose host nothing resolves, by the one proxy BasePath its path starts with.
|
|
5126
|
+
[JOINED_BY_BASE_PATH]: "base-path",
|
|
4513
5127
|
"declared-caller": "declared",
|
|
4514
5128
|
// ADR 0162 §6 (F8): a topic or queue the profile names as an outside system's: a person's word.
|
|
4515
5129
|
[DECLARED_TOPIC]: "declared",
|
|
4516
5130
|
// ADR 0160 (O3): answered by an entry of another team's shared map.
|
|
4517
5131
|
[JOINED_TO_SHARED_MAP]: "shared"
|
|
4518
5132
|
};
|
|
5133
|
+
var GUESS_FLAGS = new Set(JOIN_GUESS_FLAGS);
|
|
4519
5134
|
function joinHow(i) {
|
|
4520
|
-
|
|
5135
|
+
const flags = i.flags ?? [];
|
|
5136
|
+
const topic = i.via === "event-bus" || i.via === "mq";
|
|
5137
|
+
if (i.confidence === "verified") {
|
|
5138
|
+
for (const f of flags)
|
|
5139
|
+
if (HOW_OF_FLAG[f] && !GUESS_FLAGS.has(f))
|
|
5140
|
+
return HOW_OF_FLAG[f];
|
|
5141
|
+
if (topic)
|
|
5142
|
+
return "topic";
|
|
5143
|
+
}
|
|
5144
|
+
for (const f of flags)
|
|
4521
5145
|
if (HOW_OF_FLAG[f])
|
|
4522
5146
|
return HOW_OF_FLAG[f];
|
|
4523
|
-
if (
|
|
5147
|
+
if (topic)
|
|
4524
5148
|
return "topic";
|
|
4525
5149
|
return "unknown";
|
|
4526
5150
|
}
|
|
5151
|
+
var GUESS_HOWS = new Set(JOIN_GUESS_FLAGS.map((f) => HOW_OF_FLAG[f]).filter(Boolean));
|
|
5152
|
+
function alsoOf(i, how) {
|
|
5153
|
+
if (i.confidence !== "verified" || GUESS_HOWS.has(how))
|
|
5154
|
+
return [];
|
|
5155
|
+
return [
|
|
5156
|
+
...new Set((i.flags ?? []).flatMap((f) => GUESS_FLAGS.has(f) && HOW_OF_FLAG[f] ? [HOW_OF_FLAG[f]] : []))
|
|
5157
|
+
];
|
|
5158
|
+
}
|
|
4527
5159
|
function joinOf(i) {
|
|
4528
5160
|
const side = (s) => evidenceOf(i.evidence.filter((e) => e.side === s));
|
|
4529
5161
|
const sided = /* @__PURE__ */ new Set(["caller", "callee", "gateway"]);
|
|
5162
|
+
const how = joinHow(i);
|
|
5163
|
+
const also = alsoOf(i, how);
|
|
4530
5164
|
return {
|
|
4531
5165
|
interface: i.id,
|
|
4532
5166
|
from: i.from,
|
|
4533
5167
|
to: i.to,
|
|
4534
|
-
how
|
|
5168
|
+
how,
|
|
4535
5169
|
gateway: i.via === "gateway",
|
|
4536
|
-
verified:
|
|
5170
|
+
// A link is verified when one of its calls is (ADR 0135 section 5): its how is that call's,
|
|
5171
|
+
// and the guesses its other calls rest on are `also`, never the reason. One with no how but
|
|
5172
|
+
// a guess has no call that wasn't guessed to show, so it is never shown verified beside the
|
|
5173
|
+
// guess's words (beta.24).
|
|
5174
|
+
verified: i.confidence === "verified" && !GUESS_HOWS.has(how),
|
|
5175
|
+
...also.length ? { also } : {},
|
|
4537
5176
|
...i.method ? { method: i.method } : {},
|
|
4538
5177
|
...i.normalizedPath ? { path: i.normalizedPath } : {},
|
|
4539
5178
|
caller: side("caller"),
|
|
@@ -4565,12 +5204,12 @@ function sharedOf(i) {
|
|
|
4565
5204
|
}
|
|
4566
5205
|
};
|
|
4567
5206
|
}
|
|
4568
|
-
function mergeJoins(a, b) {
|
|
5207
|
+
function mergeJoins(a, b, cap = MAX_JOINS) {
|
|
4569
5208
|
const by = new Map(a.map((j) => [j.interface, j]));
|
|
4570
5209
|
for (const j of b)
|
|
4571
5210
|
if (!by.has(j.interface))
|
|
4572
5211
|
by.set(j.interface, j);
|
|
4573
|
-
return [...by.values()].sort((x, y) => x.interface < y.interface ? -1 : x.interface > y.interface ? 1 : 0).slice(0,
|
|
5212
|
+
return [...by.values()].sort((x, y) => x.interface < y.interface ? -1 : x.interface > y.interface ? 1 : 0).slice(0, cap);
|
|
4574
5213
|
}
|
|
4575
5214
|
var props = (o) => {
|
|
4576
5215
|
const out = {};
|
|
@@ -4586,7 +5225,29 @@ var props = (o) => {
|
|
|
4586
5225
|
return out;
|
|
4587
5226
|
};
|
|
4588
5227
|
var all = (rs, k) => rs.filter((r) => r.kind === k).sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
|
|
4589
|
-
function
|
|
5228
|
+
function dependencyJoin(l) {
|
|
5229
|
+
const lines = (end) => end.lines.map((at) => ({ source: "code", repo: end.repo, at }));
|
|
5230
|
+
return {
|
|
5231
|
+
interface: dependencyLinkId(l),
|
|
5232
|
+
from: l.from.component,
|
|
5233
|
+
to: l.to.component,
|
|
5234
|
+
how: "coordinates",
|
|
5235
|
+
gateway: false,
|
|
5236
|
+
// code at both ends, each claim checked on its line, and nobody had to guess
|
|
5237
|
+
verified: true,
|
|
5238
|
+
caller: lines(l.from),
|
|
5239
|
+
callee: lines(l.to),
|
|
5240
|
+
hops: [],
|
|
5241
|
+
other: [],
|
|
5242
|
+
dependency: {
|
|
5243
|
+
group: l.group,
|
|
5244
|
+
name: l.name,
|
|
5245
|
+
...l.version ? { version: l.version } : {},
|
|
5246
|
+
...l.scope ? { scope: l.scope } : {}
|
|
5247
|
+
}
|
|
5248
|
+
};
|
|
5249
|
+
}
|
|
5250
|
+
function buildEstate(records2, o = {}) {
|
|
4590
5251
|
const nodes = /* @__PURE__ */ new Map();
|
|
4591
5252
|
const atoms = [];
|
|
4592
5253
|
const add = (n) => {
|
|
@@ -4692,6 +5353,11 @@ function buildEstate(records2) {
|
|
|
4692
5353
|
}
|
|
4693
5354
|
});
|
|
4694
5355
|
}
|
|
5356
|
+
for (const [sys, n] of [...nodes.entries()].filter(([id]) => id.startsWith("system:"))) {
|
|
5357
|
+
const inside = [...repoSystem.entries()].filter(([, s]) => `system:${s}` === sys && systems.has(s)).map(([r]) => r).sort();
|
|
5358
|
+
if (inside.length)
|
|
5359
|
+
n.properties = { ...n.properties, repos: inside };
|
|
5360
|
+
}
|
|
4695
5361
|
const unknown = (ref) => add({
|
|
4696
5362
|
id: `unknown:${slug2(ref)}`,
|
|
4697
5363
|
kind: "unknown",
|
|
@@ -4892,6 +5558,19 @@ function buildEstate(records2) {
|
|
|
4892
5558
|
evidence: evidenceOf(c.evidence),
|
|
4893
5559
|
gaps: recordGaps(c)
|
|
4894
5560
|
});
|
|
5561
|
+
for (const l of o.dependsOn ?? []) {
|
|
5562
|
+
if (!components.has(l.from.component) || !components.has(l.to.component))
|
|
5563
|
+
continue;
|
|
5564
|
+
const join2 = dependencyJoin(l);
|
|
5565
|
+
atoms.push({
|
|
5566
|
+
from: `component:${l.from.component}`,
|
|
5567
|
+
to: `component:${l.to.component}`,
|
|
5568
|
+
type: "depends-on",
|
|
5569
|
+
evidence: mergeEvidence(join2.caller.slice(0, 1), join2.callee.slice(0, 1)),
|
|
5570
|
+
gaps: [],
|
|
5571
|
+
join: join2
|
|
5572
|
+
});
|
|
5573
|
+
}
|
|
4895
5574
|
for (const t of tables) {
|
|
4896
5575
|
const ev = evidenceOf(t.evidence);
|
|
4897
5576
|
const part = (ref) => {
|
|
@@ -5044,7 +5723,7 @@ function need(est, lens, id) {
|
|
|
5044
5723
|
if (!est.visible.get(lens).has(id))
|
|
5045
5724
|
throw new NoSuchNode(`There is no node ${id} in the ${lens} lens.`);
|
|
5046
5725
|
}
|
|
5047
|
-
function merge(mapped) {
|
|
5726
|
+
function merge(mapped, cap = MAX_JOINS) {
|
|
5048
5727
|
const by = /* @__PURE__ */ new Map();
|
|
5049
5728
|
for (const { from, to, atom } of mapped) {
|
|
5050
5729
|
const id = `${atom.type}:${from}>${to}`;
|
|
@@ -5066,7 +5745,7 @@ function merge(mapped) {
|
|
|
5066
5745
|
continue;
|
|
5067
5746
|
}
|
|
5068
5747
|
if (atom.join)
|
|
5069
|
-
e.joins = mergeJoins(e.joins ?? [], [atom.join]);
|
|
5748
|
+
e.joins = mergeJoins(e.joins ?? [], [atom.join], cap);
|
|
5070
5749
|
e.count++;
|
|
5071
5750
|
if (atom.sync && e.sync !== atom.sync)
|
|
5072
5751
|
e.sync = "mixed";
|
|
@@ -5155,7 +5834,7 @@ function nodeView(est, id, o) {
|
|
|
5155
5834
|
continue;
|
|
5156
5835
|
mapped.push({ from, to, atom });
|
|
5157
5836
|
}
|
|
5158
|
-
let edges = merge(mapped);
|
|
5837
|
+
let edges = merge(mapped, o.everyJoin ? Infinity : MAX_JOINS);
|
|
5159
5838
|
let hidden = 0;
|
|
5160
5839
|
if (!o.all)
|
|
5161
5840
|
({ edges, hidden } = reduceUses(edges));
|
|
@@ -5200,7 +5879,7 @@ function focusView(est, id, o) {
|
|
|
5200
5879
|
node: toNode(est, lens, id),
|
|
5201
5880
|
path: ancestors(est, id).map((n) => toNode(est, lens, n)),
|
|
5202
5881
|
neighbours: [...near].sort().map((n) => toNode(est, lens, n)),
|
|
5203
|
-
edges: merge(ends.filter((e) => set.has(e.from) && set.has(e.to)))
|
|
5882
|
+
edges: merge(ends.filter((e) => set.has(e.from) && set.has(e.to)), o.everyJoin ? Infinity : MAX_JOINS)
|
|
5204
5883
|
};
|
|
5205
5884
|
}
|
|
5206
5885
|
|
|
@@ -6091,6 +6770,7 @@ function houseImportsUntaught(source, o) {
|
|
|
6091
6770
|
export {
|
|
6092
6771
|
insideRepo,
|
|
6093
6772
|
dirSource,
|
|
6773
|
+
isBuildFile,
|
|
6094
6774
|
correctionFor,
|
|
6095
6775
|
outsidePairingFor,
|
|
6096
6776
|
correctedFact,
|