@maycombhq/atticus 2.0.0-beta.23 → 2.0.0-beta.25

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.
Files changed (281) hide show
  1. package/dist/bin.js +3 -3
  2. package/dist/{chunk-S7GUZ45I.js → chunk-23QHP4JJ.js} +5 -3
  3. package/dist/{chunk-73V2OONC.js → chunk-2RABF6RT.js} +17 -15
  4. package/dist/{chunk-ENH6Z4TY.js → chunk-2ULVUSIP.js} +17 -17
  5. package/dist/{chunk-G6EFXTUO.js → chunk-2VN4TLGI.js} +7 -5
  6. package/dist/{chunk-ZSNOILL5.js → chunk-2Y5FJQSF.js} +1 -1
  7. package/dist/{chunk-YDCOZOER.js → chunk-334N6EI2.js} +20 -18
  8. package/dist/chunk-3D74UADA.js +22 -0
  9. package/dist/{chunk-63NFFAGI.js → chunk-3NA2VE45.js} +14 -12
  10. package/dist/{chunk-CJEBRJBS.js → chunk-3VC2XJ53.js} +6 -4
  11. package/dist/{chunk-7NQAGYK4.js → chunk-3WO7ASU7.js} +8 -8
  12. package/dist/{chunk-GM4EFHUX.js → chunk-4GWQVT2C.js} +19 -16
  13. package/dist/{chunk-SVGGMBJI.js → chunk-4PW5SRKJ.js} +15 -13
  14. package/dist/{chunk-27AJAKX7.js → chunk-4SS5ZK47.js} +3 -3
  15. package/dist/{chunk-PQQKZPBU.js → chunk-4U3JLIRC.js} +1 -1
  16. package/dist/{chunk-Z3H27OMV.js → chunk-4WIVTPGE.js} +6 -4
  17. package/dist/{chunk-XF6TSZW2.js → chunk-5267F4BS.js} +6 -4
  18. package/dist/chunk-5CPZIWIN.js +38 -0
  19. package/dist/{chunk-PWXB5GBB.js → chunk-5GLGLWAJ.js} +18 -16
  20. package/dist/{chunk-2QPJ4E4Z.js → chunk-5K6ZKHZR.js} +4 -2
  21. package/dist/{chunk-QZWRPQTI.js → chunk-5OVSDV77.js} +8 -6
  22. package/dist/{chunk-FJVUHQPS.js → chunk-5P4PNGPL.js} +26 -23
  23. package/dist/{chunk-M3EOFSPY.js → chunk-5R3FRI6H.js} +33 -29
  24. package/dist/{chunk-PNSSE7JM.js → chunk-5RDKQOY3.js} +25 -23
  25. package/dist/{chunk-KDJ2YKAZ.js → chunk-5RKN5QIX.js} +9 -7
  26. package/dist/{chunk-3EX5HCZD.js → chunk-5UJ7C7IH.js} +16 -14
  27. package/dist/{chunk-ZLQEQR3D.js → chunk-5WZV37WS.js} +8 -6
  28. package/dist/{chunk-OBUB3H72.js → chunk-62FMA437.js} +14 -12
  29. package/dist/{chunk-UALE35WK.js → chunk-6576X5BJ.js} +5 -3
  30. package/dist/{chunk-TXNSQ24G.js → chunk-6WYOJCB4.js} +3 -3
  31. package/dist/{chunk-TV56QLLV.js → chunk-77REYYY5.js} +5 -3
  32. package/dist/{chunk-QLQIFJP3.js → chunk-7AKJ2XTW.js} +19 -16
  33. package/dist/{chunk-2WUTCPPJ.js → chunk-7E3G5NCH.js} +17 -13
  34. package/dist/{chunk-FVYZ4Y52.js → chunk-7EAH2MFY.js} +5 -3
  35. package/dist/{chunk-PXW2RZGQ.js → chunk-7F4GZ7U2.js} +3 -3
  36. package/dist/{chunk-6RQOINER.js → chunk-7FUQAT2R.js} +6 -4
  37. package/dist/{chunk-AQRUQNFB.js → chunk-7HW2CMIN.js} +10 -8
  38. package/dist/{chunk-AGOLEMHK.js → chunk-7NLYSTEK.js} +10 -8
  39. package/dist/{chunk-YHMPDIRG.js → chunk-7QZDGM5V.js} +6 -4
  40. package/dist/{chunk-MEJ63LDG.js → chunk-7U6PBBXG.js} +11 -9
  41. package/dist/{chunk-UTPIFH4I.js → chunk-7UYRN4ON.js} +5 -3
  42. package/dist/{chunk-5OXKCH4Z.js → chunk-7X3WLAKP.js} +93 -40
  43. package/dist/{chunk-7IFTSAHP.js → chunk-7YFUNWFM.js} +10 -8
  44. package/dist/chunk-7YSMZEO3.js +55 -0
  45. package/dist/{chunk-RPQITJNX.js → chunk-A3AADMM2.js} +10 -8
  46. package/dist/{chunk-VK7WYA64.js → chunk-A3J75BO2.js} +14 -12
  47. package/dist/chunk-AENMOZMM.js +42 -0
  48. package/dist/{chunk-7K5OH45X.js → chunk-AGAFNUYZ.js} +87 -10
  49. package/dist/{chunk-VKTXFFOZ.js → chunk-AYWJMHSX.js} +5 -3
  50. package/dist/{chunk-3UHV76UD.js → chunk-B2U4AOZ5.js} +41 -38
  51. package/dist/chunk-BDKYHCGI.js +71 -0
  52. package/dist/{chunk-RQQYEDAC.js → chunk-BEDZNT62.js} +12 -9
  53. package/dist/{chunk-PGAMTKBI.js → chunk-BIQNPWGX.js} +6 -4
  54. package/dist/{chunk-LSHSDC6S.js → chunk-BJDVI5W6.js} +19 -17
  55. package/dist/{chunk-PFULMC2D.js → chunk-BMMTWRWE.js} +22 -20
  56. package/dist/{chunk-KT6Q44CA.js → chunk-BPDS7KUR.js} +27 -25
  57. package/dist/{chunk-7XYLNQFO.js → chunk-BS52P2CM.js} +13 -5
  58. package/dist/{chunk-TABH4RBZ.js → chunk-C5LX54QK.js} +16 -14
  59. package/dist/{chunk-NCLZJCXA.js → chunk-CB6H7MH2.js} +23 -21
  60. package/dist/{chunk-CZ2ZS7AT.js → chunk-CGVRLQAY.js} +2166 -326
  61. package/dist/{chunk-HJQVUOUL.js → chunk-CMUJSPP4.js} +13 -11
  62. package/dist/{chunk-CT6NINGR.js → chunk-CNF7D3A7.js} +3 -3
  63. package/dist/{chunk-BP33TBLI.js → chunk-CPFAWYVC.js} +9 -7
  64. package/dist/chunk-CQRFCWQV.js +45 -0
  65. package/dist/chunk-CTJHEG6A.js +97 -0
  66. package/dist/{chunk-SCT4CEF7.js → chunk-CVWKS6GO.js} +22 -20
  67. package/dist/chunk-D2CGJ7RR.js +46 -0
  68. package/dist/{chunk-K757G7AD.js → chunk-D45K3XKK.js} +19 -16
  69. package/dist/chunk-D7QIZLWB.js +38 -0
  70. package/dist/{chunk-YERAAEO4.js → chunk-DAHKLVHU.js} +15 -13
  71. package/dist/{chunk-OPWGPQ2N.js → chunk-DBVQEPZB.js} +8 -6
  72. package/dist/{chunk-T33TPFGI.js → chunk-DCPI3ETH.js} +24 -22
  73. package/dist/{chunk-RRQUQAXP.js → chunk-DJ4C5ELF.js} +5 -2
  74. package/dist/{chunk-RCG5IAAT.js → chunk-DLNQ3HUM.js} +12 -10
  75. package/dist/chunk-DM3H4V2G.js +62 -0
  76. package/dist/{chunk-EVTI22PQ.js → chunk-DMQJDHXG.js} +7 -4
  77. package/dist/{chunk-5VTIWEWP.js → chunk-DPZD7WVX.js} +4 -2
  78. package/dist/{chunk-WF3RCZNO.js → chunk-DYVUNT4O.js} +9 -7
  79. package/dist/{chunk-2UMSHYCB.js → chunk-E2OP6JNF.js} +26 -24
  80. package/dist/{chunk-6Y4FXOMI.js → chunk-E7PR4WMM.js} +24 -22
  81. package/dist/{chunk-TNCF26JK.js → chunk-EAGSM3XY.js} +14 -12
  82. package/dist/{chunk-X5ZHDSLU.js → chunk-EJGUEUXG.js} +25 -23
  83. package/dist/chunk-ELKTDXV3.js +67 -0
  84. package/dist/{chunk-T3FNG2H2.js → chunk-ELNIQYLR.js} +14 -12
  85. package/dist/{chunk-DHKDH464.js → chunk-ELNLHU7Y.js} +6 -4
  86. package/dist/{chunk-CA3DKO4D.js → chunk-EM7F6XEU.js} +4 -2
  87. package/dist/{chunk-K4OXYSGS.js → chunk-EP7ZBZLT.js} +7 -5
  88. package/dist/chunk-EPXYFJTY.js +278 -0
  89. package/dist/{chunk-MBYYQHPM.js → chunk-EUCATH2U.js} +6 -4
  90. package/dist/{chunk-73CC73I4.js → chunk-EXCXNDTQ.js} +1 -1
  91. package/dist/{chunk-SRTUETF5.js → chunk-EXGXCVWC.js} +24 -22
  92. package/dist/{chunk-BYBU2EIB.js → chunk-F36DIKJ3.js} +23 -21
  93. package/dist/{chunk-P22EPEBR.js → chunk-F4WKGX7K.js} +18 -16
  94. package/dist/{chunk-ZJGCGKA4.js → chunk-F56DNMDD.js} +5 -3
  95. package/dist/chunk-FJS2FZFZ.js +41 -0
  96. package/dist/{chunk-2YSD6E6V.js → chunk-FNP4M4VL.js} +42 -33
  97. package/dist/{chunk-B4AEL3RF.js → chunk-G3ZFEHCX.js} +21 -107
  98. package/dist/{chunk-XOMEQVLK.js → chunk-G5P7F6RQ.js} +5 -3
  99. package/dist/chunk-GAU2IFIC.js +33 -0
  100. package/dist/{chunk-XNFM6WUK.js → chunk-GAVEIYKH.js} +21 -18
  101. package/dist/{chunk-TUM52SOE.js → chunk-GD6FXN6R.js} +17 -15
  102. package/dist/{chunk-D6BVLTDV.js → chunk-GDGE7ZHC.js} +28 -26
  103. package/dist/{chunk-SYP56T2D.js → chunk-GIOOA2ZO.js} +7 -4
  104. package/dist/chunk-GLISHJ4G.js +21345 -0
  105. package/dist/chunk-GPOL5H3B.js +55 -0
  106. package/dist/{chunk-ZFHFC74B.js → chunk-GVOQJPKA.js} +20 -18
  107. package/dist/{chunk-G7VBMOZH.js → chunk-GX67TNFA.js} +3 -3
  108. package/dist/{chunk-VNIN7Q6Q.js → chunk-H75SPCAW.js} +18 -16
  109. package/dist/{chunk-J4CPHJUL.js → chunk-H7GAPNGQ.js} +29 -18
  110. package/dist/{chunk-X7ZKNSK4.js → chunk-HD72AL3L.js} +20 -18
  111. package/dist/{chunk-FBCVC2GJ.js → chunk-HHZ2ZKUD.js} +16 -13
  112. package/dist/{chunk-K4RNVDR4.js → chunk-HHZEXF7V.js} +8 -6
  113. package/dist/{chunk-OK6JGLE7.js → chunk-HR34F2AJ.js} +14 -12
  114. package/dist/{chunk-3MYBT62N.js → chunk-HU7VXMFV.js} +9 -7
  115. package/dist/{chunk-LPDTDFKA.js → chunk-HV3KPEFH.js} +18 -16
  116. package/dist/{chunk-4ETO2FXE.js → chunk-I2M7MXSV.js} +14 -12
  117. package/dist/{chunk-W3AZE7LN.js → chunk-IDTVBZQI.js} +3 -3
  118. package/dist/{chunk-BFL4PO64.js → chunk-IFDCCCEN.js} +6 -4
  119. package/dist/{chunk-3ZA3AK2D.js → chunk-IKRM64KR.js} +12 -10
  120. package/dist/{chunk-JMEWJPF2.js → chunk-IMTAHDME.js} +7 -7
  121. package/dist/{chunk-DCRYOMTM.js → chunk-IP6TSICI.js} +14 -12
  122. package/dist/{chunk-PT4USJNN.js → chunk-IW3QMW3X.js} +10 -8
  123. package/dist/{chunk-MLGWSBF4.js → chunk-IWQEZFVV.js} +261 -62
  124. package/dist/{chunk-C6ORPLCN.js → chunk-J65TN6QU.js} +7 -5
  125. package/dist/{chunk-QBMLBCQH.js → chunk-JCKKAELC.js} +16 -13
  126. package/dist/{chunk-XGO74QWR.js → chunk-JJEPU4VS.js} +7 -5
  127. package/dist/{chunk-BFMTGNAQ.js → chunk-JKEUPSCE.js} +5 -3
  128. package/dist/{chunk-HMZ2DRBC.js → chunk-JMOZ6K5A.js} +16 -5
  129. package/dist/{chunk-WZYM5M4U.js → chunk-JQGWP3SC.js} +19 -17
  130. package/dist/{chunk-ZR6J4QFQ.js → chunk-JWLABUXL.js} +13 -11
  131. package/dist/{chunk-EXJZBL5N.js → chunk-JXLUHMTC.js} +23 -21
  132. package/dist/{chunk-DSHRA72L.js → chunk-K373N5U6.js} +13 -11
  133. package/dist/{chunk-WYGTSZHR.js → chunk-K3OIBTCV.js} +16 -14
  134. package/dist/{chunk-BAY4K55I.js → chunk-K4C2DWOZ.js} +16 -13
  135. package/dist/{chunk-GOZLTLRY.js → chunk-K77ILFUQ.js} +4 -4
  136. package/dist/{chunk-4R3TO4VL.js → chunk-KFDOL2Y4.js} +19 -17
  137. package/dist/{chunk-T6MX7WXM.js → chunk-KGT5RIGE.js} +30 -13
  138. package/dist/{chunk-SWNKO4C4.js → chunk-KJPKIU2R.js} +29 -26
  139. package/dist/{chunk-T7IIEDA3.js → chunk-KN4UQJ7R.js} +6 -4
  140. package/dist/{chunk-AVMWESFZ.js → chunk-KW4DIXUL.js} +6 -3
  141. package/dist/{chunk-FRAEQVYN.js → chunk-KY3BUZYI.js} +24 -22
  142. package/dist/{chunk-FMJYKLDY.js → chunk-LGE6H4UP.js} +15 -8
  143. package/dist/{chunk-XAPXKFIS.js → chunk-LKRMVWXB.js} +33 -24
  144. package/dist/{chunk-BUUJ7N4O.js → chunk-LMNCRSER.js} +31 -11
  145. package/dist/{chunk-TMFMXQEN.js → chunk-LNGFTPU7.js} +22 -19
  146. package/dist/{chunk-N2YX6JMY.js → chunk-LOJGNSPA.js} +28 -23
  147. package/dist/{chunk-6ZSYLZ7O.js → chunk-LP5QGTCR.js} +3 -3
  148. package/dist/{chunk-S35DIFJH.js → chunk-LPXH2DA4.js} +19 -17
  149. package/dist/{chunk-FRCOKUU4.js → chunk-LQD3R6NZ.js} +9 -7
  150. package/dist/{chunk-FPBUTZI5.js → chunk-LZFKJ2BR.js} +3233 -22921
  151. package/dist/{chunk-TDSCKP3V.js → chunk-M6HI36T3.js} +2 -2
  152. package/dist/{chunk-SK5RVP7X.js → chunk-M7XNX5IC.js} +11 -9
  153. package/dist/{chunk-RGZFOKVO.js → chunk-MELS6T5J.js} +6 -4
  154. package/dist/{chunk-6NN36LVK.js → chunk-MJAIBPI5.js} +3 -3
  155. package/dist/{chunk-Y2H7X3VI.js → chunk-MJMEF7SD.js} +10 -8
  156. package/dist/{chunk-FTLYXMHA.js → chunk-MJOIMGS4.js} +7 -5
  157. package/dist/chunk-MLUHBVCI.js +45 -0
  158. package/dist/{chunk-JXAKYP45.js → chunk-MM5OAVSW.js} +27 -25
  159. package/dist/{chunk-6ZFF7XSL.js → chunk-MM7YWUBB.js} +6 -6
  160. package/dist/{chunk-S5GSQPIN.js → chunk-MN2XDLDM.js} +18 -16
  161. package/dist/{chunk-MNIPPBCT.js → chunk-MWOPED6I.js} +7 -5
  162. package/dist/{chunk-JFFKHIM6.js → chunk-MXPKXCGP.js} +1 -1
  163. package/dist/{chunk-IYNCSYU4.js → chunk-MZTU5L6S.js} +6 -4
  164. package/dist/{chunk-NAPHHWW2.js → chunk-N3OEBQTA.js} +3 -3
  165. package/dist/{chunk-PCCLVIDP.js → chunk-N6SSI6XO.js} +25 -22
  166. package/dist/{chunk-POSDBRKV.js → chunk-NB664KWQ.js} +28 -25
  167. package/dist/{chunk-Z3RAFU5B.js → chunk-NL6GIEJU.js} +17 -15
  168. package/dist/{chunk-ISG547IS.js → chunk-NMBHFSJQ.js} +24 -22
  169. package/dist/{chunk-CFUDAW3R.js → chunk-NMGFXT4S.js} +17 -15
  170. package/dist/{chunk-ZENHDXRZ.js → chunk-NPZ4KXIV.js} +20 -18
  171. package/dist/{chunk-CQ7RF4QN.js → chunk-NQLTWGF4.js} +6 -4
  172. package/dist/{chunk-KTNOBTV5.js → chunk-O6DJMDBR.js} +6 -4
  173. package/dist/{chunk-MH2ZK67S.js → chunk-OEUTV6EL.js} +15 -12
  174. package/dist/{chunk-CKVBDVIW.js → chunk-OMSH46JK.js} +6 -4
  175. package/dist/chunk-ONB7M2AF.js +52 -0
  176. package/dist/{chunk-QX4MAMUG.js → chunk-OOU4N2JQ.js} +136 -30
  177. package/dist/{chunk-4MYHETJ3.js → chunk-OW53P52N.js} +20 -18
  178. package/dist/{chunk-APDN6UOR.js → chunk-P4QTTCVK.js} +20 -18
  179. package/dist/{chunk-JSP73CDW.js → chunk-P56N3NPT.js} +8 -5
  180. package/dist/{chunk-CS4BMJLL.js → chunk-PCZ4C2V7.js} +7 -5
  181. package/dist/{chunk-A4JXVO5O.js → chunk-PGKCRK77.js} +10 -8
  182. package/dist/{chunk-RLZFL76D.js → chunk-PYVFLITV.js} +15 -13
  183. package/dist/{chunk-Z2D4P3R3.js → chunk-Q52KWTG5.js} +14 -12
  184. package/dist/{chunk-YD3KTW4H.js → chunk-Q6UYUCNS.js} +14 -12
  185. package/dist/chunk-QBK33722.js +51 -0
  186. package/dist/{chunk-L3RCQWVQ.js → chunk-QE444DZ2.js} +53 -26
  187. package/dist/{chunk-Y5IE6YKD.js → chunk-QEP4HTJE.js} +6 -4
  188. package/dist/{chunk-FSN6JFXB.js → chunk-QFOJ3UPU.js} +25 -19
  189. package/dist/{chunk-3424TLIJ.js → chunk-QQD25YNF.js} +12 -10
  190. package/dist/{chunk-HRS5O7VV.js → chunk-QSKY7FE3.js} +21 -17
  191. package/dist/{chunk-LO6Y7OTG.js → chunk-R6HJ4SDB.js} +10 -7
  192. package/dist/{chunk-QLWDIKO4.js → chunk-RFQW7XT3.js} +20 -17
  193. package/dist/{chunk-4GAB5ZOZ.js → chunk-RL7PETU6.js} +30 -26
  194. package/dist/{chunk-66AQ2JIU.js → chunk-ROVOAF2O.js} +13 -11
  195. package/dist/{chunk-UJF7PIMP.js → chunk-RSA5JJMN.js} +58 -34
  196. package/dist/{chunk-J32IPTVQ.js → chunk-RX56MZLX.js} +22 -20
  197. package/dist/chunk-S7I7SLZN.js +59 -0
  198. package/dist/{chunk-S6W3D5GS.js → chunk-S7UQFI4B.js} +29 -26
  199. package/dist/{chunk-TVQSXWWV.js → chunk-SBNBVUOF.js} +35 -33
  200. package/dist/{chunk-POEMZECG.js → chunk-SD3PGZSR.js} +1 -1
  201. package/dist/{chunk-EMVZIOOD.js → chunk-SEBBJQWK.js} +17 -15
  202. package/dist/{chunk-MWF4PXQR.js → chunk-SGTAQNOP.js} +37 -34
  203. package/dist/{chunk-HUGQZQ2K.js → chunk-SHWHRCMU.js} +9 -7
  204. package/dist/{chunk-POSZFDSQ.js → chunk-SRLUADSY.js} +6 -4
  205. package/dist/{chunk-J25YOUIZ.js → chunk-SXF66YNZ.js} +6 -4
  206. package/dist/{chunk-PRMUQUWN.js → chunk-T5QYYB5L.js} +16 -14
  207. package/dist/{chunk-OSYHGGL3.js → chunk-TAIYQDIV.js} +20 -18
  208. package/dist/{chunk-NROSSWMS.js → chunk-TIOYZDRB.js} +8 -6
  209. package/dist/{chunk-S6LW2RRC.js → chunk-TKCNJJ2S.js} +10 -8
  210. package/dist/{chunk-T6MAWL5P.js → chunk-TVFADTAT.js} +6 -4
  211. package/dist/{chunk-FMR2D3AZ.js → chunk-U4HZ5CXL.js} +8 -6
  212. package/dist/{chunk-XMUWPA56.js → chunk-U7F6E5M3.js} +27 -24
  213. package/dist/{chunk-FL344WQD.js → chunk-U7YZ3IRI.js} +6 -4
  214. package/dist/{chunk-OCQWSFJD.js → chunk-UCKG6UE7.js} +14 -12
  215. package/dist/{chunk-LM45GMMB.js → chunk-UCQB6NKS.js} +7 -7
  216. package/dist/{chunk-6SNTHK43.js → chunk-UI7ID4HG.js} +24 -19
  217. package/dist/{chunk-S5XFO4GY.js → chunk-UJ535VWR.js} +6 -4
  218. package/dist/chunk-UKMA5JFE.js +52 -0
  219. package/dist/{chunk-E3PDCQRH.js → chunk-UR6JGVX2.js} +299 -247
  220. package/dist/{chunk-IMZFOMVX.js → chunk-USH4VU5D.js} +5 -3
  221. package/dist/{chunk-V7PEHQZU.js → chunk-UTYL4XVA.js} +21 -19
  222. package/dist/{chunk-NC755EKE.js → chunk-UTZMF5CV.js} +1 -1
  223. package/dist/{chunk-FQVSLBTV.js → chunk-UVKJVTKX.js} +3 -3
  224. package/dist/{chunk-Q367UGYN.js → chunk-V7T6URII.js} +10 -8
  225. package/dist/{chunk-6RYB3EET.js → chunk-VAZYNF6I.js} +14 -12
  226. package/dist/{chunk-J2H7YG3K.js → chunk-VBJHIRKV.js} +5 -3
  227. package/dist/{chunk-QVVGJVVX.js → chunk-VOBG7BLB.js} +18 -16
  228. package/dist/{chunk-7XWJ6ED2.js → chunk-W2W7YCFL.js} +16 -13
  229. package/dist/{chunk-XFDDJQT7.js → chunk-WA644MUQ.js} +15 -13
  230. package/dist/{chunk-6NCPLIIP.js → chunk-WDJGJ3HV.js} +441 -365
  231. package/dist/chunk-WGOQZ4PQ.js +488 -0
  232. package/dist/{chunk-3EWKO457.js → chunk-WS7KBKP4.js} +8 -6
  233. package/dist/chunk-X7QLAUNS.js +47 -0
  234. package/dist/{chunk-4FLNCK6Q.js → chunk-XC5ZDFW7.js} +13 -11
  235. package/dist/{chunk-VRO7KSGL.js → chunk-XF5UMMQL.js} +23 -21
  236. package/dist/{chunk-WOMQQWTO.js → chunk-XM3JE4QY.js} +7 -5
  237. package/dist/{chunk-73GFVW2L.js → chunk-XP5DF5MC.js} +51 -14
  238. package/dist/{chunk-W5VYJWOG.js → chunk-XUCHGEF5.js} +25 -23
  239. package/dist/{chunk-AFBCNZRZ.js → chunk-XVQQ3BQS.js} +26 -24
  240. package/dist/{chunk-VJFXQISZ.js → chunk-XXJSGCDO.js} +13 -9
  241. package/dist/{chunk-WXVTYLVH.js → chunk-XY6FVBBV.js} +4 -4
  242. package/dist/{chunk-QAVRDONY.js → chunk-XZQBFF65.js} +121 -119
  243. package/dist/{chunk-LZVHP7CT.js → chunk-Y3J365UC.js} +7 -5
  244. package/dist/{chunk-GUGQSIQM.js → chunk-Y6KPWRZJ.js} +11 -9
  245. package/dist/{chunk-ZNHQGG7J.js → chunk-YAUMNRCB.js} +4 -4
  246. package/dist/{chunk-6R5VHR3N.js → chunk-YEGGQG5E.js} +9 -7
  247. package/dist/{chunk-LHH5KG5A.js → chunk-YGNQUFVZ.js} +3 -3
  248. package/dist/{chunk-CMB7FXHJ.js → chunk-YGS2YVF2.js} +16 -14
  249. package/dist/{chunk-IKAW2KJU.js → chunk-YRKAJ42V.js} +525 -287
  250. package/dist/{chunk-7YQBDE5W.js → chunk-Z3KEX7ON.js} +6 -4
  251. package/dist/{chunk-ZNTTW4IT.js → chunk-Z4N7BKLN.js} +7 -5
  252. package/dist/{chunk-75OMRKY2.js → chunk-ZD64ZR64.js} +7 -5
  253. package/dist/{chunk-3ASYYMOX.js → chunk-ZJQ64T6M.js} +10 -8
  254. package/dist/files.json +563 -547
  255. package/dist/packages/sdk/npm/index.js +5530 -4902
  256. package/dist/packages/ui/dist/assets/{elk-api-DxfAMOJq.js → elk-api-ts8TigYQ.js} +2 -2
  257. package/dist/packages/ui/dist/assets/index-CIfmX7DJ.css +1 -0
  258. package/dist/packages/ui/dist/assets/index-DNtpSfZS.js +63 -0
  259. package/dist/packages/ui/dist/index.html +2 -2
  260. package/package.json +3 -3
  261. package/dist/chunk-5MYE42AP.js +0 -43
  262. package/dist/chunk-5O7U67UA.js +0 -57
  263. package/dist/chunk-6JVPBGQG.js +0 -50
  264. package/dist/chunk-AHFQHPFF.js +0 -49
  265. package/dist/chunk-CXTG6AWM.js +0 -40
  266. package/dist/chunk-GPNMSX5H.js +0 -36
  267. package/dist/chunk-HMWJWYE2.js +0 -31
  268. package/dist/chunk-ICBGVVRI.js +0 -317
  269. package/dist/chunk-J2CDBSFP.js +0 -69
  270. package/dist/chunk-NKJDO4UC.js +0 -39
  271. package/dist/chunk-NOYOFYAJ.js +0 -59
  272. package/dist/chunk-OXXZZ7HQ.js +0 -50
  273. package/dist/chunk-P4YUT7W7.js +0 -45
  274. package/dist/chunk-RQSLHZ7T.js +0 -36
  275. package/dist/chunk-RYQ4JCFT.js +0 -65
  276. package/dist/chunk-UMCDODBX.js +0 -53
  277. package/dist/chunk-VJZI6KFP.js +0 -47
  278. package/dist/chunk-W4TNCEI4.js +0 -44
  279. package/dist/chunk-XLZAAAPX.js +0 -43
  280. package/dist/packages/ui/dist/assets/index-Buit9TfP.js +0 -62
  281. package/dist/packages/ui/dist/assets/index-Jyc9dFeZ.css +0 -1
@@ -5,30 +5,35 @@ 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-G6EFXTUO.js";
8
+ } from "./chunk-2VN4TLGI.js";
9
9
  import {
10
10
  globToRegExp
11
- } from "./chunk-PQQKZPBU.js";
11
+ } from "./chunk-4U3JLIRC.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
+ JOINED_BY_PATH,
19
+ JOINED_BY_PATH_OVERLAP,
18
20
  JOINED_BY_PERSON,
19
21
  JOINED_TO_SHARED_MAP,
22
+ JOIN_GUESS_FLAGS,
20
23
  JOIN_HOW_FLAGS,
21
24
  LINK_EVIDENCE_NOT_GAPS,
22
25
  MOCK_FILE,
23
- NEVER_CHECKED_STEPS,
24
26
  SHARED_MAP_EVIDENCE,
25
27
  citedFiles,
26
28
  claimOnLines,
27
29
  clusterServiceAddress,
30
+ configSecretField,
31
+ credentialLike,
28
32
  decodeText,
33
+ dependencyLinkId,
29
34
  factIdPart,
30
35
  forwardSlashes,
31
- gatewayBundleTest,
36
+ hasSecretShape,
32
37
  isBinaryText,
33
38
  isLfsPointer,
34
39
  isPatternPath,
@@ -36,11 +41,11 @@ import {
36
41
  lineNamesClaim,
37
42
  linksFor,
38
43
  listRepoFilesSync,
39
- normalizePath,
40
- notDeviceName,
44
+ looksLikeSecret,
41
45
  noteProblem,
42
46
  partsBuildWord,
43
47
  partsNamePath,
48
+ placedComponentOf,
44
49
  plainPathPrefix,
45
50
  quoteHoldsSecret,
46
51
  quoteMatches,
@@ -48,9 +53,17 @@ import {
48
53
  redactSecrets,
49
54
  staleCite,
50
55
  toCanonicalYaml,
51
- tokenUnits,
56
+ tokenUnits
57
+ } from "./chunk-GLISHJ4G.js";
58
+ import {
59
+ DEFAULT_CONVENTIONS,
60
+ DEFAULT_GATEWAY_BUNDLE_FOLDERS,
61
+ NEVER_CHECKED_STEPS,
62
+ gatewayBundleTest,
63
+ normalizePath,
64
+ notDeviceName,
52
65
  underFolders
53
- } from "./chunk-FPBUTZI5.js";
66
+ } from "./chunk-LZFKJ2BR.js";
54
67
 
55
68
  // packages/verify/dist/source.js
56
69
  import { lstatSync, readFileSync, realpathSync, statSync } from "node:fs";
@@ -166,6 +179,1046 @@ function tooBigToRead(source, path) {
166
179
  return n !== void 0 && n > MAX_SOURCE_BYTES;
167
180
  }
168
181
 
182
+ // packages/verify/dist/build-coords.js
183
+ var POM = /(^|\/)([^/]*[-_.])?pom\.xml$|\.pom$/i;
184
+ var GENERATED_POM = /(^|\/)(dependency-reduced-pom\.xml|\.flattened-pom\.xml)$/i;
185
+ var GRADLE_BUILD = /(^|\/)build\.gradle(\.kts)?$/i;
186
+ var GRADLE_SETTINGS = /(^|\/)settings\.gradle(\.kts)?$/i;
187
+ var VERSION_CATALOG = /(^|\/)gradle\/([\w-]+)\.versions\.toml$/i;
188
+ var slash = (p) => p.replace(/\\/g, "/");
189
+ var isPomFile = (p) => POM.test(slash(p)) && !GENERATED_POM.test(slash(p));
190
+ var isGradleBuildFile = (p) => GRADLE_BUILD.test(slash(p));
191
+ var isGradleSettingsFile = (p) => GRADLE_SETTINGS.test(slash(p));
192
+ var isVersionCatalogFile = (p) => VERSION_CATALOG.test(slash(p));
193
+ var isGradleFile = (p) => isGradleBuildFile(p) || isGradleSettingsFile(p) || isVersionCatalogFile(p);
194
+ var isBuildFile = (p) => isPomFile(p) || isGradleFile(p);
195
+ var isPomFileIn = (p, named) => isPomFile(p) || !!named?.has(slash(p)) && !GENERATED_POM.test(slash(p));
196
+ var isBuildFileIn = (p, named) => isBuildFile(p) || isPomFileIn(p, named);
197
+ var COORDINATE = /^[A-Za-z0-9_][A-Za-z0-9._-]*$/;
198
+ function lineIndex(text) {
199
+ const starts = [0];
200
+ for (let i = 0; i < text.length; i++)
201
+ if (text.charCodeAt(i) === 10)
202
+ starts.push(i + 1);
203
+ return (offset) => {
204
+ let lo = 0;
205
+ let hi = starts.length - 1;
206
+ while (lo < hi) {
207
+ const mid = lo + hi + 1 >> 1;
208
+ if (starts[mid] <= offset)
209
+ lo = mid;
210
+ else
211
+ hi = mid - 1;
212
+ }
213
+ return lo + 1;
214
+ };
215
+ }
216
+ function xmlTokens(text) {
217
+ const lineAt = lineIndex(text);
218
+ const out = [];
219
+ const pushText = (from, to, value = text.slice(from, to)) => {
220
+ const lead = value.length - value.trimStart().length;
221
+ if (value.trim())
222
+ out.push({ type: "text", value: value.trim(), line: lineAt(from + lead) });
223
+ };
224
+ let i = 0;
225
+ let textFrom = 0;
226
+ while (i < text.length) {
227
+ const lt = text.indexOf("<", i);
228
+ if (lt < 0)
229
+ break;
230
+ if (text.startsWith("<!--", lt)) {
231
+ pushText(textFrom, lt);
232
+ const end = text.indexOf("-->", lt + 4);
233
+ i = textFrom = end < 0 ? text.length : end + 3;
234
+ continue;
235
+ }
236
+ if (text.startsWith("<![CDATA[", lt)) {
237
+ pushText(textFrom, lt);
238
+ const end = text.indexOf("]]>", lt + 9);
239
+ const stop = end < 0 ? text.length : end;
240
+ pushText(lt + 9, stop);
241
+ i = textFrom = end < 0 ? text.length : end + 3;
242
+ continue;
243
+ }
244
+ if (text.startsWith("<?", lt) || text.startsWith("<!", lt)) {
245
+ pushText(textFrom, lt);
246
+ const end = text.indexOf(text.startsWith("<?", lt) ? "?>" : ">", lt + 2);
247
+ i = textFrom = end < 0 ? text.length : end + (text.startsWith("<?", lt) ? 2 : 1);
248
+ continue;
249
+ }
250
+ const m = /^<(\/?)([A-Za-z_][\w.:-]*)/.exec(text.slice(lt, lt + 200));
251
+ if (!m) {
252
+ i = lt + 1;
253
+ continue;
254
+ }
255
+ let j = lt + m[0].length;
256
+ let quote = "";
257
+ for (; j < text.length; j++) {
258
+ const c = text[j];
259
+ if (quote) {
260
+ if (c === quote)
261
+ quote = "";
262
+ } else if (c === '"' || c === "'")
263
+ quote = c;
264
+ else if (c === ">")
265
+ break;
266
+ }
267
+ pushText(textFrom, lt);
268
+ const close = m[1] === "/";
269
+ const self = !close && text[j - 1] === "/";
270
+ out.push({ type: close ? "close" : self ? "self" : "open", name: m[2], line: lineAt(lt) });
271
+ i = textFrom = j + 1;
272
+ }
273
+ pushText(textFrom, text.length);
274
+ return out;
275
+ }
276
+ var leaf = (frame, name) => frame.leaves.get(name);
277
+ function pomCoordinates(lines) {
278
+ const held = POMS.get(lines);
279
+ if (held)
280
+ return held;
281
+ const out = readPom(lines);
282
+ POMS.set(lines, out);
283
+ return out;
284
+ }
285
+ var POMS = /* @__PURE__ */ new WeakMap();
286
+ function readPom(lines) {
287
+ const out = { dependencies: [], modules: [], properties: /* @__PURE__ */ new Map() };
288
+ const text = lines.map((l, i) => {
289
+ const t = l.endsWith("\r") ? l.slice(0, -1) : l;
290
+ return i === 0 && t.charCodeAt(0) === 65279 ? t.slice(1) : t;
291
+ }).join("\n");
292
+ const stack = [];
293
+ const names = () => stack.map((f) => f.name);
294
+ for (const t of xmlTokens(text)) {
295
+ const top = stack[stack.length - 1];
296
+ if (t.type === "text") {
297
+ if (top && !top.text) {
298
+ top.text = t.value;
299
+ top.textLine = t.line;
300
+ }
301
+ continue;
302
+ }
303
+ if (t.type !== "close") {
304
+ if (top)
305
+ top.children = true;
306
+ if (t.type === "self") {
307
+ if (t.name === "relativePath" && top?.name === "parent")
308
+ top.leaves.set("relativePath", { value: "", line: t.line });
309
+ continue;
310
+ }
311
+ stack.push({ name: t.name, leaves: /* @__PURE__ */ new Map(), children: false, text: "", textLine: t.line });
312
+ continue;
313
+ }
314
+ const at = names().lastIndexOf(t.name);
315
+ if (at < 0)
316
+ continue;
317
+ while (stack.length > at + 1)
318
+ stack.pop();
319
+ const done = stack.pop();
320
+ const parent = stack[stack.length - 1];
321
+ const value = !done.children && done.text ? { value: done.text, line: done.textLine } : void 0;
322
+ if (value && parent)
323
+ parent.leaves.set(done.name, value);
324
+ const path = [...names(), done.name];
325
+ if (done.name === "dependency") {
326
+ const g = leaf(done, "groupId");
327
+ const a = leaf(done, "artifactId");
328
+ const v = leaf(done, "version");
329
+ const s = leaf(done, "scope");
330
+ out.dependencies.push({
331
+ ...g ? { group: g } : {},
332
+ ...a ? { artifact: a } : {},
333
+ ...v ? { version: v } : {},
334
+ ...s ? { scope: s } : {},
335
+ managed: path.includes("dependencyManagement"),
336
+ plugin: path.includes("plugin") || path.includes("extension")
337
+ });
338
+ } else if (done.name === "module" && value && path[0] === "project") {
339
+ const p = path.join("/");
340
+ if (p === "project/modules/module" || p === "project/profiles/profile/modules/module")
341
+ out.modules.push(value);
342
+ } else if (done.name === "properties" && path.length === 2 && path[0] === "project") {
343
+ for (const [k, v] of done.leaves)
344
+ out.properties.set(k, v);
345
+ } else if (done.name === "parent" && path.length === 2 && path[0] === "project") {
346
+ if (leaf(done, "groupId"))
347
+ out.parentGroup = leaf(done, "groupId");
348
+ if (leaf(done, "artifactId"))
349
+ out.parentArtifact = leaf(done, "artifactId");
350
+ if (leaf(done, "version"))
351
+ out.parentVersion = leaf(done, "version");
352
+ if (leaf(done, "relativePath"))
353
+ out.parentRelativePath = leaf(done, "relativePath");
354
+ } else if (done.name === "project" && path.length === 1) {
355
+ if (leaf(done, "groupId"))
356
+ out.group = leaf(done, "groupId");
357
+ if (leaf(done, "artifactId"))
358
+ out.artifact = leaf(done, "artifactId");
359
+ if (leaf(done, "version"))
360
+ out.version = leaf(done, "version");
361
+ }
362
+ }
363
+ return out;
364
+ }
365
+ var PROPERTY = /^\$\{([^}]+)\}$/;
366
+ function resolvePomValue(at, pom, o = {}, depth = 0) {
367
+ const m = PROPERTY.exec(at.value.trim());
368
+ if (!m)
369
+ return { value: at.value, line: at.line };
370
+ const key = m[1].trim();
371
+ const own = {
372
+ "project.groupId": pom.group ?? pom.parentGroup,
373
+ "pom.groupId": pom.group ?? pom.parentGroup,
374
+ groupId: pom.group ?? pom.parentGroup,
375
+ "project.artifactId": pom.artifact,
376
+ "pom.artifactId": pom.artifact,
377
+ artifactId: pom.artifact,
378
+ "project.version": pom.version ?? pom.parentVersion,
379
+ "pom.version": pom.version ?? pom.parentVersion,
380
+ "project.parent.groupId": pom.parentGroup,
381
+ "parent.groupId": pom.parentGroup,
382
+ "project.parent.artifactId": pom.parentArtifact,
383
+ "parent.artifactId": pom.parentArtifact,
384
+ "project.parent.version": pom.parentVersion,
385
+ "parent.version": pom.parentVersion
386
+ };
387
+ const builtin = Object.hasOwn(own, key);
388
+ let to;
389
+ if (builtin) {
390
+ const b = own[key];
391
+ if (b)
392
+ to = { at: b, file: o.file ?? "" };
393
+ } else {
394
+ const mine = pom.properties.get(key);
395
+ if (mine)
396
+ to = { at: mine, file: o.file ?? "" };
397
+ else
398
+ for (const p of o.parents ?? []) {
399
+ const theirs = p.pom.properties.get(key);
400
+ if (theirs) {
401
+ to = { at: theirs, file: p.file };
402
+ break;
403
+ }
404
+ }
405
+ }
406
+ if (!to || to.at === at || depth > 4)
407
+ return { missing: key };
408
+ const next = resolvePomValue(to.at, pom, o, depth + 1);
409
+ if ("missing" in next)
410
+ return next;
411
+ const via = [...builtin ? [] : [{ file: to.file, line: to.at.line }], ...next.via ?? []];
412
+ return { value: next.value, line: at.line, ...via.length ? { via } : {} };
413
+ }
414
+ function pomTarget(dir, rel) {
415
+ const to = joinDir(dir, rel.trim());
416
+ if (/\.(xml|pom)$/i.test(rel.trim()))
417
+ return to;
418
+ return to ? `${to}/pom.xml` : "pom.xml";
419
+ }
420
+ function pomFilesNamed(files, linesOf2) {
421
+ const held = NAMED.get(files);
422
+ if (held)
423
+ return held;
424
+ const all2 = new Set(files.map(slash));
425
+ const out = /* @__PURE__ */ new Set();
426
+ let next = files.map(slash).filter(isPomFile);
427
+ for (let round = 0; round < 5 && next.length; round++) {
428
+ const found = [];
429
+ for (const f of next) {
430
+ const lines = linesOf2(f);
431
+ const rel = lines ? pomCoordinates(lines).parentRelativePath?.value.trim() : void 0;
432
+ if (!rel)
433
+ continue;
434
+ const to = pomTarget(dirOf(f), rel);
435
+ if (all2.has(to) && !isPomFile(to) && !out.has(to) && !GENERATED_POM.test(to)) {
436
+ out.add(to);
437
+ found.push(to);
438
+ }
439
+ }
440
+ next = found;
441
+ }
442
+ NAMED.set(files, out);
443
+ return out;
444
+ }
445
+ var NAMED = /* @__PURE__ */ new WeakMap();
446
+ function moduleParentsOf(files, linesOf2) {
447
+ const held = LISTED.get(files);
448
+ if (held)
449
+ return held;
450
+ const named = pomFilesNamed(files, linesOf2);
451
+ const out = /* @__PURE__ */ new Map();
452
+ for (const f of files.map(slash).sort()) {
453
+ if (!isPomFileIn(f, named))
454
+ continue;
455
+ const lines = linesOf2(f);
456
+ if (!lines)
457
+ continue;
458
+ for (const m of pomCoordinates(lines).modules) {
459
+ const dir = dirOf(pomTarget(dirOf(f), m.value));
460
+ if (!out.has(dir))
461
+ out.set(dir, f);
462
+ }
463
+ }
464
+ LISTED.set(files, out);
465
+ return out;
466
+ }
467
+ var LISTED = /* @__PURE__ */ new WeakMap();
468
+ function pomParents(file, linesOf2, files) {
469
+ const out = [];
470
+ const seen = /* @__PURE__ */ new Set([slash(file)]);
471
+ let at = slash(file);
472
+ let lines = linesOf2(at);
473
+ for (let n = 0; n < 6 && lines; n++) {
474
+ const pom = pomCoordinates(lines);
475
+ if (!pom.parentArtifact)
476
+ break;
477
+ const rel = pom.parentRelativePath?.value.trim();
478
+ if (rel === "")
479
+ break;
480
+ const dir = dirOf(at);
481
+ const candidates = rel ? [pomTarget(dir, rel)] : [
482
+ ...files ? [moduleParentsOf(files, linesOf2).get(dir)] : [],
483
+ ...dir ? [pomTarget(dir, "..")] : []
484
+ ];
485
+ const want = pom.parentArtifact.value.trim();
486
+ let found;
487
+ for (const c of candidates) {
488
+ if (!c || seen.has(c))
489
+ continue;
490
+ const ls = linesOf2(c);
491
+ if (!ls)
492
+ continue;
493
+ const theirs = pomCoordinates(ls);
494
+ const name = theirs.artifact?.value.trim();
495
+ if (name !== void 0 && !PROPERTY.test(name) && !PROPERTY.test(want) && name !== want)
496
+ continue;
497
+ found = { file: c, pom: theirs };
498
+ break;
499
+ }
500
+ if (!found)
501
+ break;
502
+ out.push(found);
503
+ seen.add(found.file);
504
+ at = found.file;
505
+ lines = linesOf2(at);
506
+ }
507
+ return out;
508
+ }
509
+ var CONFIGURATION = `(?:(["'])([A-Za-z]\\w*)\\1\\s*(?=\\()|([A-Za-z]\\w*))`;
510
+ var GRADLE_DEP = new RegExp(`^\\s*${CONFIGURATION}\\s*\\(?\\s*(?:(platform|enforcedPlatform)\\s*\\(\\s*)?(['"])([^'"\\s]+)\\5`);
511
+ var GRADLE_MAP_DEP = new RegExp(`^\\s*${CONFIGURATION}\\s*\\(?\\s*group\\s*[:=]\\s*(['"])([^'"]+)\\4\\s*,\\s*name\\s*[:=]\\s*(['"])([^'"]+)\\6(?:\\s*,\\s*version\\s*[:=]\\s*(['"])([^'"]+)\\8)?`);
512
+ var NOT_A_CONFIGURATION = /* @__PURE__ */ new Set([
513
+ "id",
514
+ "apply",
515
+ "plugin",
516
+ "include",
517
+ "includeBuild",
518
+ "classpath",
519
+ "group",
520
+ "version",
521
+ "url",
522
+ "uri",
523
+ "dependency",
524
+ "dependencySet",
525
+ "entry",
526
+ "mavenBom",
527
+ "imports",
528
+ "force",
529
+ "exclude",
530
+ "module",
531
+ "substitute",
532
+ "because",
533
+ "strictly",
534
+ "require",
535
+ "prefer",
536
+ "reject",
537
+ "alias",
538
+ "from",
539
+ "maven",
540
+ "mainClass",
541
+ "println",
542
+ "description"
543
+ ]);
544
+ var TOOL_CONFIGURATIONS = /* @__PURE__ */ new Set([
545
+ "checkstyle",
546
+ "pmd",
547
+ "spotbugs",
548
+ "spotbugsPlugins",
549
+ "spotbugsSlf4j",
550
+ "jacocoAgent",
551
+ "jacocoAnt",
552
+ "detekt",
553
+ "detektPlugins",
554
+ "ktlint",
555
+ "ktlintRuleset",
556
+ "codenarc",
557
+ "errorprone",
558
+ "pitest"
559
+ ]);
560
+ function gradleToolConfigurationOn(line) {
561
+ const c = /^\s*(["']?)([A-Za-z]\w*)\1\s*[\s(]/.exec(line)?.[2];
562
+ return c && TOOL_CONFIGURATIONS.has(c) ? c : void 0;
563
+ }
564
+ var TEST_CONFIGURATION = /^(test|testFixtures|\w+Test)(Implementation|Api|CompileOnly|RuntimeOnly|Compile|Runtime|AnnotationProcessor|CompileClasspath|RuntimeClasspath)$/;
565
+ function scopeOfConfiguration(c, platform) {
566
+ if (platform)
567
+ return "import";
568
+ if (TEST_CONFIGURATION.test(c))
569
+ return "test";
570
+ if (/^(compileOnly|annotationProcessor|kapt|ksp|compileOnlyApi|providedCompile|providedRuntime)$/.test(c))
571
+ return "provided";
572
+ if (/^(runtimeOnly|runtime|developmentOnly|testAndDevelopmentOnly)$/.test(c))
573
+ return "runtime";
574
+ return "compile";
575
+ }
576
+ function gradleDependencyOn(line) {
577
+ if (gradleToolConfigurationOn(line))
578
+ return void 0;
579
+ const map = GRADLE_MAP_DEP.exec(line);
580
+ const mapConf = map ? map[2] ?? map[3] : "";
581
+ if (map && !NOT_A_CONFIGURATION.has(mapConf)) {
582
+ if (!COORDINATE.test(map[5]) || !COORDINATE.test(map[7]))
583
+ return void 0;
584
+ return {
585
+ configuration: mapConf,
586
+ group: map[5],
587
+ name: map[7],
588
+ ...map[9] ? { version: map[9] } : {},
589
+ scope: scopeOfConfiguration(mapConf, false)
590
+ };
591
+ }
592
+ const m = GRADLE_DEP.exec(line);
593
+ const conf = m ? m[2] ?? m[3] : "";
594
+ if (!m || NOT_A_CONFIGURATION.has(conf))
595
+ return void 0;
596
+ const parts = m[6].split(":");
597
+ if (parts.length < 2 || !COORDINATE.test(parts[0]) || !COORDINATE.test(parts[1]))
598
+ return void 0;
599
+ return {
600
+ configuration: conf,
601
+ group: parts[0],
602
+ name: parts[1],
603
+ ...parts[2] ? { version: parts[2] } : {},
604
+ scope: scopeOfConfiguration(conf, !!m[4])
605
+ };
606
+ }
607
+ function gradleBlocks(lines) {
608
+ const held = BLOCKS.get(lines);
609
+ if (held)
610
+ return held;
611
+ const out = readBlocks(lines);
612
+ BLOCKS.set(lines, out);
613
+ return out;
614
+ }
615
+ var BLOCKS = /* @__PURE__ */ new WeakMap();
616
+ function readBlocks(lines) {
617
+ const out = [];
618
+ const stack = [];
619
+ let triple = "";
620
+ let block = false;
621
+ let previous = "";
622
+ for (const raw of lines) {
623
+ out.push([...stack]);
624
+ let code2 = "";
625
+ for (let i = 0; i < raw.length; i++) {
626
+ const c = raw[i];
627
+ if (block) {
628
+ if (raw.startsWith("*/", i)) {
629
+ block = false;
630
+ i++;
631
+ }
632
+ continue;
633
+ }
634
+ if (triple) {
635
+ if (raw.startsWith(triple, i)) {
636
+ code2 += triple;
637
+ i += 2;
638
+ triple = "";
639
+ }
640
+ continue;
641
+ }
642
+ if (raw.startsWith("//", i))
643
+ break;
644
+ if (raw.startsWith("/*", i)) {
645
+ block = true;
646
+ i++;
647
+ continue;
648
+ }
649
+ if (raw.startsWith("'''", i) || raw.startsWith('"""', i)) {
650
+ triple = raw.slice(i, i + 3);
651
+ code2 += triple;
652
+ i += 2;
653
+ continue;
654
+ }
655
+ if (c === "'" || c === '"') {
656
+ let j = i + 1;
657
+ for (; j < raw.length && raw[j] !== c; j++)
658
+ if (raw[j] === "\\")
659
+ j++;
660
+ code2 += raw.slice(i, j + 1).replace(/[{}]/g, " ");
661
+ i = j;
662
+ continue;
663
+ }
664
+ if (c === "{") {
665
+ const before = code2.trim() || previous;
666
+ const m = /([A-Za-z_][\w.]*)\s*(?:\(\s*([^()]*?)\s*\))?\s*(?:\w+\s*->\s*)?$/.exec(before);
667
+ const name = m?.[1] ?? "";
668
+ stack.push(name === "project" && m?.[2] ? `project(${m[2].replace(/['"]/g, "")})` : name);
669
+ code2 = "";
670
+ continue;
671
+ }
672
+ if (c === "}") {
673
+ stack.pop();
674
+ code2 = "";
675
+ continue;
676
+ }
677
+ code2 += c;
678
+ }
679
+ if (code2.trim())
680
+ previous = code2.trim();
681
+ }
682
+ return out;
683
+ }
684
+ var PROJECT_BLOCK = (b) => b === "subprojects" || b === "allprojects" || /^project\(:?[^)]*\)$/.test(b);
685
+ var projectOf = (b) => /^project\(:?([^)]*)\)$/.exec(b)?.[1];
686
+ function gradleDependencyAt(lines, line, blocks = gradleBlocks(lines)) {
687
+ const d = gradleDependencyOn(lines[line - 1] ?? "");
688
+ if (!d)
689
+ return void 0;
690
+ const at = projectDependenciesAt(blocks, line);
691
+ return "none" in at ? at : { dependency: d, ...at };
692
+ }
693
+ function projectDependenciesAt(blocks, line) {
694
+ const stack = blocks[line - 1] ?? [];
695
+ const outer = stack.slice(0, -1);
696
+ if (stack[stack.length - 1] !== "dependencies" || !outer.every(PROJECT_BLOCK)) {
697
+ const inside = stack.filter((b) => !PROJECT_BLOCK(b)).join(" { ");
698
+ return { none: inside ? `${inside} { }` : "no dependencies { } block" };
699
+ }
700
+ const proj = outer.map(projectOf).find((x) => x !== void 0);
701
+ return {
702
+ ...proj !== void 0 ? { project: proj } : {},
703
+ ...outer.some((b) => b === "subprojects" || b === "allprojects") ? { all: true } : {}
704
+ };
705
+ }
706
+ function catalogVersions(lines) {
707
+ const out = /* @__PURE__ */ new Map();
708
+ let section = "";
709
+ lines.forEach((raw, i) => {
710
+ const l = raw.replace(/\r$/, "");
711
+ const s = /^\s*\[\s*([^\]]+?)\s*\]\s*(#.*)?$/.exec(l);
712
+ if (s)
713
+ return void (section = s[1]);
714
+ if (section !== "versions")
715
+ return;
716
+ const m = /^\s*(["']?)([A-Za-z][\w.-]*)\1\s*=\s*(["'])([^"']+)\3\s*(#.*)?$/.exec(l);
717
+ if (m)
718
+ out.set(m[2], { value: m[4], line: i + 1 });
719
+ });
720
+ return out;
721
+ }
722
+ var catalogNameOf = (file) => VERSION_CATALOG.exec(slash(file))?.[2];
723
+ var accessorOf = (alias) => alias.replace(/[-_.]+/g, ".");
724
+ function catalogLibraryAt(lines, line) {
725
+ let section = "";
726
+ for (let i = 0; i < line && i < lines.length; i++) {
727
+ const m2 = /^\s*\[\s*([^\]]+?)\s*\]\s*(#.*)?$/.exec((lines[i] ?? "").replace(/\r$/, ""));
728
+ if (m2)
729
+ section = m2[1];
730
+ }
731
+ if (section !== "libraries")
732
+ return void 0;
733
+ const text = (lines[line - 1] ?? "").replace(/\r$/, "");
734
+ const m = /^\s*(["']?)([A-Za-z][\w.-]*)\1\s*=\s*(.+)$/.exec(text);
735
+ if (!m)
736
+ return void 0;
737
+ const alias = m[2];
738
+ const body = m[3].replace(/\s+#.*$/, "").trim();
739
+ const str = (key) => new RegExp(`(?:^|[{,\\s])${key.replace(".", "\\.")}\\s*=\\s*(["'])([^"']+)\\1`).exec(body)?.[2];
740
+ let group;
741
+ let name;
742
+ let version;
743
+ const whole = /^(["'])([^"']+)\1$/.exec(body);
744
+ if (whole)
745
+ [group, name, version] = whole[2].split(":");
746
+ else if (body.startsWith("{")) {
747
+ const module = str("module");
748
+ if (module)
749
+ [group, name] = module.split(":");
750
+ else {
751
+ group = str("group");
752
+ name = str("name");
753
+ }
754
+ version = str("version");
755
+ }
756
+ const versionRef = body.startsWith("{") ? str("version.ref") : void 0;
757
+ if (!group || !name || !COORDINATE.test(group) || !COORDINATE.test(name))
758
+ return void 0;
759
+ return {
760
+ alias,
761
+ accessor: accessorOf(alias),
762
+ group,
763
+ name,
764
+ ...version ? { version } : {},
765
+ ...versionRef ? { versionRef } : {}
766
+ };
767
+ }
768
+ function gradleCatalogUseOn(line) {
769
+ const m = new RegExp(`^\\s*${CONFIGURATION}\\s*\\(?\\s*(?:(platform|enforcedPlatform)\\s*\\(\\s*)?([A-Za-z]\\w*)\\.([A-Za-z][\\w.]*?)\\s*\\)?\\s*\\)?\\s*(?:\\{.*)?(?:\\/\\/.*)?\\r?$`).exec(line);
770
+ const conf = m ? m[2] ?? m[3] : "";
771
+ if (!m || NOT_A_CONFIGURATION.has(conf) || TOOL_CONFIGURATIONS.has(conf))
772
+ return void 0;
773
+ if (/^(bundles|plugins|versions)\./.test(m[6]) || m[5] === "project")
774
+ return void 0;
775
+ return {
776
+ configuration: conf,
777
+ catalog: m[5],
778
+ accessor: m[6],
779
+ scope: scopeOfConfiguration(conf, !!m[4])
780
+ };
781
+ }
782
+ function gradleGroupOn(line) {
783
+ return /^\s*(?:(?:allprojects|subprojects)\s*\{\s*)?(?:project\.)?group\s*=?\s*(['"])([^'"]+)\1\s*\}?\s*$/.exec(line)?.[2];
784
+ }
785
+ function gradleNameOn(line) {
786
+ return /^\s*(?:rootProject\.name|archivesBaseName|(?:base\.)?archivesName(?:\.set)?)\s*[=(]?\s*(['"])([^'"]+)\1\s*\)?\s*$/.exec(line)?.[2];
787
+ }
788
+ function gradleProjectsOn(line) {
789
+ const rename = /^\s*project\s*\(\s*(['"]):?([^'"]+)\1\s*\)\.name\s*=\s*(['"])([^'"]+)\3\s*$/.exec(line);
790
+ if (rename)
791
+ return [{ path: rename[2], name: rename[4], renamed: true }];
792
+ const inc = /^\s*include\s*\(?\s*((?:(['"])[^'"]+\2\s*,?\s*)+)\)?\s*$/.exec(line);
793
+ if (!inc)
794
+ return [];
795
+ return [...inc[1].matchAll(/(['"]):?([^'"]+)\1/g)].map((m) => ({
796
+ path: m[2],
797
+ name: m[2].split(":").pop()
798
+ }));
799
+ }
800
+ function gradleProjects(lines) {
801
+ const held = PROJECTS.get(lines);
802
+ if (held)
803
+ return held;
804
+ const out = [];
805
+ let open = "";
806
+ const names = (text, line) => {
807
+ for (const m of text.matchAll(/(['"]):?([^'"]+)\1/g))
808
+ out.push({ path: m[2], name: m[2].split(":").pop(), line });
809
+ };
810
+ lines.forEach((raw, i) => {
811
+ const code2 = raw.replace(/\r$/, "").replace(/\s\/\/.*$|^\s*\/\/.*$/, "");
812
+ if (open) {
813
+ names(code2, i + 1);
814
+ if (open === "paren" ? code2.includes(")") : !/,\s*$/.test(code2))
815
+ open = "";
816
+ return;
817
+ }
818
+ const rename = gradleProjectsOn(code2);
819
+ if (rename.length && rename[0].renamed)
820
+ return void out.push({ ...rename[0], line: i + 1 });
821
+ const inc = /^\s*include(?!\w)\s*(\(?)\s*(.*)$/.exec(code2);
822
+ if (!inc)
823
+ return;
824
+ names(inc[2], i + 1);
825
+ if (inc[1] === "(" && !inc[2].includes(")"))
826
+ open = "paren";
827
+ else if (inc[1] !== "(" && /,\s*$/.test(inc[2]))
828
+ open = "comma";
829
+ });
830
+ PROJECTS.set(lines, out);
831
+ return out;
832
+ }
833
+ var PROJECTS = /* @__PURE__ */ new WeakMap();
834
+ function projectDirs(settings) {
835
+ const dirs = /* @__PURE__ */ new Map();
836
+ for (const l of settings ?? []) {
837
+ const m = /^\s*project\s*\(\s*(['"]):?([^'"]+)\1\s*\)\.projectDir\s*=\s*(?:file\s*\(|new\s+File\s*\(\s*(?:settingsDir|rootDir)\s*,)\s*(['"])([^'"]+)\3\s*\)\s*$/.exec(l);
838
+ if (m)
839
+ dirs.set(m[2], normDir(m[4]));
840
+ }
841
+ return dirs;
842
+ }
843
+ var normDir = (p) => slash(p).replace(/^\.\//, "").replace(/\/(pom\.xml|build\.gradle(\.kts)?)$/i, "").replace(/\/+$/, "");
844
+ var dirOf = (file) => {
845
+ const f = slash(file);
846
+ return f.includes("/") ? f.slice(0, f.lastIndexOf("/")) : "";
847
+ };
848
+ var joinDir = (base2, rel) => {
849
+ const parts = base2 ? base2.split("/") : [];
850
+ for (const s of normDir(rel).split("/")) {
851
+ if (!s || s === ".")
852
+ continue;
853
+ if (s === "..")
854
+ parts.pop();
855
+ else
856
+ parts.push(s);
857
+ }
858
+ return parts.join("/");
859
+ };
860
+ var settingsOf = (linesOf2) => {
861
+ for (const f of ["settings.gradle", "settings.gradle.kts"]) {
862
+ const l = linesOf2(f);
863
+ if (l)
864
+ return { file: f, lines: l };
865
+ }
866
+ return void 0;
867
+ };
868
+ function buildLineOf(f) {
869
+ if (!isVersionCatalogFile(f.cite.file))
870
+ return f.cite;
871
+ return (f.cite.with ?? []).find((p) => isGradleBuildFile(p.file));
872
+ }
873
+ var ENVS = /* @__PURE__ */ new WeakMap();
874
+ function gradleEnvOf(linesOf2) {
875
+ const held = ENVS.get(linesOf2);
876
+ if (held)
877
+ return held;
878
+ const settings = settingsOf(linesOf2);
879
+ const env = {
880
+ ...settings ? { settings } : {},
881
+ dirs: projectDirs(settings?.lines),
882
+ projects: settings ? gradleProjects(settings.lines) : []
883
+ };
884
+ ENVS.set(linesOf2, env);
885
+ return env;
886
+ }
887
+ var projectDirOf = (env, project) => env.dirs.get(project) ?? project.replace(/:/g, "/");
888
+ function gradleProjectOf(f, at, linesOf2) {
889
+ const lines = linesOf2(at.file);
890
+ if (!lines)
891
+ return void 0;
892
+ if (isGradleSettingsFile(at.file)) {
893
+ const ps = gradleProjects(lines).filter((p) => p.line === at.line);
894
+ return ps.find((p) => p.name === f.name)?.path ?? (ps.length === 1 ? ps[0].path : void 0);
895
+ }
896
+ if (f.kind === "dependency" && isGradleBuildFile(at.file)) {
897
+ const d = projectDependenciesAt(gradleBlocks(lines), at.line);
898
+ return "project" in d ? d.project : void 0;
899
+ }
900
+ return void 0;
901
+ }
902
+ function isBuildModuleDir(dir, linesOf2) {
903
+ const want = normDir(dir);
904
+ const pom = linesOf2("pom.xml");
905
+ if (pom && pomCoordinates(pom).modules.some((m) => normDir(m.value) === want))
906
+ return true;
907
+ for (const f of ["settings.gradle", "settings.gradle.kts"]) {
908
+ const lines = linesOf2(f);
909
+ if (!lines)
910
+ continue;
911
+ for (const p of gradleProjects(lines))
912
+ if (normDir(p.path.replace(/^:/, "").replace(/:/g, "/")) === want)
913
+ return true;
914
+ }
915
+ return false;
916
+ }
917
+ function buildModuleOf(f, linesOf2, modules = [], repoComponent) {
918
+ const listed2 = modules.map((m) => ({ path: normDir(m.path), component: m.component })).filter((m) => m.path).sort((a, b) => b.path.length - a.path.length);
919
+ const repo = () => repoComponent ? { path: "", component: repoComponent, names: [repoComponent], from: "repo" } : void 0;
920
+ const of = (dir) => {
921
+ const m = listed2.find((x) => dir === x.path || dir.startsWith(`${x.path}/`));
922
+ return m ? { path: m.path, component: m.component, names: [m.component], from: "manifest" } : repo();
923
+ };
924
+ const at = buildLineOf(f);
925
+ if (!at)
926
+ return repo();
927
+ if (!listed2.length)
928
+ return repo();
929
+ const env = gradleEnvOf(linesOf2);
930
+ if (f.kind === "dependency" && isGradleBuildFile(at.file) && dirOf(at.file) === "") {
931
+ const lines = linesOf2(at.file);
932
+ const stack = lines ? gradleBlocks(lines)[at.line - 1] ?? [] : [];
933
+ const sub = stack.includes("subprojects");
934
+ const all2 = stack.includes("allprojects");
935
+ if ((sub || all2) && !stack.some((b) => projectOf(b) !== void 0)) {
936
+ const dirs = env.projects.length ? env.projects.filter((p) => !p.renamed).map((p) => projectDirOf(env, p.path)) : listed2.map((m) => m.path);
937
+ const mods = [...all2 ? [""] : [], ...dirs].flatMap((d) => {
938
+ const m = of(d);
939
+ return m ? [m] : [];
940
+ });
941
+ const names = [...new Set(mods.map((m) => m.component))].sort();
942
+ if (names.length === 1)
943
+ return mods.find((m) => m.component === names[0]);
944
+ if (names.length > 1)
945
+ return { path: "", names, from: "manifest", every: true };
946
+ return repo();
947
+ }
948
+ }
949
+ const project = gradleProjectOf(f, at, linesOf2);
950
+ return of(project !== void 0 ? projectDirOf(env, project) : dirOf(at.file));
951
+ }
952
+ function buildModuleProblem(f, mod) {
953
+ if (!mod)
954
+ return void 0;
955
+ if (mod.every) {
956
+ const names = mod.names.join(", ");
957
+ if (f.component === void 0)
958
+ return `${f.kind} ${f.id} cites ${f.cite.file}:${f.cite.line}, a dependency every subproject's build takes (components ${names}): write one dependency fact for each, each naming its component`;
959
+ const c2 = factIdPart(f.component);
960
+ if (mod.names.some((n) => factIdPart(n) === c2))
961
+ return void 0;
962
+ return `${f.kind} ${f.id} names component "${f.component}", and ${f.cite.file}:${f.cite.line} is a dependency of every subproject (components ${names}): name one of them`;
963
+ }
964
+ if (f.component === void 0)
965
+ return void 0;
966
+ const c = factIdPart(f.component);
967
+ if (mod.names.some((n) => factIdPart(n) === c))
968
+ return void 0;
969
+ if (mod.from === "repo")
970
+ return `${f.kind} ${f.id} names component "${f.component}", and ${f.cite.file} is a build file of ${mod.component} (repos.manifest.yaml lists no module of the repo there, so it ships as ${mod.component}): a module is a component only when the manifest lists it; name ${mod.component}, or leave component out`;
971
+ return `${f.kind} ${f.id} names component "${f.component}", and ${f.cite.file} is the build file of module ${mod.component} (${mod.path}/, repos.manifest.yaml's modules): a dependency belongs to the module whose build file declares it; name ${mod.component}, or leave component out`;
972
+ }
973
+ var citedLine = (f, file, line) => f.cite.file === file && f.cite.line === line || (f.cite.with ?? []).some((p) => p.file === file && p.line === line);
974
+ function buildCoordinatesProblem(f, linesOf2, files) {
975
+ const file = f.cite.file;
976
+ const label = `${f.kind} ${f.id}`;
977
+ const lines = linesOf2(file);
978
+ if (!lines)
979
+ return void 0;
980
+ const where = `${file}:${f.cite.line}`;
981
+ const named = files ? pomFilesNamed(files, linesOf2) : void 0;
982
+ if (isPomFileIn(file, named))
983
+ return pomProblem(f, label, where, {
984
+ file,
985
+ pom: pomCoordinates(lines),
986
+ parents: pomParents(file, linesOf2, files)
987
+ });
988
+ if (isGradleFile(file))
989
+ return gradleProblem(f, label, where, lines, linesOf2);
990
+ 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`;
991
+ }
992
+ function pomValue(f, label, file, at, ctx, what) {
993
+ const r = resolvePomValue(at, ctx.pom, { file: ctx.file, parents: ctx.parents });
994
+ if ("missing" in r)
995
+ return {
996
+ problem: `${label}: ${what} at ${file}:${at.line} is \${${r.missing}}, which no <properties> entry or <parent> of ${file}${ctx.parents.length ? ` or of its parent poms (${ctx.parents.map((p) => p.file).join(", ")})` : ""} sets: Atticus can't say what it resolves to`
997
+ };
998
+ const uncited = (r.via ?? []).find((l) => !citedLine(f, l.file, l.line));
999
+ if (uncited !== void 0)
1000
+ return {
1001
+ problem: `${label}: ${what} at ${file}:${at.line} is ${at.value}, written as "${r.value}" through ${uncited.file}:${uncited.line}; cite that line in cite.with`
1002
+ };
1003
+ return { value: r.value };
1004
+ }
1005
+ var DEPS = /* @__PURE__ */ new WeakMap();
1006
+ function dependencyOnLine(pom, line) {
1007
+ let byLine = DEPS.get(pom);
1008
+ if (!byLine) {
1009
+ byLine = /* @__PURE__ */ new Map();
1010
+ for (const d of pom.dependencies)
1011
+ if (d.artifact && !byLine.has(d.artifact.line))
1012
+ byLine.set(d.artifact.line, d);
1013
+ DEPS.set(pom, byLine);
1014
+ }
1015
+ return byLine.get(line);
1016
+ }
1017
+ var pomScopeOf = (declared) => declared === void 0 ? "compile" : declared.trim() === "system" ? "provided" : declared.trim();
1018
+ function pomProblem(f, label, where, ctx) {
1019
+ const pom = ctx.pom;
1020
+ const line = f.cite.line;
1021
+ const file = f.cite.file;
1022
+ if (f.kind === "artifact") {
1023
+ if (pom.artifact?.line !== line) {
1024
+ const dep2 = dependencyOnLine(pom, line);
1025
+ 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>";
1026
+ 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}` : ""}`;
1027
+ }
1028
+ const name2 = pomValue(f, label, file, pom.artifact, ctx, "the project's <artifactId>");
1029
+ if ("problem" in name2)
1030
+ return name2.problem;
1031
+ if (name2.value !== f.name)
1032
+ return `${label} names "${f.name}", and ${where} writes the project's artifactId as "${name2.value}"`;
1033
+ const at = pom.group ?? pom.parentGroup;
1034
+ if (!at)
1035
+ return `${label} names group "${f.group}", and ${file} writes no groupId of the project or its <parent>`;
1036
+ const inherited = pom.group ? "" : " (the <parent>'s, which the project inherits)";
1037
+ const group2 = pomValue(f, label, file, at, ctx, `the group${inherited}`);
1038
+ if ("problem" in group2)
1039
+ return group2.problem;
1040
+ if (group2.value !== f.group)
1041
+ return `${label} names group "${f.group}", and ${file}:${at.line} writes "${group2.value}"${inherited}`;
1042
+ if (!citedLine(f, file, at.line))
1043
+ return `${label}: the group is written at ${file}:${at.line}${pom.group ? "" : " (the <parent>'s)"}; cite that line in cite.with`;
1044
+ return void 0;
1045
+ }
1046
+ const dep = dependencyOnLine(pom, line);
1047
+ if (!dep) {
1048
+ const what = pom.artifact?.line === line ? "the project's own <artifactId>" : pom.parentArtifact?.line === line ? "the <parent>'s <artifactId>" : "no dependency's <artifactId>";
1049
+ return `${label} says ${where} declares a dependency, and that line is ${what}: cite the <artifactId> line of the <dependency> in <dependencies>`;
1050
+ }
1051
+ if (dep.managed)
1052
+ return `${label} cites ${where}, a <dependencyManagement> entry, which only pins a version: cite the dependency where <dependencies> declares it`;
1053
+ if (dep.plugin)
1054
+ return `${label} cites ${where}, a dependency of a build plugin, not of the component: leave it out`;
1055
+ const name = pomValue(f, label, file, dep.artifact, ctx, "the dependency's <artifactId>");
1056
+ if ("problem" in name)
1057
+ return name.problem;
1058
+ if (name.value !== f.name)
1059
+ return `${label} names "${f.name}", and ${where} declares "${name.value}"`;
1060
+ if (!dep.group)
1061
+ return `${label}: the <dependency> at ${where} writes no <groupId>`;
1062
+ const group = pomValue(f, label, file, dep.group, ctx, "the dependency's <groupId>");
1063
+ if ("problem" in group)
1064
+ return group.problem;
1065
+ if (group.value !== f.group)
1066
+ return `${label} names group "${f.group}", and the <dependency> at ${where} writes "${dep.group.value}"${group.value !== dep.group.value ? ` (${group.value})` : ""}`;
1067
+ if (!citedLine(f, file, dep.group.line))
1068
+ return `${label}: the dependency's group is written at ${file}:${dep.group.line}; cite that line in cite.with`;
1069
+ const declared = pomScopeOf(dep.scope?.value);
1070
+ if (declared !== (f.scope ?? "compile"))
1071
+ return `${label} says scope ${f.scope ?? "compile"}, and the <dependency> at ${where} declares ${dep.scope?.value.trim() === "system" ? "system, which is recorded as provided" : declared}${dep.scope ? ` (${file}:${dep.scope.line})` : ""}`;
1072
+ return void 0;
1073
+ }
1074
+ function gradleProblem(f, label, where, lines, linesOf2) {
1075
+ const text = lines[f.cite.line - 1] ?? "";
1076
+ const file = f.cite.file;
1077
+ if (f.kind === "dependency" && isVersionCatalogFile(file))
1078
+ return catalogProblem(f, label, where, lines, linesOf2);
1079
+ if (f.kind === "dependency") {
1080
+ const at = isGradleBuildFile(file) ? gradleDependencyAt(lines, f.cite.line) : void 0;
1081
+ const tool = gradleToolConfigurationOn(text);
1082
+ if (!at && tool)
1083
+ return `${label} cites ${where}, the ${tool} tool's own configuration: what it names runs the tool, and is no dependency of the component`;
1084
+ if (!at)
1085
+ return `${label} says ${where} declares a dependency, and that line declares none: cite the line in dependencies { } that names it`;
1086
+ if ("none" in at)
1087
+ return `${label} cites ${where}, which is in ${at.none}, not a project's dependencies { }: a version pinned, a constraint or the build's own class path is no dependency of the component`;
1088
+ const d = at.dependency;
1089
+ if (d.group !== f.group || d.name !== f.name)
1090
+ return `${label} names "${f.group}:${f.name}", and ${where} declares "${d.group}:${d.name}"`;
1091
+ if (d.scope !== (f.scope ?? "compile"))
1092
+ return `${label} says scope ${f.scope ?? "compile"}, and ${where} declares it with ${d.configuration} (${d.scope})`;
1093
+ return void 0;
1094
+ }
1095
+ let project;
1096
+ if (isGradleSettingsFile(file)) {
1097
+ const root = gradleNameOn(text);
1098
+ if (root !== void 0) {
1099
+ if (root !== f.name)
1100
+ return `${label} names "${f.name}", and ${where} sets "${root}"`;
1101
+ } else {
1102
+ const all2 = gradleProjects(lines);
1103
+ const ps = all2.filter((x) => x.line === f.cite.line);
1104
+ if (!ps.length)
1105
+ return `${label} says ${where} is the coordinates the build publishes, and that line sets no project name: cite rootProject.name, an include, or a project(':x').name line`;
1106
+ const p = ps.find((x) => x.name === f.name);
1107
+ if (!p)
1108
+ return `${label} names "${f.name}", and ${where} names ${ps.map((x) => `"${x.name}"`).join(", ")}`;
1109
+ const renamed = all2.find((x) => x.renamed && x.path === p.path);
1110
+ if (!p.renamed && renamed)
1111
+ return `${label} names "${f.name}", and ${file}:${renamed.line} names that project "${renamed.name}": cite that line`;
1112
+ project = p.path;
1113
+ }
1114
+ } else {
1115
+ const name = gradleNameOn(text);
1116
+ if (name === void 0)
1117
+ 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`;
1118
+ if (name !== f.name)
1119
+ return `${label} names "${f.name}", and ${where} sets "${name}"`;
1120
+ const dir = dirOf(file);
1121
+ if (dir) {
1122
+ const dirs2 = projectDirs(settingsOf(linesOf2)?.lines);
1123
+ project = [...dirs2].find(([, d]) => d === dir)?.[0] ?? dir.replace(/\//g, ":");
1124
+ }
1125
+ }
1126
+ const dirs = projectDirs(settingsOf(linesOf2)?.lines);
1127
+ const ownDir = project === void 0 ? "" : dirs.get(project) ?? project.replace(/:/g, "/");
1128
+ const parts = [{ file, line: f.cite.line }, ...f.cite.with ?? []];
1129
+ const groups = parts.flatMap((p) => {
1130
+ const ls = linesOf2(p.file);
1131
+ const g2 = gradleGroupOn(ls?.[p.line - 1] ?? "");
1132
+ if (g2 === void 0 || !ls || !isGradleBuildFile(p.file))
1133
+ return [];
1134
+ const stack = gradleBlocks(ls)[p.line - 1] ?? [];
1135
+ const pDir = dirOf(p.file);
1136
+ const applies = pDir === ownDir && pDir !== "" ? stack.length === 0 : pDir === "" && (stack.length === 0 ? project === void 0 : stack.length === 1 && (stack[0] === "allprojects" || project !== void 0 && (stack[0] === "subprojects" || projectOf(stack[0]) === project)));
1137
+ return [{ ...p, group: g2, applies }];
1138
+ });
1139
+ const g = groups.find((x) => x.applies);
1140
+ if (!g) {
1141
+ const other = groups[0];
1142
+ if (other)
1143
+ return `${label}: ${other.file}:${other.line} sets the group of another project than ${f.name}; cite the line that sets ${f.name}'s (group = '${f.group}') in cite.with`;
1144
+ return `${label}: no line it cites sets the group; cite the build.gradle line that does (group = '${f.group}') in cite.with`;
1145
+ }
1146
+ if (g.group !== f.group)
1147
+ return `${label} names group "${f.group}", and ${g.file}:${g.line} sets "${g.group}"`;
1148
+ return void 0;
1149
+ }
1150
+ function catalogProblem(f, label, where, lines, linesOf2) {
1151
+ const lib = catalogLibraryAt(lines, f.cite.line);
1152
+ if (!lib)
1153
+ return `${label} cites ${where}, which is no [libraries] entry of the version catalog: cite the entry that gives its coordinates`;
1154
+ if (lib.group !== f.group || lib.name !== f.name)
1155
+ return `${label} names "${f.group}:${f.name}", and ${where} gives ${lib.alias} as "${lib.group}:${lib.name}"`;
1156
+ if (f.version !== void 0) {
1157
+ const v = lib.version ?? (lib.versionRef ? catalogVersions(lines).get(lib.versionRef)?.value : void 0);
1158
+ if (v !== f.version)
1159
+ return `${label} says version ${f.version}, and ${where} gives ${v === void 0 ? "no version Atticus can read" : `"${v}"`}${lib.versionRef ? ` (version.ref = "${lib.versionRef}")` : ""}`;
1160
+ }
1161
+ const catalog = catalogNameOf(f.cite.file);
1162
+ const use = `${catalog}.${lib.accessor}`;
1163
+ let problem;
1164
+ for (const p of f.cite.with ?? []) {
1165
+ if (!isGradleBuildFile(p.file))
1166
+ continue;
1167
+ const ls = linesOf2(p.file);
1168
+ const u = ls ? gradleCatalogUseOn(ls[p.line - 1] ?? "") : void 0;
1169
+ if (!ls || !u || u.catalog !== catalog || u.accessor !== lib.accessor)
1170
+ continue;
1171
+ const at = projectDependenciesAt(gradleBlocks(ls), p.line);
1172
+ if ("none" in at) {
1173
+ problem ??= `${label}: ${p.file}:${p.line} is in ${at.none}, not a project's dependencies { }: a version pinned, a constraint or the build's own class path is no dependency of the component`;
1174
+ continue;
1175
+ }
1176
+ if (u.scope !== (f.scope ?? "compile")) {
1177
+ problem ??= `${label} says scope ${f.scope ?? "compile"}, and ${p.file}:${p.line} declares it with ${u.configuration} (${u.scope})`;
1178
+ continue;
1179
+ }
1180
+ return void 0;
1181
+ }
1182
+ return problem ?? `${label}: ${where} is the catalog's entry, which only names the library; cite the build line in dependencies { } that declares it (${use}) in cite.with`;
1183
+ }
1184
+ function buildUnrecorded(files, linesOf2, kept, all2) {
1185
+ const named = all2 ? pomFilesNamed(all2, linesOf2) : void 0;
1186
+ const cited = new Set(kept.filter((f) => f.kind === "artifact" || f.kind === "dependency").map((f) => `${f.cite.file}:${f.cite.line}`));
1187
+ const out = [];
1188
+ const add = (file, line, kind, c) => {
1189
+ if (!cited.has(`${file}:${line}`))
1190
+ out.push({ cite: `${file}:${line}`, kind, coordinates: c });
1191
+ };
1192
+ for (const file of [...files].sort()) {
1193
+ const lines = linesOf2(file);
1194
+ if (!lines)
1195
+ continue;
1196
+ if (isPomFileIn(file, named)) {
1197
+ const pom = pomCoordinates(lines);
1198
+ const parents = pomParents(file, linesOf2, all2);
1199
+ const said = (at) => {
1200
+ if (!at)
1201
+ return "?";
1202
+ const r = resolvePomValue(at, pom, { file, parents });
1203
+ return "value" in r ? r.value : at.value;
1204
+ };
1205
+ if (pom.artifact)
1206
+ add(file, pom.artifact.line, "artifact", `${said(pom.group ?? pom.parentGroup)}:${said(pom.artifact)}`);
1207
+ for (const d of pom.dependencies)
1208
+ if (!d.managed && !d.plugin && d.artifact)
1209
+ add(file, d.artifact.line, "dependency", `${said(d.group)}:${said(d.artifact)}`);
1210
+ } else if (isGradleBuildFile(file)) {
1211
+ const blocks = gradleBlocks(lines);
1212
+ lines.forEach((_, i) => {
1213
+ const at = gradleDependencyAt(lines, i + 1, blocks);
1214
+ if (at && "dependency" in at && at.dependency.scope !== "import")
1215
+ add(file, i + 1, "dependency", `${at.dependency.group}:${at.dependency.name}`);
1216
+ });
1217
+ }
1218
+ }
1219
+ return out;
1220
+ }
1221
+
169
1222
  // packages/verify/dist/frameworks.js
170
1223
  var FRAMEWORKS = [
171
1224
  "spring",
@@ -424,6 +1477,7 @@ function rulesOf(c) {
424
1477
  notProduct: underFolders(c.notProductFolders),
425
1478
  notRead: notReadTest(c.notReadFolders),
426
1479
  gatewayBundle: gatewayBundleTest(c.gatewayBundleFolders),
1480
+ gatewayBundleFolders: c.gatewayBundleFolders,
427
1481
  frameworks: c.frameworks
428
1482
  };
429
1483
  }
@@ -581,7 +1635,8 @@ function correctionFor(f, all2) {
581
1635
  const byCite = corrections.filter((c) => at(c) && c.target.value === f.cite.value);
582
1636
  const edited = corrections.filter((c) => c.fact === f.id && c.action === "edit");
583
1637
  const moved = edited.filter((c) => (c.line ?? c.target.line) === f.cite.line);
584
- return [...byId, ...byCite, ...moved].sort((a, b) => a.at < b.at ? 1 : a.at > b.at ? -1 : 0)[0];
1638
+ const pos = new Map(all2.map((c, i) => [c, i]));
1639
+ return [.../* @__PURE__ */ new Set([...byId, ...byCite, ...moved])].sort((a, b) => a.at < b.at ? 1 : a.at > b.at ? -1 : pos.get(b) - pos.get(a))[0];
585
1640
  }
586
1641
  function outsidePairingFor(f, all2) {
587
1642
  const newest = linksFor(f, all2)[0];
@@ -1530,201 +2585,110 @@ function pageRouteMatches(file, lines, exists, path) {
1530
2585
  const route = pageRouteOf(file, lines, exists);
1531
2586
  if (route === void 0)
1532
2587
  return false;
1533
- const norm = (p) => normalizePath(p.replace(/\{([^}:?]*)[^}]*\}/g, "{$1}")).toLowerCase() || "/";
1534
- return norm(route) === norm(path);
2588
+ const norm2 = (p) => normalizePath(p.replace(/\{([^}:?]*)[^}]*\}/g, "{$1}")).toLowerCase() || "/";
2589
+ return norm2(route) === norm2(path);
1535
2590
  }
1536
2591
 
1537
- // packages/verify/dist/reachable.js
1538
- var CODE = /\.(java|kt|kts|scala|groovy|cs|vb|fs|py|rb|go|rs|php|swift|ts|tsx|js|mjs|cjs|dart)$/i;
1539
- var MODEL_DIR = /(^|\/)(models?|dtos?|payloads?|schemas?|pojos?|beans|viewmodels?)\//i;
1540
- var MODEL_NAME = /(dto|request|response|payload|model|body)$/i;
1541
- var MODEL_PART = /[._-](dto|model|schema|payload|request|response)\.[^/.]+$/i;
1542
- var MAPS_TABLE = /@Entity\b|@Table\b|@Document\b|\[Table\(|__tablename__|models\.Model\b|@Entity\(|\bgorm\.Model\b/;
1543
- var ROOT_PART = /[._-](controller|resolver|gateway|handlers?|router|routes?|consumer|listener|subscriber|client|publisher|producer|endpoints?)\.[^/.]+$/i;
1544
- var CLIENT_NAME = /(client|gateway|publisher|producer|sender|feign|proxy|connector)$/i;
1545
- var CLIENT_DIR = /(^|\/)(clients?|gateways?|integrations?|publishers?|producers?|outbound)\//i;
1546
- var base = (path) => path.slice(path.lastIndexOf("/") + 1);
1547
- var stem = (path) => {
1548
- const b = base(path);
1549
- const dot = b.indexOf(".");
1550
- return dot > 0 ? b.slice(0, dot) : b;
1551
- };
1552
- function isModelFile(path, text) {
1553
- if (!CODE.test(path) || readingRank(path) === 5)
1554
- return false;
1555
- if (!MODEL_DIR.test(path) && !MODEL_NAME.test(stem(path)) && !MODEL_PART.test(path))
1556
- return false;
1557
- return text === void 0 || !MAPS_TABLE.test(text);
1558
- }
1559
- var ENTRY_POINT_NAME = /(controller|resource|router|routes?|handlers?|listener|consumer|subscriber|endpoints?|servlet|webhook|resolver)$/i;
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);
2592
+ // packages/verify/dist/secrets.js
2593
+ var CONFIG_FILE = /\.(ya?ml|properties|json|xml|config|env|ini|toml|conf|cfg)$|(^|\/)\.env(\.[^/]*)?$|(^|\/)credentials?$/i;
2594
+ var isConfigFile = (path) => CONFIG_FILE.test(path.replace(/\\/g, "/"));
2595
+ var PLACEHOLDER = /^(<[^>]*>|\*+|x{3,}|changeme|change-me|secret|password|todo|tbd|none|null|nil|dummy|example|sample|test|redacted|your[-_ ].*)$/i;
2596
+ var KEY_VALUE = /^\s*(?:-\s+)?(?:export\s+)?["']?([A-Za-z0-9_.\-[\]]+)["']?\s*[:=]\s*(.*?)\s*,?\s*$/;
2597
+ var XML_ELEMENT = /<([A-Za-z_][\w.-]*)>([^<]+)<\/\1>/g;
2598
+ var XML_NAMED = /\b(?:key|name)\s*=\s*"([^"]+)"\s+value\s*=\s*"([^"]*)"/g;
2599
+ var XML_NAMED_AFTER = /\bvalue\s*=\s*"([^"]*)"\s+(?:key|name)\s*=\s*"([^"]+)"/g;
2600
+ var CONNECTION_PAIR = /(?:^|[;"'])\s*([A-Za-z][A-Za-z0-9 _.-]*?)\s*=\s*([^;"'<>\s][^;"'<>]*)/g;
2601
+ var TOKEN_VALUE_KEY = /^(value|val)$/i;
2602
+ var TOKEN_NAME = /^\s*"(xpath|name|key)"\s*:\s*"([^"]+)"/;
2603
+ function isReference(value) {
2604
+ 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);
2605
+ }
2606
+ var unquote = (v) => v.replace(/\s+#.*$/, "").replace(/^["']|["']$/g, "").trim();
2607
+ function tokenKeyNear(lines, i) {
2608
+ for (const step of [-1, 1])
2609
+ for (let j = i + step; j >= 0 && j < lines.length && Math.abs(j - i) <= 4; j += step) {
2610
+ const l = lines[j];
2611
+ const m = TOKEN_NAME.exec(l);
2612
+ if (m)
2613
+ return m[2];
2614
+ if (/[{}]/.test(l))
2615
+ break;
2616
+ }
2617
+ return void 0;
1566
2618
  }
1567
- function isRootFile(path) {
1568
- if (!CODE.test(path) || readingRank(path) === 5 || isModelFile(path))
2619
+ function keyIsSecret(key) {
2620
+ if (hasSecretShape(key))
2621
+ return true;
2622
+ for (const run of key.match(/[0-9a-f]{24,}|[0-9A-F]{24,}/g) ?? [])
2623
+ if (/\d/.test(run) && /[a-f]/i.test(run))
2624
+ return true;
2625
+ const digitsAndLetters = /\d/.test(key) && /[A-Za-z]/.test(key);
2626
+ if (key.length >= 32 && /^[A-Za-z0-9+/=]+$/.test(key) && digitsAndLetters)
2627
+ return true;
2628
+ if (key.length >= 32 && /^[A-Za-z0-9_-]+$/.test(key) && /\d/.test(key) && /[a-z]/.test(key) && /[A-Z]/.test(key))
2629
+ return true;
2630
+ if (key.length < 16 || !/^[A-Za-z0-9+/=]+$/.test(key) || !/\d/.test(key))
1569
2631
  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
- }
1640
- }
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));
2632
+ const kind = (c) => /\d/.test(c) ? 0 : /[a-z]/.test(c) ? 1 : 2;
2633
+ let switches = 0;
2634
+ for (let i = 1; i < key.length; i++)
2635
+ if (kind(key[i]) !== kind(key[i - 1]))
2636
+ switches++;
2637
+ return switches >= key.length / 2;
2638
+ }
2639
+ function itemNameAbove(lines, i) {
2640
+ const col = /^\s*/.exec(lines[i])[0].length;
2641
+ for (let j = i - 1; j >= 0 && i - j <= 6; j--) {
2642
+ const l = lines[j];
2643
+ if (!l.trim())
2644
+ continue;
2645
+ const lead = /^\s*/.exec(l)[0].length;
2646
+ const item = /^(\s*)-\s+(.*)$/.exec(l);
2647
+ const keyCol = item ? item[1].length + (l.length - item[1].length - item[2].length) : lead;
2648
+ if (keyCol !== col)
2649
+ return void 0;
2650
+ const m = /^(?:\s*-\s+|\s*)(name|key)\s*:\s*["']?([^"'\s#]+)["']?\s*$/.exec(l);
2651
+ if (m)
2652
+ return m[2];
2653
+ if (item)
2654
+ return void 0;
1665
2655
  }
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));
2656
+ return void 0;
1683
2657
  }
1684
- var CHAIN_LINES = 8;
1685
- var CONTINUES = /^\s*\??\./;
1686
- function chainOf(file, line) {
1687
- const at = (n) => file?.[n - 1];
1688
- const cited = at(line);
1689
- if (cited === void 0)
2658
+ function liveSecretsIn(file, lines) {
2659
+ const shownKey = (key) => keyIsSecret(key) ? "" : key;
2660
+ if (!isConfigFile(file))
1690
2661
  return [];
1691
- const out = [cited];
1692
- for (let n = line, k = 0; k < CHAIN_LINES && CONTINUES.test(at(n) ?? ""); k++, n--) {
1693
- const above = at(n - 1);
1694
- if (above === void 0)
1695
- break;
1696
- out.push(above);
1697
- }
1698
- for (let n = line + 1, k = 0; k < CHAIN_LINES && CONTINUES.test(at(n) ?? ""); k++, n++)
1699
- out.push(at(n));
2662
+ const out = [];
2663
+ lines.forEach((text, i) => {
2664
+ if (/^\s*(#|\/\/|;|<!--)/.test(text))
2665
+ return;
2666
+ const pairs = [];
2667
+ const kv = KEY_VALUE.exec(text);
2668
+ if (kv) {
2669
+ const key = TOKEN_VALUE_KEY.test(kv[1]) ? tokenKeyNear(lines, i) ?? (/\.ya?ml$/i.test(file) ? itemNameAbove(lines, i) : void 0) ?? kv[1] : kv[1];
2670
+ pairs.push({ key, value: unquote(kv[2]) });
2671
+ }
2672
+ for (const m of text.matchAll(XML_ELEMENT))
2673
+ pairs.push({ key: m[1], value: m[2].trim() });
2674
+ for (const m of text.matchAll(XML_NAMED))
2675
+ pairs.push({ key: m[1], value: m[2].trim() });
2676
+ for (const m of text.matchAll(XML_NAMED_AFTER))
2677
+ pairs.push({ key: m[2], value: m[1].trim() });
2678
+ if (text.includes(";"))
2679
+ for (const m of text.matchAll(CONNECTION_PAIR))
2680
+ pairs.push({ key: m[1].trim(), value: m[2].trim() });
2681
+ 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
2682
+ !/^[{[]/.test(value) && !isReference(value) && looksLikeSecret(key, value));
2683
+ if (named) {
2684
+ out.push({ file, line: i + 1, key: shownKey(named.key) });
2685
+ return;
2686
+ }
2687
+ if (hasSecretShape(text))
2688
+ out.push({ file, line: i + 1, key: pairs[0] ? shownKey(pairs[0].key) : "(token)" });
2689
+ });
1700
2690
  return out;
1701
2691
  }
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
2692
 
1729
2693
  // packages/verify/dist/skipped.js
1730
2694
  function notReadForSkipped(path, rules = DEFAULT_READ_RULES) {
@@ -1745,9 +2709,9 @@ var NOT_TOPIC_FIRST = new Set("com org net io java javax jakarta android android
1745
2709
  var DOTTED_TOPIC = /^[a-z][a-z0-9_-]*(\.[a-z][a-z0-9_-]*){2,}$/;
1746
2710
  var SEPARATED_NAME = /^[A-Za-z][A-Za-z0-9_]*([._:-][A-Za-z0-9_]+)+$/;
1747
2711
  var QUOTED = /(["'`])((?:\\.|(?!\1)[^\\\n])*)\1/g;
1748
- var KEY_VALUE = /^\s*-?\s*["']?([A-Za-z0-9_.\-[\]]+)["']?\s*[:=]\s*([^\s"'#]+)\s*$/;
2712
+ var KEY_VALUE2 = /^\s*-?\s*["']?([A-Za-z0-9_.\-[\]]+)["']?\s*[:=]\s*([^\s"'#]+)\s*$/;
1749
2713
  var ELEMENT_TEXT = /<([A-Za-z][\w:.-]*)[^>]*>([^<\s]+)<\/\1>/g;
1750
- var wordsOf2 = (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);
2714
+ 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
2715
  var TOPIC_WORDS = /* @__PURE__ */ new Set([
1752
2716
  "topic",
1753
2717
  "topics",
@@ -1761,7 +2725,7 @@ var TOPIC_WORDS = /* @__PURE__ */ new Set([
1761
2725
  "exchanges"
1762
2726
  ]);
1763
2727
  var topicContext = (line) => {
1764
- const w = wordsOf2(line);
2728
+ const w = wordsOf(line);
1765
2729
  return w.some((x) => TOPIC_WORDS.has(x)) || w.join(" ").includes("routing key");
1766
2730
  };
1767
2731
  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 +2736,7 @@ var keysBefore = (prefix) => [
1772
2736
  ...[...prefix.matchAll(/["']?([A-Za-z][\w.-]*)["']?\s*[:=]/g)].map((m) => m[1]),
1773
2737
  ...[...prefix.matchAll(/\b([A-Za-z]\w*)\s*\{/g)].map((m) => m[1])
1774
2738
  ];
1775
- var isBuildUrl = (u, prefix) => /\.git\/?$/i.test(u) || /\bscm:\w+:$/i.test(prefix) || keysBefore(prefix).some((k) => wordsOf2(k).some((w) => BUILD_KEY_WORDS.has(w)));
2739
+ 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
2740
  var HEADER_ARG = /header\w*\s*(?:\.\s*\w+\s*)?\(\s*(?:(?:value|name)\s*=\s*)?$/i;
1777
2741
  var isHeaderName = (s, prefix) => /^x-/i.test(s) || HEADER_ARG.test(prefix.replace(/["'`]$/, ""));
1778
2742
  var cleanUrl = (u) => u.replace(/[.:]+$/, "").replace(/^([a-z0-9+.-]+:\/\/)[^/@\s]+@/i, "$1<redacted>@");
@@ -1867,7 +2831,7 @@ function candidatesIn(path, lines) {
1867
2831
  s: m[2],
1868
2832
  before: code2.slice(0, m.index + 1)
1869
2833
  }));
1870
- const kv = KEY_VALUE.exec(code2);
2834
+ const kv = KEY_VALUE2.exec(code2);
1871
2835
  if (kv)
1872
2836
  strings2.push({ s: kv[2], before: "" });
1873
2837
  for (const m of code2.matchAll(ELEMENT_TEXT))
@@ -1907,102 +2871,747 @@ function indexFacts(facts) {
1907
2871
  Object.values(o).forEach(walk);
1908
2872
  }
1909
2873
  };
1910
- facts.forEach(walk);
1911
- const paths = /* @__PURE__ */ new Set();
1912
- for (const s of strings2) {
1913
- if (/\s/.test(s))
1914
- continue;
1915
- const u = /^[a-z0-9+.-]+:\/\/[^/]+(\/.*)?$/i.exec(s);
1916
- const p = u ? u[1] : s.includes("/") ? s : void 0;
1917
- if (p && p.length > 1)
1918
- paths.add(`${normPath(p)}/`);
2874
+ facts.forEach(walk);
2875
+ const paths = /* @__PURE__ */ new Set();
2876
+ for (const s of strings2) {
2877
+ if (/\s/.test(s))
2878
+ continue;
2879
+ const u = /^[a-z0-9+.-]+:\/\/[^/]+(\/.*)?$/i.exec(s);
2880
+ const p = u ? u[1] : s.includes("/") ? s : void 0;
2881
+ if (p && p.length > 1)
2882
+ paths.add(`${normPath(p)}/`);
2883
+ }
2884
+ return { at, strings: [...strings2].map((s) => s.toLowerCase()), paths: [...paths] };
2885
+ }
2886
+ function factsCover(file, c, ix) {
2887
+ if ([c.line - 1, c.line, c.line + 1].some((n) => ix.at.has(`${file}:${n}`)))
2888
+ return true;
2889
+ if (c.kind === "path") {
2890
+ const p = `${normPath(c.value)}/`;
2891
+ return ix.paths.some((f) => f.includes(p));
2892
+ }
2893
+ const v = c.value.toLowerCase().replace(/\/+$/, "");
2894
+ return ix.strings.some((s) => s.includes(v));
2895
+ }
2896
+ var skippedOf = (file, c) => ({
2897
+ cite: `${file}:${c.line}`,
2898
+ kind: c.kind,
2899
+ value: c.value,
2900
+ text: c.text
2901
+ });
2902
+ var SPEC_MARK = /^\s*["']?(openapi|swagger)["']?\s*:/m;
2903
+ var SPEC_EXT = /\.(ya?ml|json)$/i;
2904
+ function specOpsUncoveredIn(file, text, facts) {
2905
+ if (!SPEC_EXT.test(file) || !SPEC_MARK.test(text.slice(0, 4e3)))
2906
+ return void 0;
2907
+ let doc;
2908
+ try {
2909
+ doc = readOpenApiDocument(text);
2910
+ } catch {
2911
+ return void 0;
2912
+ }
2913
+ if (!doc || !doc.operations.length)
2914
+ return void 0;
2915
+ const server = (() => {
2916
+ const s = doc.servers[0];
2917
+ if (!s)
2918
+ return "";
2919
+ const p = /^[a-z0-9+.-]+:\/\/[^/]+(\/.*)?$/i.exec(s)?.[1] ?? (s.startsWith("/") ? s : "");
2920
+ return p.replace(/\/+$/, "");
2921
+ })();
2922
+ const entries = facts.filter((f) => f.kind === "entry");
2923
+ const atLines = /* @__PURE__ */ new Set();
2924
+ for (const e of entries)
2925
+ for (const k of indexFacts([e]).at)
2926
+ atLines.add(k);
2927
+ const out = [];
2928
+ for (const op of doc.operations) {
2929
+ const lines = [op.methodLine, op.line].filter((n) => n !== void 0);
2930
+ if (lines.some((n) => [n - 1, n, n + 1].some((x) => atLines.has(`${file}:${x}`))))
2931
+ continue;
2932
+ const method = op.method.toUpperCase();
2933
+ const own = normPath(op.path);
2934
+ const full = normPath(`${server}${op.path}`);
2935
+ const covered = entries.some((e) => {
2936
+ if (e.method && e.method.toUpperCase() !== method)
2937
+ return false;
2938
+ const p = normPath(e.path);
2939
+ return p === own || p === full || p.endsWith(own) || p.split("/").length > 2 && own.endsWith(p);
2940
+ });
2941
+ if (covered)
2942
+ continue;
2943
+ const opId = op.node?.get?.("operationId");
2944
+ const line = op.methodLine ?? op.line ?? 1;
2945
+ out.push({
2946
+ spec: file,
2947
+ method,
2948
+ path: op.path,
2949
+ ...typeof opId === "string" ? { operationId: opId } : {},
2950
+ cite: `${file}:${line}`,
2951
+ message: `${file}:${line} declares ${method} ${op.path}${typeof opId === "string" ? ` (${opId})` : ""}, which no entry covers`
2952
+ });
2953
+ }
2954
+ return out;
2955
+ }
2956
+ var REVIEWED_HOLDS_SHOWN = 5;
2957
+ function reviewedHoldsOf(r, skipped) {
2958
+ const n = skipped.length;
2959
+ const first = skipped.slice(0, 3).map((s) => `${s.cite} (${s.value})`);
2960
+ return {
2961
+ path: r.path,
2962
+ why: r.why,
2963
+ count: n,
2964
+ skipped: skipped.slice(0, REVIEWED_HOLDS_SHOWN),
2965
+ 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` : ""}`
2966
+ };
2967
+ }
2968
+
2969
+ // packages/verify/dist/settings-path.js
2970
+ var SETTINGS_FILE = /\.(ya?ml|properties|json|xml|config|conf|ini|toml|cfg|env)$|(^|\/)\.env(\.[^/]*)?$/i;
2971
+ var isSettingsFile = (path) => SETTINGS_FILE.test(path);
2972
+ var isYaml = (path) => /\.ya?ml$/i.test(path);
2973
+ var DOC_FILE = /\.(md|markdown|mdx|adoc|asciidoc|txt|text|rst|html?|textile|org|rtf|wiki)$/i;
2974
+ var isProperties = (path) => /\.properties$/i.test(path);
2975
+ var escape = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2976
+ var YAML_KEY = /^(["']?)([^\s"'#:{}[\],&*!|>][^"'#:]*?)\1\s*:(?:\s+(.*))?$/;
2977
+ function yamlLine(text) {
2978
+ if (!text.trim() || /^\s*#/.test(text) || /^\s*(---|\.\.\.)\s*$/.test(text))
2979
+ return void 0;
2980
+ const lead = /^ */.exec(text)[0].length;
2981
+ const dash = /^ *-(\s+|$)/.exec(text);
2982
+ const col = dash ? dash[0].length : lead;
2983
+ const body = text.slice(col);
2984
+ const m = YAML_KEY.exec(body.trimEnd());
2985
+ const rest = m?.[3]?.trim();
2986
+ return {
2987
+ lead,
2988
+ col,
2989
+ item: !!dash,
2990
+ key: m?.[2]?.trim(),
2991
+ // a comment or an anchor after the key sets nothing
2992
+ rest: rest && !/^[#&]/.test(rest) ? rest : void 0
2993
+ };
2994
+ }
2995
+ function yamlPathAt(lines, line) {
2996
+ const at = yamlLine(lines[line - 1] ?? "");
2997
+ if (!at?.key)
2998
+ return void 0;
2999
+ const path = [at.key];
3000
+ let col = at.item ? at.lead : at.col;
3001
+ let seq = at.item;
3002
+ for (let j = line - 2; j >= 0 && (col > 0 || seq); j--) {
3003
+ const l = lines[j];
3004
+ if (/^\s*(---|\.\.\.)\s*$/.test(l))
3005
+ break;
3006
+ const y = yamlLine(l);
3007
+ if (!y)
3008
+ continue;
3009
+ if (y.item && y.col === col) {
3010
+ col = y.lead;
3011
+ seq = true;
3012
+ continue;
3013
+ }
3014
+ if (seq && !y.item && y.col === col && y.key && !y.rest) {
3015
+ path.unshift(y.key);
3016
+ seq = false;
3017
+ continue;
3018
+ }
3019
+ if (y.col >= col)
3020
+ continue;
3021
+ seq = false;
3022
+ if (!y.key || y.rest)
3023
+ return void 0;
3024
+ path.unshift(y.key);
3025
+ col = y.lead;
3026
+ }
3027
+ if (col > 0)
3028
+ return void 0;
3029
+ return path.flatMap((k) => k.split("."));
3030
+ }
3031
+ function yamlChildren(lines, line) {
3032
+ const at = yamlLine(lines[line - 1] ?? "");
3033
+ if (!at?.key)
3034
+ return [];
3035
+ const out = [];
3036
+ let childCol;
3037
+ for (let j = line; j < lines.length; j++) {
3038
+ const y = yamlLine(lines[j]);
3039
+ if (!y)
3040
+ continue;
3041
+ if (y.lead <= at.col)
3042
+ break;
3043
+ childCol ??= y.col;
3044
+ if (y.col < childCol)
3045
+ break;
3046
+ if (y.col === childCol && y.key && !y.item)
3047
+ out.push(y.key);
3048
+ }
3049
+ return out;
3050
+ }
3051
+ function propertiesKeyAt(lines, line) {
3052
+ const l = lines[line - 1] ?? "";
3053
+ if (/^\s*[#!]/.test(l))
3054
+ return void 0;
3055
+ return /^\s*((?:\\.|[^\s=:\\])+)\s*[=:\s]/.exec(l)?.[1];
3056
+ }
3057
+ var sameSegs = (a, b) => a.length === b.length && a.every((s, i) => s === b[i]);
3058
+ var keySegments = (key) => key.trim().split(".").map((s) => s.replace(/\[[^\]]*\]$/, "")).filter(Boolean);
3059
+ var fieldNames = (seg) => [
3060
+ seg,
3061
+ seg.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase())
3062
+ ];
3063
+ var CONFIG_PROPS = /@ConfigurationProperties\s*\(\s*(?:(?:prefix|value)\s*=\s*)?"([^"]+)"/;
3064
+ function helperBuildsKey(key, cite2, linesOf2) {
3065
+ if (isSettingsFile(cite2.file) || DOC_FILE.test(cite2.file))
3066
+ return false;
3067
+ const segs = keySegments(key);
3068
+ if (segs.length < 2 || segs.join(".") !== key.trim())
3069
+ return false;
3070
+ const last = segs[segs.length - 1];
3071
+ const prefix = segs.slice(0, -1);
3072
+ const line = linesOf2(cite2.file)?.[cite2.line - 1];
3073
+ if (line === void 0)
3074
+ return false;
3075
+ const code2 = isCommentLine(line) ? line : line.replace(/\/\*.*?\*\//g, "").replace(/(^|\s)\/\/.*$/, "");
3076
+ const literals = [];
3077
+ const bare2 = code2.replace(/(["'`])((?:(?!\1)[^\\]|\\.)*)\1/g, (_all, _q, text) => {
3078
+ literals.push(text);
3079
+ return '""';
3080
+ });
3081
+ if (!literals.includes(last) && !new RegExp(`(^|[^A-Za-z0-9_$-])${escape(last)}($|[^A-Za-z0-9_$-])`).test(bare2))
3082
+ return false;
3083
+ const parts = cite2.with ?? [];
3084
+ const files = [...new Set(parts.map((p) => p.file))];
3085
+ return files.some((file) => {
3086
+ const ls = linesOf2(file);
3087
+ if (!ls)
3088
+ return false;
3089
+ const here = parts.filter((p) => p.file === file);
3090
+ if (isYaml(file))
3091
+ return here.some((p) => {
3092
+ const at = yamlPathAt(ls, p.line);
3093
+ if (!at)
3094
+ return false;
3095
+ if (sameSegs(at, segs))
3096
+ return true;
3097
+ return sameSegs(at, prefix) && yamlChildren(ls, p.line).includes(last);
3098
+ });
3099
+ if (isProperties(file))
3100
+ return here.some((p) => propertiesKeyAt(ls, p.line) === segs.join("."));
3101
+ if (isSettingsFile(file))
3102
+ return false;
3103
+ return here.some((p) => {
3104
+ const m = CONFIG_PROPS.exec(ls[p.line - 1] ?? "");
3105
+ if (!m)
3106
+ return false;
3107
+ const pre = m[1].split(".");
3108
+ if (pre.length > prefix.length || !pre.every((s, i) => s === prefix[i]))
3109
+ return false;
3110
+ 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] ?? ""))));
3111
+ });
3112
+ });
3113
+ }
3114
+ var norm = (s) => s.replace(/[‘’‚'"“”„`]/g, "").replace(/\s+/g, " ").trim();
3115
+ function yamlScalar(rest) {
3116
+ const t = rest.trim().replace(/^!!?[\w/:.-]*\s+/, "");
3117
+ const q = /^(["'])((?:(?!\1).|\1\1)*)\1/.exec(t);
3118
+ if (q)
3119
+ return q[1] === "'" ? q[2].replace(/''/g, "'") : q[2];
3120
+ return t.replace(/\s+#.*$/, "").trim();
3121
+ }
3122
+ function propertiesValues(line, key, next = []) {
3123
+ let v = line.slice(line.indexOf(key) + key.length).replace(/^\s*[=:]?\s*/, "");
3124
+ for (let i = 0; /(^|[^\\])(\\\\)*\\$/.test(v) && i < next.length; i++)
3125
+ v = v.slice(0, -1) + next[i].replace(/^\s+/, "");
3126
+ return [v.trim(), decodeProperties(v)];
3127
+ }
3128
+ function decodeProperties(v) {
3129
+ return v.replace(/\\(u[0-9a-fA-F]{4}|.)/g, (_, c) => c.length === 5 ? String.fromCharCode(parseInt(c.slice(1), 16)) : c === "t" ? " " : c === "n" ? "\n" : c).trim();
3130
+ }
3131
+ function jsonValueOn(line) {
3132
+ const m = /"value"\s*:\s*("(?:[^"\\]|\\.)*"|[^,}\]\s]+)/.exec(line);
3133
+ if (!m)
3134
+ return void 0;
3135
+ if (!m[1].startsWith('"'))
3136
+ return m[1];
3137
+ try {
3138
+ return JSON.parse(m[1]);
3139
+ } catch {
3140
+ return m[1].slice(1, -1);
3141
+ }
3142
+ }
3143
+ function jsonFrames(lines) {
3144
+ const out = [];
3145
+ const stack = [];
3146
+ for (let ln = 0; ln < lines.length; ln++) {
3147
+ const l = lines[ln];
3148
+ for (let i = 0; i < l.length; i++) {
3149
+ const ch = l[i];
3150
+ const top = stack[stack.length - 1];
3151
+ if (ch === '"') {
3152
+ let j = i + 1;
3153
+ let text = "";
3154
+ for (; j < l.length && l[j] !== '"'; j++) {
3155
+ if (l[j] === "\\" && j + 1 < l.length)
3156
+ j++;
3157
+ text += l[j];
3158
+ }
3159
+ const isKey = top?.type === "{" && !top.afterColon && /^\s*:/.test(l.slice(j + 1));
3160
+ if (top?.type === "{") {
3161
+ if (isKey)
3162
+ top.pending = text;
3163
+ else if (top.afterColon && top.pending === "name" && top.name === void 0)
3164
+ top.name = text;
3165
+ }
3166
+ i = j;
3167
+ continue;
3168
+ }
3169
+ if (ch === ":" && top?.type === "{")
3170
+ top.afterColon = true;
3171
+ else if (ch === "," && top?.type === "{") {
3172
+ top.afterColon = false;
3173
+ top.pending = void 0;
3174
+ } else if (ch === "{" || ch === "[") {
3175
+ const under4 = top?.type === "{" ? top.pending : top?.under;
3176
+ stack.push({ type: ch, start: ln + 1, end: lines.length, ...under4 ? { under: under4 } : {} });
3177
+ } else if (ch === "}" || ch === "]") {
3178
+ const f = stack.pop();
3179
+ if (f) {
3180
+ out.push({
3181
+ type: f.type,
3182
+ start: f.start,
3183
+ end: ln + 1,
3184
+ ...f.under ? { under: f.under } : {},
3185
+ ...f.name !== void 0 ? { name: f.name } : {}
3186
+ });
3187
+ }
3188
+ }
3189
+ }
3190
+ }
3191
+ return out;
3192
+ }
3193
+ var noExt = (s) => s.trim().toLowerCase().replace(/\.[^.]*$/, "");
3194
+ function enclosingObject(lines, line) {
3195
+ let depth = 0;
3196
+ let start = -1;
3197
+ for (let j = line - 1; j >= 0; j--) {
3198
+ const l = lines[j];
3199
+ for (let k = l.length - 1; k >= 0; k--) {
3200
+ if (l[k] === "}" && j !== line - 1)
3201
+ depth++;
3202
+ if (l[k] === "{") {
3203
+ if (depth === 0) {
3204
+ start = j;
3205
+ break;
3206
+ }
3207
+ depth--;
3208
+ }
3209
+ }
3210
+ if (start >= 0)
3211
+ break;
3212
+ }
3213
+ if (start < 0)
3214
+ return void 0;
3215
+ depth = 0;
3216
+ for (let j = start; j < lines.length; j++) {
3217
+ for (const ch of lines[j]) {
3218
+ if (ch === "{")
3219
+ depth++;
3220
+ if (ch === "}" && --depth === 0)
3221
+ return lines.slice(start, j + 1);
3222
+ }
3223
+ }
3224
+ return void 0;
3225
+ }
3226
+ function configLineProblem(f, linesOf2, listed2, bundleFolders = DEFAULT_GATEWAY_BUNDLE_FOLDERS) {
3227
+ const lines = linesOf2(f.cite.file);
3228
+ if (!lines)
3229
+ return void 0;
3230
+ const at = lines[f.cite.line - 1] ?? "";
3231
+ const where = `${f.cite.file}:${f.cite.line}`;
3232
+ const segs = keySegments(f.key);
3233
+ const value = f.value === void 0 ? void 0 : norm(f.value);
3234
+ const same = (v) => value !== void 0 && v !== void 0 && norm(v) === value;
3235
+ const has = (l) => value !== void 0 && norm(l).includes(value);
3236
+ if (f.key.trim().startsWith("/") && /(^|\/)config\.json$/i.test(f.cite.file)) {
3237
+ const dir = f.cite.file.replace(/[^/]*$/, "");
3238
+ if (!listed2().some((p) => bundleFolders.some((b) => p.startsWith(`${dir}${b}/`))))
3239
+ return `config ${where} is a config.json beside no gateway bundle (no ${bundleFolders.map((b) => `${dir}${b}/`).join(" or ")}); a token's setting is read only from the bundle's own`;
3240
+ const obj = enclosingObject(lines, f.cite.line);
3241
+ const xpathRe = new RegExp(`"xpath"\\s*:\\s*"${escape(f.key.trim())}"`);
3242
+ if (!obj || !obj.some((l) => xpathRe.test(l)))
3243
+ return `the token at ${where} has no "xpath" of ${f.key}`;
3244
+ if (value !== void 0 && !obj.some((l) => same(jsonValueOn(l))))
3245
+ return `the token at ${where} sets no such value; cite the token whose "value" it is`;
3246
+ const around = jsonFrames(lines).filter((x) => x.type === "{" && x.start <= f.cite.line && x.end >= f.cite.line).sort((a, b) => b.start - a.start);
3247
+ if (f.target !== void 0) {
3248
+ const file = around.find((x) => /^(targets|policies|proxies)$/i.test(x.under ?? ""));
3249
+ if (!file?.name || noExt(file.name) !== noExt(f.target))
3250
+ return `the token at ${where} is ${file?.name ? `${file.name}'s` : "in no file's list"}, not ${f.target}'s; give the target the token's file is named`;
3251
+ }
3252
+ if (f.env !== void 0) {
3253
+ const conf = around.find((x) => /^configurations$/i.test(x.under ?? ""));
3254
+ if (!conf?.name || conf.name.trim() !== f.env.trim())
3255
+ return `the token at ${where} is in ${conf?.name ? `the ${conf.name} configuration` : "no named configuration"}, not ${f.env}; give the env its configuration is named`;
3256
+ }
3257
+ return void 0;
3258
+ }
3259
+ if (isYaml(f.cite.file)) {
3260
+ const y = yamlLine(at);
3261
+ const path = yamlPathAt(lines, f.cite.line);
3262
+ if (y?.key && path && segs.length && keySegments(y.key).at(-1) === segs.at(-1)) {
3263
+ const tail = path.slice(path.length - segs.length);
3264
+ if (path.length < segs.length || !sameSegs(tail, segs))
3265
+ return `${where} sets ${path.join(".")}, not ${f.key}: the key's parents are not the lines above it`;
3266
+ if (value !== void 0 && y.rest && !/^[|>]/.test(y.rest)) {
3267
+ if (!same(yamlScalar(y.rest)))
3268
+ return `${where} sets ${y.key} to something other than the value claimed`;
3269
+ return void 0;
3270
+ }
3271
+ }
3272
+ }
3273
+ if (isProperties(f.cite.file)) {
3274
+ const k = propertiesKeyAt(lines, f.cite.line);
3275
+ if (k && k.split(".").at(-1) === segs.at(-1)) {
3276
+ if (k !== segs.join(".") && !k.endsWith(`.${segs.join(".")}`))
3277
+ return `${where} sets ${k}, not ${f.key}`;
3278
+ if (value !== void 0) {
3279
+ if (!propertiesValues(at, k, lines.slice(f.cite.line)).some(same))
3280
+ return `${where} sets ${k} to something other than the value claimed`;
3281
+ return void 0;
3282
+ }
3283
+ }
3284
+ }
3285
+ if (value === void 0 || value === "")
3286
+ return void 0;
3287
+ const near = [f.cite.line - 1, f.cite.line, f.cite.line + 1].map((n) => lines[n - 1] ?? "");
3288
+ const partLines = (f.cite.with ?? []).map((p) => linesOf2(p.file)?.[p.line - 1] ?? "");
3289
+ if ([...near, ...partLines].some(has))
3290
+ return void 0;
3291
+ const hp = /^([^\s:/]+):(\d{1,5})$/.exec(f.value.trim());
3292
+ if (hp) {
3293
+ const parts = f.cite.with ?? [];
3294
+ const written = (want) => parts.some((p) => {
3295
+ if (p.value.trim() !== want)
3296
+ return false;
3297
+ const l = linesOf2(p.file)?.[p.line - 1] ?? "";
3298
+ return new RegExp(`(^|[^A-Za-z0-9.-])${escape(want)}($|[^A-Za-z0-9.-])`).test(l);
3299
+ });
3300
+ if (written(hp[1]) && written(hp[2]))
3301
+ return void 0;
3302
+ }
3303
+ return `${where} (or the line either side) and its parts don't write the value claimed`;
3304
+ }
3305
+
3306
+ // packages/verify/dist/reachable.js
3307
+ var CODE = /\.(java|kt|kts|scala|groovy|cs|vb|fs|py|rb|go|rs|php|swift|ts|tsx|js|mjs|cjs|dart)$/i;
3308
+ var MODEL_DIR = /(^|\/)(models?|dtos?|payloads?|schemas?|pojos?|beans|viewmodels?)\//i;
3309
+ var MODEL_NAME = /(dto|request|response|payload|model|body)$/i;
3310
+ var MODEL_PART = /[._-](dto|model|schema|payload|request|response)\.[^/.]+$/i;
3311
+ var MAPS_TABLE = /@Entity\b|@Table\b|@Document\b|\[Table\(|__tablename__|models\.Model\b|@Entity\(|\bgorm\.Model\b/;
3312
+ var ROOT_PART = /[._-](controller|resolver|gateway|handlers?|router|routes?|consumer|listener|subscriber|client|publisher|producer|endpoints?)\.[^/.]+$/i;
3313
+ var CLIENT_NAME = /(client|gateway|publisher|producer|sender|feign|proxy|connector)$/i;
3314
+ var CLIENT_DIR = /(^|\/)(clients?|gateways?|integrations?|publishers?|producers?|outbound)\//i;
3315
+ var base = (path) => path.slice(path.lastIndexOf("/") + 1);
3316
+ var stem = (path) => {
3317
+ const b = base(path);
3318
+ const dot = b.indexOf(".");
3319
+ return dot > 0 ? b.slice(0, dot) : b;
3320
+ };
3321
+ function isModelFile(path, text) {
3322
+ if (!CODE.test(path) || readingRank(path) === 5)
3323
+ return false;
3324
+ if (!MODEL_DIR.test(path) && !MODEL_NAME.test(stem(path)) && !MODEL_PART.test(path))
3325
+ return false;
3326
+ return text === void 0 || !MAPS_TABLE.test(text);
3327
+ }
3328
+ var ENTRY_POINT_NAME = /(controller|resource|router|routes?|handlers?|listener|consumer|subscriber|endpoints?|servlet|webhook|resolver)$/i;
3329
+ var ENTRY_POINT_DIR = /(^|\/)(controllers?|routes|routers|handlers|endpoints|listeners|consumers)\//i;
3330
+ var ENTRY_POINT_PART = /[._-](controller|resolver|handlers?|router|routes?|consumer|listener|subscriber|endpoints?)\.[^/.]+$/i;
3331
+ function isEntryPointFile(path) {
3332
+ if (!CODE.test(path) || readingRank(path) === 5 || isModelFile(path))
3333
+ return false;
3334
+ return ENTRY_POINT_NAME.test(stem(path)) || ENTRY_POINT_DIR.test(path) || ENTRY_POINT_PART.test(path);
3335
+ }
3336
+ function isRootFile(path) {
3337
+ if (!CODE.test(path) || readingRank(path) === 5 || isModelFile(path))
3338
+ return false;
3339
+ return readingRank(path) === 2 || isEntryPointFile(path) || ROOT_PART.test(path) || CLIENT_NAME.test(stem(path)) || CLIENT_DIR.test(path);
3340
+ }
3341
+ 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;
3342
+ var IDENT = /[A-Za-z_][A-Za-z0-9_]*/g;
3343
+ function declaredTypes(path, text) {
3344
+ const out = [];
3345
+ const s = stem(path);
3346
+ if (/^[A-Z][A-Za-z0-9_]*$/.test(s))
3347
+ out.push(s);
3348
+ for (const m of text.matchAll(DECLARES)) {
3349
+ const n = m[1] ?? m[2];
3350
+ if (n && !out.includes(n))
3351
+ out.push(n);
3352
+ }
3353
+ return out;
3354
+ }
3355
+ function identifiers(text) {
3356
+ return [...new Set(text.match(IDENT) ?? [])];
3357
+ }
3358
+ 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";
3359
+ function reachableModels(o) {
3360
+ const texts = /* @__PURE__ */ new Map();
3361
+ const textOf = (p) => {
3362
+ if (!texts.has(p))
3363
+ texts.set(p, o.read(p) ?? "");
3364
+ return texts.get(p);
3365
+ };
3366
+ const ordered = readingOrder(o.paths);
3367
+ const models = ordered.filter((p) => isModelFile(p, textOf(p))).sort();
3368
+ const isModel = new Set(models);
3369
+ const byName = /* @__PURE__ */ new Map();
3370
+ const declared = /* @__PURE__ */ new Map();
3371
+ for (const p of models) {
3372
+ const names = declaredTypes(p, textOf(p));
3373
+ declared.set(p, names);
3374
+ for (const n of names)
3375
+ byName.set(n, [...byName.get(n) ?? [], p]);
3376
+ }
3377
+ const known = new Set(o.paths);
3378
+ const roots = [];
3379
+ const addRoot = (p) => {
3380
+ if (known.has(p) && !isModel.has(p) && !roots.includes(p))
3381
+ roots.push(p);
3382
+ };
3383
+ const facts = o.facts ?? [];
3384
+ const entries = o.from === "entries";
3385
+ const calls2 = new Set(facts.filter((f) => f.kind === "call").map((f) => f.id));
3386
+ for (const f of facts)
3387
+ if (f.kind === "entry" || f.kind === "call" && !entries)
3388
+ for (const p of citedFiles(f))
3389
+ addRoot(p);
3390
+ for (const p of ordered)
3391
+ if (entries ? isEntryPointFile(p) : isRootFile(p))
3392
+ addRoot(p);
3393
+ const reached = /* @__PURE__ */ new Map();
3394
+ const queue = [];
3395
+ const reach = (names, from, own = []) => {
3396
+ for (const n of names) {
3397
+ if (own.includes(n))
3398
+ continue;
3399
+ for (const p of byName.get(n) ?? []) {
3400
+ const r = reached.get(p);
3401
+ if (r) {
3402
+ if (r.from === from && !r.types.includes(n))
3403
+ r.types.push(n);
3404
+ continue;
3405
+ }
3406
+ reached.set(p, { path: p, types: [n], from });
3407
+ queue.push(p);
3408
+ }
3409
+ }
3410
+ };
3411
+ for (const p of roots)
3412
+ reach(identifiers(textOf(p)), p);
3413
+ for (const f of facts) {
3414
+ for (const p of citedFiles(f))
3415
+ if (isModel.has(p) && !reached.has(p)) {
3416
+ reached.set(p, { path: p, types: [...(declared.get(p) ?? []).slice(0, 1)], from: f.id });
3417
+ queue.push(p);
3418
+ }
3419
+ if (f.kind === "field" && !(entries && calls2.has(f.owner)))
3420
+ reach(identifiers([f.type ?? "", f.transform === "message type" ? f.name : ""].join(" ")), f.id);
1919
3421
  }
1920
- return { at, strings: [...strings2].map((s) => s.toLowerCase()), paths: [...paths] };
3422
+ const rooted = roots.length > 0 || reached.size > 0;
3423
+ if (!rooted)
3424
+ return {
3425
+ rooted,
3426
+ roots,
3427
+ reached: models.map((p) => ({ path: p, types: declared.get(p) ?? [], from: "" })),
3428
+ notReached: [],
3429
+ models: models.length
3430
+ };
3431
+ for (let i = 0; i < queue.length; i++) {
3432
+ const p = queue[i];
3433
+ reach(identifiers(textOf(p)), p, declared.get(p));
3434
+ }
3435
+ return {
3436
+ rooted,
3437
+ roots,
3438
+ reached: queue.map((p) => reached.get(p)),
3439
+ notReached: models.filter((p) => !reached.has(p)),
3440
+ models: models.length
3441
+ };
1921
3442
  }
1922
- function factsCover(file, c, ix) {
1923
- if ([c.line - 1, c.line, c.line + 1].some((n) => ix.at.has(`${file}:${n}`)))
1924
- return true;
1925
- if (c.kind === "path") {
1926
- const p = `${normPath(c.value)}/`;
1927
- return ix.paths.some((f) => f.includes(p));
3443
+
3444
+ // packages/verify/dist/method.js
3445
+ var HTTP_METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
3446
+ function wordsOf2(line) {
3447
+ 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);
3448
+ }
3449
+ function methodOnLines(method, lines) {
3450
+ const m = method.toLowerCase();
3451
+ return lines.some((l) => wordsOf2(l).includes(m));
3452
+ }
3453
+ var CHAIN_LINES = 8;
3454
+ var CONTINUES = /^\s*\??\./;
3455
+ function chainOf(file, line) {
3456
+ const at = (n) => file?.[n - 1];
3457
+ const cited = at(line);
3458
+ if (cited === void 0)
3459
+ return [];
3460
+ const out = [cited];
3461
+ for (let n = line, k = 0; k < CHAIN_LINES && CONTINUES.test(at(n) ?? ""); k++, n--) {
3462
+ const above = at(n - 1);
3463
+ if (above === void 0)
3464
+ break;
3465
+ out.push(above);
1928
3466
  }
1929
- const v = c.value.toLowerCase().replace(/\/+$/, "");
1930
- return ix.strings.some((s) => s.includes(v));
3467
+ for (let n = line + 1, k = 0; k < CHAIN_LINES && CONTINUES.test(at(n) ?? ""); k++, n++)
3468
+ out.push(at(n));
3469
+ return out;
1931
3470
  }
1932
- var skippedOf = (file, c) => ({
1933
- cite: `${file}:${c.line}`,
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)))
3471
+ function methodUnseenOf(f, lines, factOf) {
3472
+ if (f.kind !== "entry" && f.kind !== "call")
1942
3473
  return void 0;
1943
- let doc;
1944
- try {
1945
- doc = readOpenApiDocument(text);
1946
- } catch {
3474
+ if (!f.method || !HTTP_METHODS.has(f.method.toUpperCase()))
1947
3475
  return void 0;
1948
- }
1949
- if (!doc || !doc.operations.length)
3476
+ const at = (file, line) => lines(file)?.[line - 1];
3477
+ const route = f.kind === "call" && f.from ? factOf?.(f.from) : void 0;
3478
+ const forwards = route?.kind === "entry" && route.method?.toUpperCase() === f.method.toUpperCase();
3479
+ const looked = [
3480
+ ...chainOf(lines(f.cite.file), f.cite.line),
3481
+ at(f.cite.file, f.cite.line + 1),
3482
+ ...(f.cite.with ?? []).map((p) => at(p.file, p.line)),
3483
+ ...forwards ? [at(route.cite.file, route.cite.line), at(route.cite.file, route.cite.line + 1)] : []
3484
+ ].filter((l) => l !== void 0);
3485
+ if (methodOnLines(f.method, looked))
1950
3486
  return void 0;
1951
- const server = (() => {
1952
- const s = doc.servers[0];
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);
3487
+ const cite2 = `${f.cite.file}:${f.cite.line}`;
3488
+ const method = f.method.toUpperCase();
3489
+ return {
3490
+ id: f.id,
3491
+ kind: f.kind,
3492
+ method,
3493
+ cite: cite2,
3494
+ 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`
3495
+ };
3496
+ }
3497
+
3498
+ // packages/verify/dist/verify.js
3499
+ var LINE_KEY_VALUE = /^\s*(?:-\s+)?(?:export\s+)?["']?([A-Za-z0-9_.\-[\]]+)["']?\s*[:=]\s*(.*?)\s*,?\s*$/;
3500
+ var LINE_XML = [
3501
+ /<([A-Za-z_][\w.-]*)>([^<]+)<\/\1>/g,
3502
+ /\b(?:key|name)\s*=\s*"([^"]+)"\s+value\s*=\s*"([^"]*)"/g
3503
+ ];
3504
+ var unquoted = (v) => v.replace(/^["'`]|["'`]$/g, "").trim();
3505
+ function pairsOf(t) {
1963
3506
  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
- });
3507
+ const kv = LINE_KEY_VALUE.exec(t);
3508
+ if (kv)
3509
+ out.push({ key: kv[1], value: unquoted(kv[2]) });
3510
+ for (const re of LINE_XML)
3511
+ for (const m of t.matchAll(re))
3512
+ out.push({ key: m[1], value: unquoted(m[2]) });
3513
+ return out;
3514
+ }
3515
+ function lineSecrets(line) {
3516
+ const t = line.trim();
3517
+ if (!t)
3518
+ return [];
3519
+ const pairs = pairsOf(t);
3520
+ const words = t.split(/[\s"'`=:,;()<>{}[\]/@]+/).filter((w) => w.length >= 6 && credentialLike(w));
3521
+ const holds = redactSecrets(t) !== t || hasSecretShape(t) || quoteHoldsSecret(t) || words.length > 0 || pairs.some((p) => looksLikeSecret(p.key, "x") || p.value && credentialLike(p.value));
3522
+ if (!holds)
3523
+ return [];
3524
+ const literals = [...t.matchAll(/(["'`])((?:(?!\1).){3,})\1/g)].map((m) => m[2]);
3525
+ return [t, t.slice(0, 200), ...pairs.map((p) => p.value), ...literals, ...words].filter((s) => s.length >= 3);
3526
+ }
3527
+ function citesIn(x, out = []) {
3528
+ if (Array.isArray(x))
3529
+ for (const v of x)
3530
+ citesIn(v, out);
3531
+ else if (x && typeof x === "object") {
3532
+ const o = x;
3533
+ if (typeof o.file === "string" && typeof o.line === "number")
3534
+ out.push(o);
3535
+ for (const v of Object.values(o))
3536
+ if (v && typeof v === "object")
3537
+ citesIn(v, out);
1989
3538
  }
1990
3539
  return out;
1991
3540
  }
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})`);
3541
+ function quietFact(f, lineAt) {
3542
+ if (f.kind !== "config")
3543
+ return false;
3544
+ if (looksLikeSecret(f.key, "x") || configSecretField(f))
3545
+ return true;
3546
+ if ([f.value, f.source, f.cite.quote, ...(f.cite.with ?? []).map((w) => w.value)].some((t) => t !== void 0 && (hasSecretShape(t) || credentialLike(t) || redactSecrets(t) !== t)))
3547
+ return true;
3548
+ return lineAt !== void 0 && [f.cite, ...f.cite.with ?? []].some((c) => lineSecrets(lineAt(c.file, c.line) ?? "").length);
3549
+ }
3550
+ function sanitised(f, message, lineAt, quiet) {
3551
+ let out = redactSecrets(message);
3552
+ const texts = /* @__PURE__ */ new Set();
3553
+ for (const c of citesIn(f))
3554
+ for (const n of [c.line - 1, c.line, c.line + 1])
3555
+ for (const s of lineSecrets(lineAt(c.file, n) ?? ""))
3556
+ texts.add(s);
3557
+ for (const t of [...texts].sort((a, b) => b.length - a.length))
3558
+ out = out.split(t).join("<redacted>");
3559
+ out = out.replace(/"([^"]*)"/g, (all2, inner) => lineSecrets(inner).length ? '"<redacted>"' : all2);
3560
+ return quiet ? scrubbed(f, out) : out;
3561
+ }
3562
+ function shownFact(f, quiet, lineAt) {
3563
+ if (quiet)
3564
+ return withoutSecret(f);
3565
+ const cites = citesIn(f).filter((c) => c.quote !== void 0);
3566
+ const bad = (c) => {
3567
+ const q = c.quote;
3568
+ if (lineSecrets(q).length)
3569
+ return true;
3570
+ return [c.line - 1, c.line, c.line + 1].some((n) => lineSecrets(lineAt(c.file, n) ?? "").some((s) => s !== "" && q.includes(s)));
3571
+ };
3572
+ if (!cites.some(bad))
3573
+ return f;
3574
+ const strip = (x) => {
3575
+ if (Array.isArray(x))
3576
+ return x.map(strip);
3577
+ if (!x || typeof x !== "object")
3578
+ return x;
3579
+ const o = Object.fromEntries(Object.entries(x).map(([k, v]) => [k, strip(v)]));
3580
+ const c = x;
3581
+ if (typeof c.file === "string" && typeof c.line === "number" && typeof c.quote === "string" && bad(c))
3582
+ delete o.quote;
3583
+ return o;
3584
+ };
3585
+ return strip(f);
3586
+ }
3587
+ function scrubbed(f, message) {
3588
+ if (f.kind !== "config")
3589
+ return message;
3590
+ const names = new Set([f.key, f.target, f.env, f.cite.file, ...(f.cite.with ?? []).map((w) => w.file)].filter((x) => x !== void 0));
3591
+ const texts = [f.value, f.source, f.cite.quote, ...(f.cite.with ?? []).map((w) => w.value)].flatMap((t) => t === void 0 ? [] : [t, t.trim()]).filter((t) => t.length >= 3 && !names.has(t)).sort((a, b) => b.length - a.length);
3592
+ let out = message;
3593
+ for (const t of texts)
3594
+ out = out.split(t).join("<redacted>");
3595
+ return out;
3596
+ }
3597
+ var asRead = /* @__PURE__ */ new WeakMap();
3598
+ function factAsRead(f) {
3599
+ return asRead.get(f) ?? f;
3600
+ }
3601
+ function withoutSecret(f) {
3602
+ if (f.kind !== "config")
3603
+ return f;
3604
+ const { quote: _q, ...cite2 } = f.cite;
1996
3605
  return {
1997
- path: r.path,
1998
- why: r.why,
1999
- count: n,
2000
- skipped: skipped.slice(0, REVIEWED_HOLDS_SHOWN),
2001
- 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` : ""}`
3606
+ ...f,
3607
+ ...f.value !== void 0 ? { value: "<redacted>" } : {},
3608
+ ...f.source !== void 0 ? { source: "<redacted>" } : {},
3609
+ cite: {
3610
+ ...cite2,
3611
+ ...f.cite.with ? { with: f.cite.with.map((w) => ({ ...w, value: "<redacted>" })) } : {}
3612
+ }
2002
3613
  };
2003
3614
  }
2004
-
2005
- // packages/verify/dist/verify.js
2006
3615
  var FOLLOWED_TYPES = ["event-topic", "mq-queue", "rest", "grpc"];
2007
3616
  function entriesNoFlowFollows(facts, rules = DEFAULT_READ_RULES) {
2008
3617
  const started = new Set(facts.flatMap((f) => f.kind === "flow" ? [f.entry] : []));
@@ -2029,6 +3638,8 @@ var LINES_HELD = 64;
2029
3638
  var SOURCE_EXT = /\.(java|kt|kts|scala|groovy|cs|vb|fs|ts|tsx|js|jsx|mjs|cjs|py|rb|go|rs|php|swift|m|mm|c|cc|cpp|h|hpp|sql|graphql|gql|proto|ya?ml|json|xml|properties|toml|ini|conf|tf|tfvars|hcl|bicep|sh|ps1|bat|cmd|gradle|html?|vue|svelte|cshtml|razor|aspx|jsp|ftl|hbs|cob|cbl|cpy|jcl|avsc|wsdl|xsd|csproj|sln|config)$/i;
2030
3639
  var SOURCE_NAME = /(^|\/)(Dockerfile[^/]*|Makefile|Jenkinsfile|Procfile|Containerfile)$/;
2031
3640
  var LOCKFILE = /(^|\/)(package-lock\.json|npm-shrinkwrap\.json|yarn\.lock|pnpm-lock\.yaml|composer\.lock|Gemfile\.lock|Cargo\.lock|poetry\.lock|go\.sum|packages\.lock\.json)$/;
3641
+ var ENV_FOLDER = /(^|\/)(env|envs|environments?|overlays|stages?)\/[^/]+(?=\/)/gi;
3642
+ var testFileOf = (rules, p) => rules.notProduct.test(p.replace(ENV_FOLDER, "$1$2/_"));
2032
3643
  var NOT_PRODUCT = [
2033
3644
  /(\.|_|-)(test|spec|tests|specs)\.[a-z0-9]+$/i,
2034
3645
  /(Test|Tests|IT|Spec)\.(java|kt|scala|groovy|cs|vb)$/,
@@ -2076,12 +3687,16 @@ var repoModule = (exposes) => {
2076
3687
  const m = /^([^/]+)\/([^/]+)$/.exec(exposes.trim());
2077
3688
  return m ? { repo: m[1], module: m[2] } : void 0;
2078
3689
  };
3690
+ var PLACEHOLDER_KEY = /^\$\{([A-Za-z_][A-Za-z0-9_.-]*)\}$/;
2079
3691
  var routeOrWord = (v) => v.includes("/") ? { kind: "route", value: v } : { kind: "word", value: v };
2080
3692
  function claimsOf(f) {
2081
3693
  switch (f.kind) {
3694
+ // A call whose path is a setting's placeholder a helper puts together is checked apart
3695
+ // (`helperBuildsKey`): its bare key is never a claim, or a settings line would be a call.
2082
3696
  case "entry":
2083
- case "call":
2084
3697
  return [routeOrWord(f.path)];
3698
+ case "call":
3699
+ return f.path.trim() === "/" && /^[a-z][a-z0-9+.-]*:\/\/[^/\s?#]+\/?$/i.test(f.cite.value.trim()) ? [routeOrWord(f.path), { kind: "word", value: f.cite.value.trim() }] : [routeOrWord(f.path)];
2085
3700
  case "store":
2086
3701
  return [
2087
3702
  { kind: "word", value: f.name },
@@ -2117,6 +3732,14 @@ function claimsOf(f) {
2117
3732
  // ADR 0180: the signal the type rests on, as written on its line.
2118
3733
  case "component":
2119
3734
  return [{ kind: "word", value: f.cite.value }];
3735
+ // ADR 0192: the coordinates as the build file writes them on the line (the name, or a
3736
+ // Gradle line's whole `group:name:version`); `buildCoordinatesProblem` reads the rest.
3737
+ case "artifact":
3738
+ case "dependency":
3739
+ return [
3740
+ { kind: "word", value: f.cite.value },
3741
+ { kind: "word", value: f.name }
3742
+ ];
2120
3743
  }
2121
3744
  }
2122
3745
  var sameCommit = (a, b) => a.startsWith(b) || b.startsWith(a);
@@ -2225,7 +3848,8 @@ async function verifyFacts(o) {
2225
3848
  return lines;
2226
3849
  };
2227
3850
  const deriveEnv = { lines: linesOf2, files: listed2 };
2228
- const checkCite = (cite2, claims, label, withHint = true, alsoHolds) => {
3851
+ const lineAt = (file, n) => n >= 1 ? linesOf2(file)?.[n - 1] : void 0;
3852
+ const checkCite = (cite2, claims, label, withHint = true, alsoHolds, quiet = false) => {
2229
3853
  const where = `${cite2.file}:${cite2.line}`;
2230
3854
  if (!insideRepo(cite2.file))
2231
3855
  return {
@@ -2278,7 +3902,7 @@ async function verifyFacts(o) {
2278
3902
  !partsNamePath(near(ls, p.line), p.value))
2279
3903
  return {
2280
3904
  code: "claim-not-on-line",
2281
- message: `${pl} says "${p.value}" is written at ${p.file}:${p.line} (or the line either side), and it isn't`
3905
+ message: quiet ? `${pl} is not written at ${p.file}:${p.line} (or the line either side); cite the line that writes it (its text is not repeated here: it may be a secret)` : `${pl} says "${p.value}" is written at ${p.file}:${p.line} (or the line either side), and it isn't`
2282
3906
  };
2283
3907
  partLines.push(...near(ls, p.line));
2284
3908
  }
@@ -2295,6 +3919,11 @@ async function verifyFacts(o) {
2295
3919
  code: "claim-not-on-line",
2296
3920
  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
3921
  };
3922
+ if (claims && parts.length && isCommentLine(lines[cite2.line - 1] ?? "") && !/(^|\/)_redirects$/.test(cite2.file))
3923
+ return {
3924
+ code: "claim-in-comment",
3925
+ message: `${label} cites ${where}, which is a comment; cite the code that does it`
3926
+ };
2298
3927
  if (claims && !parts.length) {
2299
3928
  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
3929
  if (naming.length && !/(^|\/)_redirects$/.test(cite2.file) && naming.every(isCommentLine))
@@ -2309,7 +3938,7 @@ async function verifyFacts(o) {
2309
3938
  if (!near2.some((l) => quoteMatches(l, cite2.quote)))
2310
3939
  return {
2311
3940
  code: "quote-mismatch",
2312
- message: `${label} quotes "${cite2.quote}", but ${where} reads "${line.trim().slice(0, 200)}"`
3941
+ message: quiet ? `${label}'s quote is not what ${where} (or the line either side) reads; neither is repeated here, as either may hold a secret` : `${label} quotes "${cite2.quote}", but ${where} reads "${line.trim().slice(0, 200)}"`
2313
3942
  };
2314
3943
  }
2315
3944
  return void 0;
@@ -2328,6 +3957,8 @@ async function verifyFacts(o) {
2328
3957
  };
2329
3958
  const estate = o.estate ? new Set(o.estate.components.map(factIdPart)) : void 0;
2330
3959
  const serves2 = facts.some((f) => f.kind === "entry");
3960
+ const moduleOf = /* @__PURE__ */ new Map();
3961
+ const placedFrom = /* @__PURE__ */ new Map();
2331
3962
  const repoComponents = new Map(Object.entries(o.estate?.repoComponents ?? {}).map(([r, cs]) => [factIdPart(r), new Set(cs.map(factIdPart))]));
2332
3963
  for (const f of facts) {
2333
3964
  const label = `${f.kind} ${f.id}`;
@@ -2342,7 +3973,21 @@ async function verifyFacts(o) {
2342
3973
  problem(f, "wrong-commit", `${label} was read at ${f.commit}, not at ${o.commit}; read it again`);
2343
3974
  continue;
2344
3975
  }
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) : void 0));
3976
+ 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,
3977
+ // beta.24): a helper puts the key together (a `@ConfigurationProperties` prefix, a
3978
+ // map field, the name passed to a lookup). The cited line is code naming the key's
3979
+ // last segment, and one file among the parts proves the rest of the key nests so.
3980
+ f.kind === "call" && PLACEHOLDER_KEY.test(f.path.trim()) && helperBuildsKey(PLACEHOLDER_KEY.exec(f.path.trim())[1], f.cite, linesOf2) : void 0, quietFact(f, lineAt)));
3981
+ if (f.kind === "config" && !found.has(f.id)) {
3982
+ const bad = configLineProblem(f, linesOf2, listed2, rules.gatewayBundleFolders);
3983
+ if (bad)
3984
+ problem(f, "claim-not-on-line", `${label}: ${bad}`);
3985
+ }
3986
+ if (f.kind === "config") {
3987
+ const field = configSecretField(f);
3988
+ if (field)
3989
+ problem(f, "secret-value", `${label}: "${f.key}" carries a secret in its ${field}; cite the line that names the setting and give its source (env:NAME, vault:path), never its value`);
3990
+ }
2346
3991
  if (f.kind === "entry" && f.authCite)
2347
3992
  add(f, checkCite({ ...f.authCite }, [{ kind: "word", value: f.authCite.value }], `${label} authCite${f.auth ? ` (auth ${f.auth})` : ""}`, false));
2348
3993
  if (f.kind === "entry" && f.authCite && f.auth) {
@@ -2433,6 +4078,32 @@ async function verifyFacts(o) {
2433
4078
  if (f.version !== void 0)
2434
4079
  add(f, checkCite(f.cite, [{ kind: "word", value: f.version }], `${label} version`, false));
2435
4080
  }
4081
+ const own = o.estate?.repoComponent?.[f.repo];
4082
+ if (own !== void 0 && o.estate) {
4083
+ const to = placedComponentOf(f, {
4084
+ component: own,
4085
+ modules: o.estate.modules?.[f.repo],
4086
+ components: o.estate.components,
4087
+ prototype: o.estate.prototypes?.includes(f.repo)
4088
+ });
4089
+ const top = f.cite?.file?.split("/")[0];
4090
+ if (to !== void 0 && top !== void 0 && isBuildModuleDir(top, linesOf2)) {
4091
+ moduleOf.set(f.id, to);
4092
+ placedFrom.set(f.id, f.component);
4093
+ }
4094
+ }
4095
+ if ((f.kind === "artifact" || f.kind === "dependency") && !found.has(f.id)) {
4096
+ const mod = buildModuleOf(f, linesOf2, o.estate?.modules?.[f.repo] ?? [], o.estate?.repoComponent?.[f.repo]);
4097
+ const bad = buildCoordinatesProblem(f, linesOf2, listed2()) ?? buildModuleProblem(f, mod);
4098
+ if (bad)
4099
+ problem(f, "build-coordinates", bad);
4100
+ else {
4101
+ if (mod?.from === "manifest" && mod.component && f.component === void 0)
4102
+ moduleOf.set(f.id, mod.component);
4103
+ if (f.version !== void 0 && !isVersionCatalogFile(f.cite.file))
4104
+ add(f, checkCite(f.cite, [{ kind: "word", value: f.version }], `${label} version`, false));
4105
+ }
4106
+ }
2436
4107
  if (f.kind === "flow") {
2437
4108
  f.steps.forEach((s, i) => add(f, checkCite(s.cite, stepClaims(s.kind, s.cite.value), `${label} step ${i + 1}`)));
2438
4109
  f.errors.forEach((e, i) => add(f, checkCite(e.cite, [routeOrWord(e.cite.value)], `${label} error ${i + 1}`)));
@@ -2478,11 +4149,17 @@ async function verifyFacts(o) {
2478
4149
  }
2479
4150
  const rejected = /* @__PURE__ */ new Map();
2480
4151
  for (const f of facts) {
2481
- const ps = found.get(f.id);
4152
+ let ps = found.get(f.id);
2482
4153
  if (!ps?.length)
2483
4154
  continue;
2484
- rejected.set(f.id, ps.length === 1 ? { fact: f, ...ps[0] } : {
2485
- fact: f,
4155
+ const isOther = other.has(f.id);
4156
+ const quiet = ps.some((p) => p.code === "secret-value") || quietFact(f, isOther ? void 0 : lineAt);
4157
+ ps = ps.map((p) => ({ ...p, message: sanitised(f, p.message, lineAt, quiet) }));
4158
+ const shown = isOther ? f.kind === "config" && configSecretField(f) || citesIn(f).some((c) => c.quote && lineSecrets(c.quote).length) ? withoutSecret(f) : f : shownFact(f, quiet, lineAt);
4159
+ if (isOther && shown !== f)
4160
+ asRead.set(shown, f);
4161
+ rejected.set(f.id, ps.length === 1 ? { fact: shown, ...ps[0] } : {
4162
+ fact: shown,
2486
4163
  code: ps[0].code,
2487
4164
  message: ps.map((p, i) => `(${i + 1}) ${p.message}`).join(" "),
2488
4165
  problems: ps
@@ -2495,10 +4172,11 @@ async function verifyFacts(o) {
2495
4172
  continue;
2496
4173
  const r = refsOf(f).find((x) => rejected.has(x.id));
2497
4174
  if (r) {
4175
+ const quiet = quietFact(f, lineAt);
2498
4176
  rejected.set(f.id, {
2499
- fact: f,
4177
+ fact: shownFact(f, quiet, lineAt),
2500
4178
  code: "ref-rejected",
2501
- message: `${f.kind} ${f.id} names ${r.field} "${r.id}", which was rejected (${rejected.get(r.id).code})`
4179
+ message: sanitised(f, `${f.kind} ${f.id} names ${r.field} "${r.id}", which was rejected (${rejected.get(r.id).code})`, lineAt, quiet)
2502
4180
  });
2503
4181
  changed = true;
2504
4182
  }
@@ -2532,7 +4210,13 @@ async function verifyFacts(o) {
2532
4210
  const accepted = facts.filter((f) => !rejected.has(f.id)).map((f) => {
2533
4211
  o.room?.();
2534
4212
  const verified = f.by === "person" && f.verified !== "none" ? f.verified : "line";
2535
- const base2 = { ...f, verified, cite: fixQuote(f.cite) };
4213
+ const module = moduleOf.get(f.id);
4214
+ const base2 = {
4215
+ ...f,
4216
+ ...module !== void 0 ? { component: module } : {},
4217
+ verified,
4218
+ cite: fixQuote(f.cite)
4219
+ };
2536
4220
  if (base2.kind === "entry" && base2.auth !== void 0 && !base2.authCite && f.by !== "person")
2537
4221
  authUncited.push({
2538
4222
  id: base2.id,
@@ -2553,17 +4237,41 @@ async function verifyFacts(o) {
2553
4237
  const excludeRes = (o.exclude ?? []).map(globToRegExp);
2554
4238
  const sources = [];
2555
4239
  const excluded = [];
4240
+ const secrets = [];
2556
4241
  for (const p of o.source.list()) {
2557
4242
  o.room?.();
2558
- if (!isSourceFile(p, "", void 0, rules) || tooBigToRead(o.source, p))
4243
+ if (isSecretPath(p)) {
4244
+ if (insideRepo(p) && isConfigFile(p) && !testFileOf(rules, p) && !tooBigToRead(o.source, p)) {
4245
+ const text = o.source.read(p);
4246
+ const ls2 = text === void 0 ? void 0 : text.replace(/\r\n?/g, "\n").split("\n");
4247
+ if (ls2 && !binaryLines(ls2))
4248
+ secrets.push(...liveSecretsIn(p, ls2));
4249
+ }
4250
+ continue;
4251
+ }
4252
+ const scanOnly = () => {
4253
+ if (!insideRepo(p) || !isConfigFile(p) || LOCKFILE.test(p) || testFileOf(rules, p) || tooBigToRead(o.source, p))
4254
+ return;
4255
+ const ls2 = readLines(p);
4256
+ if (ls2 && !binaryLines(ls2))
4257
+ secrets.push(...liveSecretsIn(p, ls2));
4258
+ };
4259
+ if (!isSourceFile(p, "", void 0, rules) || tooBigToRead(o.source, p)) {
4260
+ scanOnly();
2559
4261
  continue;
4262
+ }
2560
4263
  const ls = readLines(p) ?? [""];
2561
- if (!isSourceFile(p, ls[0] ?? "", ls, rules))
4264
+ if (!isSourceFile(p, ls[0] ?? "", ls, rules)) {
4265
+ if (isConfigFile(p) && !LOCKFILE.test(p) && !testFileOf(rules, p) && !binaryLines(ls))
4266
+ secrets.push(...liveSecretsIn(p, ls));
2562
4267
  continue;
4268
+ }
2563
4269
  if (excludeRes.some((re) => re.test(p)))
2564
4270
  excluded.push(p);
2565
- else
4271
+ else {
2566
4272
  sources.push(p);
4273
+ secrets.push(...liveSecretsIn(p, ls));
4274
+ }
2567
4275
  }
2568
4276
  const touched = new Set(o.routed ?? []);
2569
4277
  for (const f of accepted)
@@ -2664,6 +4372,14 @@ async function verifyFacts(o) {
2664
4372
  const held = files.flatMap(skippedIn);
2665
4373
  return held.length ? [reviewedHoldsOf(entry, held)] : [];
2666
4374
  });
4375
+ const namedPoms = [...touched].some((p) => isBuildFile(p)) ? pomFilesNamed(listed2(), linesOf2) : void 0;
4376
+ const placed = accepted.filter((f) => placedFrom.has(f.id)).map((f) => ({
4377
+ id: f.id,
4378
+ named: placedFrom.get(f.id),
4379
+ component: f.component,
4380
+ cite: `${f.cite.file}:${f.cite.line}`
4381
+ })).sort((a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0);
4382
+ const unrecorded = buildUnrecorded([...touched].filter((p) => isBuildFileIn(p, namedPoms) && insideRepo(p) && !isSecretPath(p)), (p) => linesOf2(p), accepted, listed2());
2667
4383
  return {
2668
4384
  accepted,
2669
4385
  // a rejected fact goes back as it was read, at its own commit, even one that was carried
@@ -2677,6 +4393,7 @@ async function verifyFacts(o) {
2677
4393
  ratio
2678
4394
  },
2679
4395
  redacted,
4396
+ secrets: secrets.sort((a, b) => a.file < b.file ? -1 : a.file > b.file ? 1 : a.line - b.line),
2680
4397
  quotesDropped,
2681
4398
  carried: accepted.flatMap((f) => carriedFrom.has(f.id) ? [{ id: f.id, from: carriedFrom.get(f.id) }] : []),
2682
4399
  corrections: { applied: corrected.applied, stale: corrected.stale },
@@ -2689,12 +4406,14 @@ async function verifyFacts(o) {
2689
4406
  skipped,
2690
4407
  reviewedHolds,
2691
4408
  specOpsUncovered,
2692
- frameworkGaps: frameworkGaps(accepted, rules.frameworks)
4409
+ frameworkGaps: frameworkGaps(accepted, rules.frameworks),
4410
+ ...unrecorded.length ? { buildUnrecorded: unrecorded } : {},
4411
+ ...placed.length ? { componentsPlaced: placed } : {}
2693
4412
  };
2694
4413
  }
2695
4414
 
2696
4415
  // packages/verify/dist/batches.js
2697
- var BUILD = /(^|\/)(pom\.xml|build\.gradle(\.kts)?|settings\.gradle(\.kts)?|package\.json|go\.mod|Cargo\.toml|pyproject\.toml|setup\.py|requirements[^/]*\.txt|Gemfile|[^/]+\.gemspec|composer\.json|[^/]+\.(csproj|sln|tf|tfvars|bicep|hcl)|Dockerfile[^/]*|Containerfile|Jenkinsfile|Makefile|Procfile|(docker-)?compose[^/]*\.ya?ml|Chart\.yaml|values[^/]*\.ya?ml|azure-pipelines[^/]*\.ya?ml|\.gitlab-ci\.yml|bitbucket-pipelines\.yml|serverless\.ya?ml|template\.ya?ml|manifest\.ya?ml)$/;
4416
+ var BUILD = /(^|\/)(pom\.xml|[^/]+[-_.]pom\.xml|[^/]+\.pom|gradle\/[\w-]+\.versions\.toml|build\.gradle(\.kts)?|settings\.gradle(\.kts)?|package\.json|go\.mod|Cargo\.toml|pyproject\.toml|setup\.py|requirements[^/]*\.txt|Gemfile|[^/]+\.gemspec|composer\.json|[^/]+\.(csproj|sln|tf|tfvars|bicep|hcl)|Dockerfile[^/]*|Containerfile|Jenkinsfile|Makefile|Procfile|(docker-)?compose[^/]*\.ya?ml|Chart\.yaml|values[^/]*\.ya?ml|azure-pipelines[^/]*\.ya?ml|\.gitlab-ci\.yml|bitbucket-pipelines\.yml|serverless\.ya?ml|template\.ya?ml|manifest\.ya?ml)$/;
2698
4417
  var DEPLOY_DIR = /(^|\/)(\.github\/workflows|\.circleci|k8s|kubernetes|helm|charts|deploy|deployment|deployments|manifests|infra|terraform|pipelines?)\//;
2699
4418
  var CONFIG = /(^|\/)((application|bootstrap)[^/]*\.(ya?ml|properties)|appsettings[^/]*\.json|[^/]+\.(properties|conf|ini|toml)|web\.config|config\/[^/]+\.(ya?ml|json))$/;
2700
4419
  var ENTRY_NAME = /(^|[._-])(main|app|application|server|program|startup|index|lambda|handler|function|cli)$|(controller|resource|router|routes?|handlers?|listener|consumer|subscriber|endpoints?|api|job|scheduler|worker|webhook|servlet|page|screen|view)$/i;
@@ -2953,7 +4672,7 @@ var BUILD_FILE = /^(pom\.xml|build\.gradle(\.kts)?|settings\.gradle(\.kts)?|pack
2953
4672
  var AGGREGATOR = /^(pom\.xml|settings\.gradle(\.kts)?|package\.json|pnpm-workspace\.yaml|lerna\.json|Cargo\.toml|go\.work)$/;
2954
4673
  var byPath = (a, b) => a < b ? -1 : a > b ? 1 : 0;
2955
4674
  var nameOf = (path) => path.slice(path.lastIndexOf("/") + 1);
2956
- var dirOf = (path) => path.includes("/") ? path.slice(0, path.lastIndexOf("/")) : "";
4675
+ var dirOf2 = (path) => path.includes("/") ? path.slice(0, path.lastIndexOf("/")) : "";
2957
4676
  var under = (path, dir) => !dir || path.startsWith(`${dir}/`);
2958
4677
  var quoted = (s) => [...s.matchAll(/["']([^"'\n]+)["']/g)].map((m) => m[1]);
2959
4678
  var clean = (m) => m.trim().replace(/^\.\//, "").replace(/\/pom\.xml$/, "").replace(/\/+$/, "");
@@ -2967,7 +4686,7 @@ function json(text) {
2967
4686
  var strings = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
2968
4687
  function buildModules(path, text) {
2969
4688
  const name = nameOf(path);
2970
- const dir = dirOf(path);
4689
+ const dir = dirOf2(path);
2971
4690
  let found = [];
2972
4691
  if (name === "pom.xml")
2973
4692
  found = [...text.matchAll(/<module>\s*([^<]+?)\s*<\/module>/g)].map((m) => m[1]);
@@ -3023,11 +4742,11 @@ function packageRoots(paths, inits, read) {
3023
4742
  let readCount = 0;
3024
4743
  for (const p of paths) {
3025
4744
  if (/\.py$/i.test(p)) {
3026
- let d = dirOf(p);
4745
+ let d = dirOf2(p);
3027
4746
  let top;
3028
4747
  while (d && inits.has(d)) {
3029
4748
  top = d;
3030
- d = dirOf(d);
4749
+ d = dirOf2(d);
3031
4750
  }
3032
4751
  if (top)
3033
4752
  roots.add(nameOf(top).toLowerCase());
@@ -3046,7 +4765,7 @@ function vendoredProjects(all2, read) {
3046
4765
  const licenses = /* @__PURE__ */ new Map();
3047
4766
  const builds = /* @__PURE__ */ new Map();
3048
4767
  for (const p of files) {
3049
- const d = dirOf(p);
4768
+ const d = dirOf2(p);
3050
4769
  if (LICENSE_FILE.test(nameOf(p)) && !licenses.has(d))
3051
4770
  licenses.set(d, p);
3052
4771
  if (BUILD_FILE.test(nameOf(p)))
@@ -3057,7 +4776,7 @@ function vendoredProjects(all2, read) {
3057
4776
  for (const p of files)
3058
4777
  if (AGGREGATOR.test(nameOf(p)))
3059
4778
  for (const m of buildModules(p, read(p) ?? ""))
3060
- modules.push({ from: dirOf(p), re: globToRegExp(m) });
4779
+ modules.push({ from: dirOf2(p), re: globToRegExp(m) });
3061
4780
  }
3062
4781
  const included = (dir) => modules.some((m) => m.from !== dir && under(dir, m.from) && m.re.test(dir));
3063
4782
  const nested = [];
@@ -3077,7 +4796,7 @@ function vendoredProjects(all2, read) {
3077
4796
  }
3078
4797
  const out = [...nested];
3079
4798
  if (copied.length) {
3080
- const inits = new Set(files.filter((p) => nameOf(p) === "__init__.py").map(dirOf));
4799
+ const inits = new Set(files.filter((p) => nameOf(p) === "__init__.py").map(dirOf2));
3081
4800
  const apart = [...copied, ...nested.map((n) => n.dir)];
3082
4801
  const text = read ?? (() => void 0);
3083
4802
  const mine = packageRoots(files.filter((p) => !apart.some((d) => under(p, d))), inits, text);
@@ -3238,11 +4957,11 @@ function unitsOf(dir, fs, room) {
3238
4957
  const children = /* @__PURE__ */ new Map();
3239
4958
  for (const f of fs) {
3240
4959
  const rest = f.path.slice(prefix.length);
3241
- const slash = rest.indexOf("/");
3242
- if (slash < 0)
4960
+ const slash2 = rest.indexOf("/");
4961
+ if (slash2 < 0)
3243
4962
  direct.push(f);
3244
4963
  else {
3245
- const child = prefix + rest.slice(0, slash);
4964
+ const child = prefix + rest.slice(0, slash2);
3246
4965
  children.set(child, [...children.get(child) ?? [], f]);
3247
4966
  }
3248
4967
  }
@@ -3259,11 +4978,11 @@ function groupUnits(dir, fs, room, holds) {
3259
4978
  const children = /* @__PURE__ */ new Map();
3260
4979
  for (const f of fs) {
3261
4980
  const rest = f.path.slice(prefix.length);
3262
- const slash = rest.indexOf("/");
3263
- if (slash < 0)
4981
+ const slash2 = rest.indexOf("/");
4982
+ if (slash2 < 0)
3264
4983
  direct.push(f);
3265
4984
  else {
3266
- const child = prefix + rest.slice(0, slash);
4985
+ const child = prefix + rest.slice(0, slash2);
3267
4986
  children.set(child, [...children.get(child) ?? [], f]);
3268
4987
  }
3269
4988
  }
@@ -3891,7 +5610,8 @@ function lineLegend(marks) {
3891
5610
  }
3892
5611
  return "modify";
3893
5612
  }
3894
- function changeView(records2, change, flows, known = []) {
5613
+ function changeView(records2, change, flows, known = [], retired = []) {
5614
+ const gone = new Set(retired);
3895
5615
  const c = new Catalog(records2);
3896
5616
  const inSpecs = new Set(known);
3897
5617
  const isKnown = (id) => c.components.has(id) || c.isSystem(id) || inSpecs.has(id);
@@ -3928,6 +5648,9 @@ function changeView(records2, change, flows, known = []) {
3928
5648
  }
3929
5649
  }
3930
5650
  }
5651
+ for (const id of gone)
5652
+ if (comps.has(id))
5653
+ legends.set(id, "retire");
3931
5654
  const withMark = (id) => {
3932
5655
  const l = legends.get(id);
3933
5656
  return l ? { legend: l } : {};
@@ -4446,8 +6169,25 @@ var LENS_KINDS = {
4446
6169
  infrastructure: /* @__PURE__ */ new Set(["estate", "system", "repo", "component", "deployment", "environment"])
4447
6170
  };
4448
6171
  var LENS_EDGES = {
4449
- architecture: /* @__PURE__ */ new Set(["calls", "publishes", "subscribes", "uses", "reads", "writes"]),
4450
- repo: /* @__PURE__ */ new Set(["calls", "publishes", "subscribes", "uses", "reads", "writes", "references"]),
6172
+ architecture: /* @__PURE__ */ new Set([
6173
+ "calls",
6174
+ "publishes",
6175
+ "subscribes",
6176
+ "uses",
6177
+ "depends-on",
6178
+ "reads",
6179
+ "writes"
6180
+ ]),
6181
+ repo: /* @__PURE__ */ new Set([
6182
+ "calls",
6183
+ "publishes",
6184
+ "subscribes",
6185
+ "uses",
6186
+ "depends-on",
6187
+ "reads",
6188
+ "writes",
6189
+ "references"
6190
+ ]),
4451
6191
  data: /* @__PURE__ */ new Set(["reads", "writes", "references"]),
4452
6192
  integration: /* @__PURE__ */ new Set(["calls", "publishes", "subscribes"]),
4453
6193
  infrastructure: /* @__PURE__ */ new Set(["deployed-to"])
@@ -4510,30 +6250,71 @@ var HOW_OF_FLAG = {
4510
6250
  "joined-by-name": "named",
4511
6251
  "joined-by-repo": "repo",
4512
6252
  "joined-by-host": "host",
6253
+ // beta.24: a call whose host nothing resolves, by the one proxy BasePath its path starts with.
6254
+ [JOINED_BY_BASE_PATH]: "base-path",
4513
6255
  "declared-caller": "declared",
4514
6256
  // ADR 0162 §6 (F8): a topic or queue the profile names as an outside system's: a person's word.
4515
6257
  [DECLARED_TOPIC]: "declared",
4516
6258
  // ADR 0160 (O3): answered by an entry of another team's shared map.
4517
6259
  [JOINED_TO_SHARED_MAP]: "shared"
4518
6260
  };
6261
+ var NOT_VERIFYING_FLAGS = /* @__PURE__ */ new Set([
6262
+ ...JOIN_GUESS_FLAGS,
6263
+ JOINED_BY_PERSON,
6264
+ JOINED_BY_AI,
6265
+ JOINED_BY_PATH_OVERLAP
6266
+ ]);
6267
+ var ALSO_OF_FLAG = {
6268
+ ...HOW_OF_FLAG,
6269
+ [JOINED_BY_PATH_OVERLAP]: "path"
6270
+ };
4519
6271
  function joinHow(i) {
4520
- for (const f of i.flags ?? [])
6272
+ const flags = i.flags ?? [];
6273
+ const topic = i.via === "event-bus" || i.via === "mq";
6274
+ if (i.confidence === "verified") {
6275
+ for (const f of flags)
6276
+ if (HOW_OF_FLAG[f] && !NOT_VERIFYING_FLAGS.has(f))
6277
+ return HOW_OF_FLAG[f];
6278
+ if (topic)
6279
+ return "topic";
6280
+ }
6281
+ for (const f of flags)
4521
6282
  if (HOW_OF_FLAG[f])
4522
6283
  return HOW_OF_FLAG[f];
4523
- if (i.via === "event-bus" || i.via === "mq")
6284
+ if (topic)
4524
6285
  return "topic";
4525
6286
  return "unknown";
4526
6287
  }
6288
+ var GUESS_HOWS = new Set([...NOT_VERIFYING_FLAGS].map((f) => HOW_OF_FLAG[f]).filter(Boolean));
6289
+ function alsoOf(i, how) {
6290
+ if (i.confidence !== "verified" || GUESS_HOWS.has(how))
6291
+ return [];
6292
+ const flags = i.flags ?? [];
6293
+ const byBase = how !== "base-path" && flags.includes(JOINED_BY_BASE_PATH);
6294
+ return [
6295
+ ...new Set(flags.flatMap((f) => {
6296
+ const also = byBase && f === JOINED_BY_PATH ? "base-path" : ALSO_OF_FLAG[f];
6297
+ return NOT_VERIFYING_FLAGS.has(f) && also && also !== how ? [also] : [];
6298
+ }))
6299
+ ];
6300
+ }
4527
6301
  function joinOf(i) {
4528
6302
  const side = (s) => evidenceOf(i.evidence.filter((e) => e.side === s));
4529
6303
  const sided = /* @__PURE__ */ new Set(["caller", "callee", "gateway"]);
6304
+ const how = joinHow(i);
6305
+ const also = alsoOf(i, how);
4530
6306
  return {
4531
6307
  interface: i.id,
4532
6308
  from: i.from,
4533
6309
  to: i.to,
4534
- how: joinHow(i),
6310
+ how,
4535
6311
  gateway: i.via === "gateway",
4536
- verified: i.confidence === "verified",
6312
+ // A link is verified when one of its calls is (ADR 0135 section 5): its how is that call's,
6313
+ // and the guesses its other calls rest on are `also`, never the reason. One with no how but
6314
+ // a guess has no call that wasn't guessed to show, so it is never shown verified beside the
6315
+ // guess's words (beta.24).
6316
+ verified: i.confidence === "verified" && !GUESS_HOWS.has(how),
6317
+ ...also.length ? { also } : {},
4537
6318
  ...i.method ? { method: i.method } : {},
4538
6319
  ...i.normalizedPath ? { path: i.normalizedPath } : {},
4539
6320
  caller: side("caller"),
@@ -4565,12 +6346,12 @@ function sharedOf(i) {
4565
6346
  }
4566
6347
  };
4567
6348
  }
4568
- function mergeJoins(a, b) {
6349
+ function mergeJoins(a, b, cap = MAX_JOINS) {
4569
6350
  const by = new Map(a.map((j) => [j.interface, j]));
4570
6351
  for (const j of b)
4571
6352
  if (!by.has(j.interface))
4572
6353
  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, MAX_JOINS);
6354
+ return [...by.values()].sort((x, y) => x.interface < y.interface ? -1 : x.interface > y.interface ? 1 : 0).slice(0, cap);
4574
6355
  }
4575
6356
  var props = (o) => {
4576
6357
  const out = {};
@@ -4586,7 +6367,50 @@ var props = (o) => {
4586
6367
  return out;
4587
6368
  };
4588
6369
  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 buildEstate(records2) {
6370
+ function dependencyJoin(l) {
6371
+ const lines = (end) => end.lines.map((at) => ({ source: "code", repo: end.repo, at }));
6372
+ const facts = l.facts?.length ? l.facts : [l.from];
6373
+ const caller = [];
6374
+ for (const f of facts)
6375
+ for (const e of lines(f))
6376
+ if (!caller.some((x) => x.repo === e.repo && x.at === e.at))
6377
+ caller.push(e);
6378
+ const callee = [];
6379
+ for (const p of l.published?.length ? l.published : [l.to])
6380
+ for (const e of lines(p))
6381
+ if (!callee.some((x) => x.repo === e.repo && x.at === e.at))
6382
+ callee.push(e);
6383
+ return {
6384
+ interface: dependencyLinkId(l),
6385
+ from: l.from.component,
6386
+ to: l.to.component,
6387
+ how: "coordinates",
6388
+ gateway: false,
6389
+ // code at both ends, each claim checked on its line, and nobody had to guess
6390
+ verified: true,
6391
+ caller,
6392
+ callee,
6393
+ hops: [],
6394
+ other: [],
6395
+ dependency: {
6396
+ group: l.group,
6397
+ name: l.name,
6398
+ ...l.version ? { version: l.version } : {},
6399
+ ...l.scope ? { scope: l.scope } : {},
6400
+ facts: facts.map((f) => ({
6401
+ repo: f.repo,
6402
+ fact: f.fact,
6403
+ at: f.at,
6404
+ lines: f.lines,
6405
+ ...f.group !== void 0 ? { group: f.group } : {},
6406
+ ...f.name !== void 0 ? { name: f.name } : {},
6407
+ ...f.version !== void 0 ? { version: f.version } : {},
6408
+ ...f.scope !== void 0 ? { scope: f.scope } : {}
6409
+ }))
6410
+ }
6411
+ };
6412
+ }
6413
+ function buildEstate(records2, o = {}) {
4590
6414
  const nodes = /* @__PURE__ */ new Map();
4591
6415
  const atoms = [];
4592
6416
  const add = (n) => {
@@ -4897,6 +6721,19 @@ function buildEstate(records2) {
4897
6721
  evidence: evidenceOf(c.evidence),
4898
6722
  gaps: recordGaps(c)
4899
6723
  });
6724
+ for (const l of o.dependsOn ?? []) {
6725
+ if (!components.has(l.from.component) || !components.has(l.to.component))
6726
+ continue;
6727
+ const join2 = dependencyJoin(l);
6728
+ atoms.push({
6729
+ from: `component:${l.from.component}`,
6730
+ to: `component:${l.to.component}`,
6731
+ type: "depends-on",
6732
+ evidence: mergeEvidence(join2.caller.slice(0, 1), join2.callee.slice(0, 1)),
6733
+ gaps: [],
6734
+ join: join2
6735
+ });
6736
+ }
4900
6737
  for (const t of tables) {
4901
6738
  const ev = evidenceOf(t.evidence);
4902
6739
  const part = (ref) => {
@@ -5049,7 +6886,7 @@ function need(est, lens, id) {
5049
6886
  if (!est.visible.get(lens).has(id))
5050
6887
  throw new NoSuchNode(`There is no node ${id} in the ${lens} lens.`);
5051
6888
  }
5052
- function merge(mapped) {
6889
+ function merge(mapped, cap = MAX_JOINS) {
5053
6890
  const by = /* @__PURE__ */ new Map();
5054
6891
  for (const { from, to, atom } of mapped) {
5055
6892
  const id = `${atom.type}:${from}>${to}`;
@@ -5071,7 +6908,7 @@ function merge(mapped) {
5071
6908
  continue;
5072
6909
  }
5073
6910
  if (atom.join)
5074
- e.joins = mergeJoins(e.joins ?? [], [atom.join]);
6911
+ e.joins = mergeJoins(e.joins ?? [], [atom.join], cap);
5075
6912
  e.count++;
5076
6913
  if (atom.sync && e.sync !== atom.sync)
5077
6914
  e.sync = "mixed";
@@ -5160,7 +6997,7 @@ function nodeView(est, id, o) {
5160
6997
  continue;
5161
6998
  mapped.push({ from, to, atom });
5162
6999
  }
5163
- let edges = merge(mapped);
7000
+ let edges = merge(mapped, o.everyJoin ? Infinity : MAX_JOINS);
5164
7001
  let hidden = 0;
5165
7002
  if (!o.all)
5166
7003
  ({ edges, hidden } = reduceUses(edges));
@@ -5205,7 +7042,7 @@ function focusView(est, id, o) {
5205
7042
  node: toNode(est, lens, id),
5206
7043
  path: ancestors(est, id).map((n) => toNode(est, lens, n)),
5207
7044
  neighbours: [...near].sort().map((n) => toNode(est, lens, n)),
5208
- edges: merge(ends.filter((e) => set.has(e.from) && set.has(e.to)))
7045
+ edges: merge(ends.filter((e) => set.has(e.from) && set.has(e.to)), o.everyJoin ? Infinity : MAX_JOINS)
5209
7046
  };
5210
7047
  }
5211
7048
 
@@ -6096,6 +7933,7 @@ function houseImportsUntaught(source, o) {
6096
7933
  export {
6097
7934
  insideRepo,
6098
7935
  dirSource,
7936
+ isBuildFile,
6099
7937
  correctionFor,
6100
7938
  outsidePairingFor,
6101
7939
  correctedFact,
@@ -6106,6 +7944,7 @@ export {
6106
7944
  frameworkGaps,
6107
7945
  frameworksToLearn,
6108
7946
  readRulesOf,
7947
+ keyIsSecret,
6109
7948
  lineRangeOf,
6110
7949
  parseReviewed,
6111
7950
  readingRank,
@@ -6118,6 +7957,7 @@ export {
6118
7957
  isEntryPointFile,
6119
7958
  NOT_REACHED_WHY,
6120
7959
  reachableModels,
7960
+ factAsRead,
6121
7961
  sameCommit,
6122
7962
  staleMessage,
6123
7963
  verifyFacts,