@maycombhq/atticus 2.0.0-beta.10 → 2.0.0-beta.11

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 (232) hide show
  1. package/dist/bin.js +3 -3
  2. package/dist/{chunk-GZ4TKR3Q.js → chunk-23VFQHFQ.js} +33 -134
  3. package/dist/{chunk-VKMTFIWS.js → chunk-26DBAGOP.js} +18 -18
  4. package/dist/{chunk-PKCMRPPB.js → chunk-27EDZN52.js} +33 -27
  5. package/dist/{chunk-AJJK7GLO.js → chunk-2K2ZEJVR.js} +3 -3
  6. package/dist/{chunk-XRO65C7V.js → chunk-3DDJLI7N.js} +8 -6
  7. package/dist/{chunk-XQ3YIV5R.js → chunk-3LU6YCSQ.js} +6 -6
  8. package/dist/{chunk-XTVDAHH2.js → chunk-3WU7LVTL.js} +5 -5
  9. package/dist/{chunk-6GNS32SI.js → chunk-4AYZQ3SY.js} +4 -4
  10. package/dist/{chunk-6VBXAGJX.js → chunk-4ONORLK5.js} +14 -14
  11. package/dist/{chunk-7TGYNOXD.js → chunk-4URR24DD.js} +7 -7
  12. package/dist/{chunk-CIUHAHM6.js → chunk-4UZJOQYK.js} +8 -8
  13. package/dist/chunk-4Y4FY34K.js +34 -0
  14. package/dist/{chunk-52R2YXP5.js → chunk-4YWRU7JK.js} +16 -16
  15. package/dist/chunk-52WCHTVZ.js +41 -0
  16. package/dist/{chunk-YIEOFHOL.js → chunk-55TBYJF2.js} +17 -11
  17. package/dist/{chunk-MH5OCRUM.js → chunk-5ACUW753.js} +2 -2
  18. package/dist/chunk-5BJFMAQU.js +32 -0
  19. package/dist/{chunk-YPBQNJHA.js → chunk-5ICB2BXH.js} +8 -8
  20. package/dist/{chunk-YGKYFMSL.js → chunk-5NZSJ5ZG.js} +3 -3
  21. package/dist/{chunk-YPIEYQF4.js → chunk-5P5BGG5L.js} +6 -6
  22. package/dist/{chunk-B7434AE2.js → chunk-5RUMHLIS.js} +2 -2
  23. package/dist/{chunk-5MI2SEV5.js → chunk-5TY4DTHQ.js} +3 -3
  24. package/dist/{chunk-NIXVDQVO.js → chunk-5V5BJACL.js} +2 -2
  25. package/dist/{chunk-7DUDLVFJ.js → chunk-6E2GJANQ.js} +20 -20
  26. package/dist/{chunk-RK6MKKKP.js → chunk-6N2GUZMZ.js} +1 -1
  27. package/dist/{chunk-LK44ULGI.js → chunk-6RGIM2ZH.js} +32 -6
  28. package/dist/{chunk-OS7PQ35Z.js → chunk-6V3DTQWK.js} +22 -22
  29. package/dist/{chunk-OSGQW2Z6.js → chunk-77RSRG3A.js} +8 -8
  30. package/dist/{chunk-5YIBJXGB.js → chunk-7A7IG7OA.js} +10 -10
  31. package/dist/{chunk-YLAJAI2W.js → chunk-7HQOZALR.js} +11 -11
  32. package/dist/{chunk-XB5RFZHH.js → chunk-7HWXYP4H.js} +12 -12
  33. package/dist/{chunk-PIVKU64W.js → chunk-7J7UY46S.js} +2 -2
  34. package/dist/{chunk-62YMDXY6.js → chunk-7KXYMC2P.js} +16 -16
  35. package/dist/{chunk-23M2LUYM.js → chunk-7LCQ7JAM.js} +1 -1
  36. package/dist/{chunk-5XN76FTF.js → chunk-7RGCQ4VZ.js} +5 -5
  37. package/dist/{chunk-CHC5FKTU.js → chunk-7RUMD56V.js} +1 -1
  38. package/dist/{chunk-IUD3ME4E.js → chunk-7S3XFWOU.js} +4 -4
  39. package/dist/{chunk-ZONE6E3Z.js → chunk-7SZPENUP.js} +2 -2
  40. package/dist/{chunk-T6USVBEJ.js → chunk-7VFVQX5K.js} +5 -5
  41. package/dist/chunk-ACWQDL6T.js +37 -0
  42. package/dist/{chunk-AKJTKMXU.js → chunk-ANCI3LFS.js} +5 -5
  43. package/dist/{chunk-B3O52AUQ.js → chunk-ASKDCMW5.js} +4 -4
  44. package/dist/chunk-ATNG5VOZ.js +122 -0
  45. package/dist/{chunk-I7IWQIEB.js → chunk-B3QOYE74.js} +4 -4
  46. package/dist/chunk-B3UHYXHU.js +41 -0
  47. package/dist/{chunk-GXJVY6WT.js → chunk-BA5DTXHQ.js} +5 -5
  48. package/dist/{chunk-5XDNUJ4P.js → chunk-BKFGGJKA.js} +2 -2
  49. package/dist/{chunk-DDAHCPGA.js → chunk-BQNEHB5U.js} +12 -12
  50. package/dist/{chunk-P3TKKBAH.js → chunk-BUWSOQLU.js} +4 -4
  51. package/dist/{chunk-X4W4XXWP.js → chunk-BX52REMA.js} +5 -5
  52. package/dist/{chunk-4SVJNVEE.js → chunk-BXBCMGIQ.js} +2 -0
  53. package/dist/{chunk-CRE4BJHM.js → chunk-C2YGYTU6.js} +23 -23
  54. package/dist/{chunk-7URGP4DD.js → chunk-C5JFMAXX.js} +12 -12
  55. package/dist/chunk-C75W7VXX.js +42 -0
  56. package/dist/{chunk-NGPU2ARF.js → chunk-CAN3EBE5.js} +1 -1
  57. package/dist/{chunk-FR7JPYBD.js → chunk-CE4S5ZY3.js} +12 -12
  58. package/dist/{chunk-BMHGA7WD.js → chunk-CRQ73DIF.js} +12 -12
  59. package/dist/{chunk-KIAI6PWL.js → chunk-CZI2ACNT.js} +17 -17
  60. package/dist/chunk-D7MWYJZF.js +43 -0
  61. package/dist/chunk-DDAEAZEV.js +54 -0
  62. package/dist/{chunk-G2E5MNYP.js → chunk-DGKNOPSE.js} +7 -7
  63. package/dist/{chunk-UF7TAFJM.js → chunk-DQNKG4HY.js} +18 -18
  64. package/dist/{chunk-6TJCUYC5.js → chunk-DS3ZEJVN.js} +3 -3
  65. package/dist/{chunk-3QAKDIEU.js → chunk-DYWTQXP4.js} +23 -23
  66. package/dist/chunk-E25G46RW.js +54 -0
  67. package/dist/{chunk-F2FOQLJ7.js → chunk-EAQFRD2B.js} +6 -6
  68. package/dist/{chunk-W5OYJMBT.js → chunk-EATSD7YD.js} +5 -5
  69. package/dist/{chunk-YGR6OCHQ.js → chunk-EBWIOODZ.js} +8 -14
  70. package/dist/{chunk-LVGBKKSM.js → chunk-EHUYLNLC.js} +15 -15
  71. package/dist/{chunk-IDGSU7JF.js → chunk-EI4KQYJ3.js} +9 -9
  72. package/dist/{chunk-FQSRHTTC.js → chunk-EQOSXLK3.js} +15 -15
  73. package/dist/{chunk-KC5DROFC.js → chunk-EV4TEFOD.js} +14 -14
  74. package/dist/{chunk-2KDSXJFJ.js → chunk-EW7MRMD5.js} +24 -6
  75. package/dist/{chunk-FZL2HNWP.js → chunk-EZSZFI54.js} +3 -3
  76. package/dist/{chunk-MKRBG5EF.js → chunk-FMRMTI7W.js} +1 -1
  77. package/dist/{chunk-E3JYO547.js → chunk-FOQXYMOR.js} +20 -20
  78. package/dist/{chunk-G5SFOH7P.js → chunk-G3PBLW4K.js} +8 -18
  79. package/dist/{chunk-2XM6PYQQ.js → chunk-G7WZH54P.js} +33 -11
  80. package/dist/{chunk-FTV6I76U.js → chunk-GG6HIU74.js} +25 -25
  81. package/dist/{chunk-6EDQE7GO.js → chunk-GMJXC5AL.js} +2 -2
  82. package/dist/chunk-GPLFYLGH.js +130 -0
  83. package/dist/{chunk-UR7RMZ3R.js → chunk-GVFUEGGM.js} +2 -2
  84. package/dist/{chunk-WGZWR4RF.js → chunk-GWSWS264.js} +5 -5
  85. package/dist/{chunk-NPCD54I7.js → chunk-H4VJO3M2.js} +8 -5
  86. package/dist/{chunk-73VPWF5R.js → chunk-HGQZTUAC.js} +4 -4
  87. package/dist/{chunk-2RX7PI2Y.js → chunk-HOUUBE74.js} +4 -4
  88. package/dist/{chunk-BDEKREZH.js → chunk-HQMCHHY5.js} +3 -3
  89. package/dist/{chunk-DPHCFZ7W.js → chunk-HR4DVO6X.js} +3 -3
  90. package/dist/chunk-HZYFLEWO.js +39 -0
  91. package/dist/chunk-IA2RKC6I.js +279 -0
  92. package/dist/{chunk-AY2IUF4K.js → chunk-IILZ7J3L.js} +541 -64
  93. package/dist/chunk-IRW64JFF.js +247 -0
  94. package/dist/{chunk-BJPMKJTL.js → chunk-IVHN2VYG.js} +100 -2
  95. package/dist/{chunk-OEI7LVRP.js → chunk-IWZPGIGT.js} +24 -24
  96. package/dist/{chunk-QICFHVRW.js → chunk-IY4PHPHT.js} +4 -4
  97. package/dist/{chunk-ZE3P35DA.js → chunk-J27QGXO4.js} +9 -9
  98. package/dist/{chunk-BMCKL3VQ.js → chunk-JBSD57N7.js} +24 -24
  99. package/dist/{chunk-67J3VZBA.js → chunk-JEUXCIRD.js} +5 -5
  100. package/dist/{chunk-577AJVRS.js → chunk-JMOLB347.js} +1976 -282
  101. package/dist/{chunk-7EKESFWV.js → chunk-JQX6BSE4.js} +11 -11
  102. package/dist/{chunk-YXJ4XOHF.js → chunk-JRPQX2EK.js} +4 -4
  103. package/dist/{chunk-MTEBM4Y4.js → chunk-JUQHYTXN.js} +18 -12
  104. package/dist/{chunk-APSVL2AI.js → chunk-JUZ75OG4.js} +15 -15
  105. package/dist/{chunk-7GB4ZRE2.js → chunk-KIWEBM6G.js} +12 -12
  106. package/dist/{chunk-KM2FBM3T.js → chunk-KLKENMWQ.js} +282 -50
  107. package/dist/chunk-KQK6SQPE.js +48 -0
  108. package/dist/{chunk-TM7LC37P.js → chunk-KQRYW7OS.js} +179 -115
  109. package/dist/{chunk-65C57N7P.js → chunk-KU4T2CXJ.js} +19 -19
  110. package/dist/{chunk-GFXLPJWY.js → chunk-KXZR2BLL.js} +2 -2
  111. package/dist/{chunk-MGVYVW7Q.js → chunk-L7I5PKGD.js} +1 -1
  112. package/dist/{chunk-XKS6THI5.js → chunk-LDIARP6F.js} +2 -2
  113. package/dist/{chunk-NNUASOAA.js → chunk-LEHZTKB3.js} +12 -12
  114. package/dist/{chunk-FJCFYKVO.js → chunk-LS3WR2RF.js} +86 -29
  115. package/dist/{chunk-Y4BRGOJR.js → chunk-LUPW4WLK.js} +13 -10
  116. package/dist/{chunk-HE4ZQXZM.js → chunk-LVBPY2M6.js} +14 -4
  117. package/dist/{chunk-EX6ZXS5K.js → chunk-LZWVK4YY.js} +4 -4
  118. package/dist/chunk-MCWWMMLN.js +48 -0
  119. package/dist/{chunk-BXIX7S7O.js → chunk-MKC7P5LD.js} +15 -15
  120. package/dist/{chunk-JQ7XQPQS.js → chunk-MKIULIUQ.js} +4 -4
  121. package/dist/{chunk-D3PO4DOZ.js → chunk-MMB2OHUY.js} +4 -2
  122. package/dist/{chunk-MTAUZW2Z.js → chunk-MQNBEO3N.js} +210 -104
  123. package/dist/{chunk-4PJADZRR.js → chunk-MSL3CLHX.js} +16 -16
  124. package/dist/{chunk-5KTOPOEP.js → chunk-MV4637YA.js} +25 -25
  125. package/dist/{chunk-WARBF2KY.js → chunk-MYKQVS5W.js} +4 -4
  126. package/dist/{chunk-4QUQEBFT.js → chunk-MYOW3RPC.js} +6 -6
  127. package/dist/{chunk-ROTY5J2L.js → chunk-NBGBMRIS.js} +1 -1
  128. package/dist/{chunk-BUYJL3GJ.js → chunk-NBQO75XT.js} +1 -1
  129. package/dist/chunk-NCR24CPV.js +41 -0
  130. package/dist/chunk-NDW4ROST.js +38 -0
  131. package/dist/{chunk-AWECWW5Y.js → chunk-NELU7LSL.js} +13 -11
  132. package/dist/{chunk-R64GLVBO.js → chunk-NG5R2WIY.js} +10 -10
  133. package/dist/{chunk-ZZXF6OOJ.js → chunk-NH5QH3WS.js} +2 -2
  134. package/dist/{chunk-XIWYUQZQ.js → chunk-NIYB5K5B.js} +9 -9
  135. package/dist/{chunk-LDKUC2QJ.js → chunk-NR5T46ZY.js} +17 -17
  136. package/dist/{chunk-PEF5OEMB.js → chunk-NX6QEEOA.js} +4 -4
  137. package/dist/{chunk-OGRWQ562.js → chunk-O6ILVBYB.js} +2 -2
  138. package/dist/{chunk-Y7KBQ4BD.js → chunk-OFWYZH6B.js} +22 -22
  139. package/dist/{chunk-N3NBWIYQ.js → chunk-OHXTB6CO.js} +11 -9
  140. package/dist/chunk-OJN7WME4.js +34 -0
  141. package/dist/{chunk-2HMWX4T6.js → chunk-OR5VRULZ.js} +11 -11
  142. package/dist/{chunk-UBWCUP3G.js → chunk-ORZSD2KD.js} +2 -2
  143. package/dist/{chunk-V2TH46ZY.js → chunk-OXVVRJDQ.js} +12 -12
  144. package/dist/{chunk-7YYEKTYF.js → chunk-PQW7PYUR.js} +8 -8
  145. package/dist/{chunk-EZIUFEN6.js → chunk-Q32Y5T2U.js} +12 -12
  146. package/dist/{chunk-FOGG4AUR.js → chunk-QWHTTA2X.js} +23 -7
  147. package/dist/{chunk-HKTUIMH4.js → chunk-R3RVFCJ2.js} +3 -3
  148. package/dist/{chunk-J5LHDJU4.js → chunk-R3VFLYZZ.js} +7 -7
  149. package/dist/{chunk-QKEFZRHS.js → chunk-R6UTCLH5.js} +17 -17
  150. package/dist/{chunk-SS66Q4VE.js → chunk-RB2VSED2.js} +12 -12
  151. package/dist/chunk-REWZE2XI.js +53 -0
  152. package/dist/{chunk-MF7QH4AX.js → chunk-RIEFYHXI.js} +5 -5
  153. package/dist/{chunk-7F2RUWPU.js → chunk-RJDP642F.js} +1 -1
  154. package/dist/{chunk-YFSSNGLR.js → chunk-RWMSJP7H.js} +31 -29
  155. package/dist/{chunk-JMSEEBN4.js → chunk-S2FDPN32.js} +1 -1
  156. package/dist/chunk-S5LSDXV4.js +40 -0
  157. package/dist/{chunk-OJLRFGBP.js → chunk-S7ZWCMDO.js} +79 -15
  158. package/dist/{chunk-ILFKECGI.js → chunk-SG5KY4VB.js} +4 -4
  159. package/dist/{chunk-FEZE6NIA.js → chunk-SH7AZZDA.js} +18 -18
  160. package/dist/{chunk-E3Z67HRK.js → chunk-SILY6ZEZ.js} +4 -4
  161. package/dist/{chunk-5IALSMZ2.js → chunk-SINJKQSI.js} +14 -14
  162. package/dist/chunk-SIUDWWKS.js +47 -0
  163. package/dist/{chunk-XEG3FE2R.js → chunk-SKMHS4CL.js} +1 -1
  164. package/dist/chunk-SNHOLLGN.js +280 -0
  165. package/dist/{chunk-LTQANUDH.js → chunk-SUQZGPVG.js} +25 -25
  166. package/dist/{chunk-47QE246J.js → chunk-T6ESD5KM.js} +5 -5
  167. package/dist/{chunk-YVLMBAYE.js → chunk-TC3KTG33.js} +3 -3
  168. package/dist/{chunk-IV7BCWWN.js → chunk-TCADP67G.js} +3 -3
  169. package/dist/{chunk-6JLPXDWN.js → chunk-TEBBD4XH.js} +5 -5
  170. package/dist/{chunk-F7UQR4ZX.js → chunk-TGEOLIAK.js} +3 -3
  171. package/dist/{chunk-FMKKVWZD.js → chunk-TQYBXDVH.js} +2 -2
  172. package/dist/{chunk-TZDSDDSV.js → chunk-TZXHUDI6.js} +2 -2
  173. package/dist/{chunk-YMOJD5BO.js → chunk-U5PDQTLA.js} +3 -3
  174. package/dist/{chunk-CNKGYDMG.js → chunk-U6YKL7SI.js} +23 -23
  175. package/dist/{chunk-7UKVYFQ2.js → chunk-UABFFMWH.js} +8 -8
  176. package/dist/{chunk-XPEEICAO.js → chunk-UFBKJOWB.js} +15 -15
  177. package/dist/chunk-UFTQIK2J.js +43 -0
  178. package/dist/{chunk-ZP4FJHR4.js → chunk-UNFCFJMF.js} +18 -18
  179. package/dist/{chunk-IZNSAEBX.js → chunk-UTR67XU2.js} +2 -2
  180. package/dist/{chunk-6GWHKMQR.js → chunk-V4XKYGLK.js} +4 -4
  181. package/dist/{chunk-ISNZYKAS.js → chunk-VYNZED7B.js} +21 -21
  182. package/dist/{chunk-FV5YFR6I.js → chunk-WCLAOKCH.js} +9 -9
  183. package/dist/chunk-WFYHOXTB.js +29 -0
  184. package/dist/{chunk-QWVBEK4P.js → chunk-WGU6NIUV.js} +13 -13
  185. package/dist/{chunk-R4TBNKKC.js → chunk-WIMOJMAK.js} +974 -489
  186. package/dist/{chunk-XKZHAD6Y.js → chunk-WKXOEIOY.js} +15 -15
  187. package/dist/chunk-WUE6HKIU.js +790 -0
  188. package/dist/{chunk-R6B6XAKK.js → chunk-WUP77GG2.js} +4 -4
  189. package/dist/{chunk-RRVT4MPS.js → chunk-XF3DATVU.js} +18 -18
  190. package/dist/{chunk-KIHOIVST.js → chunk-XJAJQGXJ.js} +3 -3
  191. package/dist/{chunk-Y5PZHS4K.js → chunk-XKJRPVJO.js} +5 -5
  192. package/dist/{chunk-N4QZJJVB.js → chunk-XNRPCI23.js} +5 -5
  193. package/dist/{chunk-XNYNEEBR.js → chunk-XOVLGBKI.js} +18 -18
  194. package/dist/{chunk-GR6YKM55.js → chunk-XPJR74MA.js} +95 -13
  195. package/dist/{chunk-4GZXS6S2.js → chunk-XPWSNKF3.js} +226 -8
  196. package/dist/{chunk-LRS573EX.js → chunk-XR5DD5DQ.js} +4 -4
  197. package/dist/{chunk-PGKHJYOB.js → chunk-XZJE6WIT.js} +1 -1
  198. package/dist/{chunk-3GTZ2OON.js → chunk-Y5AYBGLB.js} +16 -10
  199. package/dist/{chunk-OIU657QQ.js → chunk-YLAM4HZH.js} +4 -4
  200. package/dist/{chunk-JF2NSTFO.js → chunk-YVCOQ5TZ.js} +3 -3
  201. package/dist/{chunk-F7YL2RZ4.js → chunk-YWOMGMZB.js} +23 -23
  202. package/dist/{chunk-WLIIQ2A4.js → chunk-YWZDAZMA.js} +7 -7
  203. package/dist/{chunk-JAA53T23.js → chunk-Z2EYRUOH.js} +20 -20
  204. package/dist/{chunk-UYYN2IUZ.js → chunk-Z46OXTBE.js} +6 -6
  205. package/dist/chunk-ZHWSL6SR.js +45 -0
  206. package/dist/chunk-ZJQUIG3A.js +87 -0
  207. package/dist/{chunk-T4RTWMJD.js → chunk-ZKUDS7JG.js} +5 -5
  208. package/dist/{chunk-HHUFVJF7.js → chunk-ZTNS3L5Z.js} +6 -6
  209. package/dist/files.json +471 -423
  210. package/dist/packages/sdk/npm/index.js +2300 -1983
  211. package/dist/packages/ui/dist/assets/{elk-api-Mo5w5xCa.js → elk-api-DDup23Us.js} +2 -2
  212. package/dist/packages/ui/dist/assets/{index-Bp3XhPHX.css → index-C0JEkXyN.css} +1 -1
  213. package/dist/packages/ui/dist/assets/index-mTOWhQZm.js +29 -0
  214. package/dist/packages/ui/dist/index.html +2 -2
  215. package/package.json +5 -5
  216. package/dist/chunk-26PLPSQW.js +0 -48
  217. package/dist/chunk-2G4DFUWJ.js +0 -43
  218. package/dist/chunk-2M6WXO73.js +0 -38
  219. package/dist/chunk-5F3RJCHB.js +0 -45
  220. package/dist/chunk-B2VSVN4P.js +0 -34
  221. package/dist/chunk-CITDNDIZ.js +0 -53
  222. package/dist/chunk-DAQBIK5G.js +0 -47
  223. package/dist/chunk-DZRQDNPT.js +0 -34
  224. package/dist/chunk-FLOEZA6K.js +0 -29
  225. package/dist/chunk-FNHSVBRA.js +0 -48
  226. package/dist/chunk-FPGVOSOG.js +0 -41
  227. package/dist/chunk-FZ2E5LGK.js +0 -54
  228. package/dist/chunk-HB6XSGI6.js +0 -131
  229. package/dist/chunk-HUZQDKQK.js +0 -48
  230. package/dist/chunk-L4VJ4ETL.js +0 -41
  231. package/dist/chunk-XPCWQXTY.js +0 -37
  232. package/dist/packages/ui/dist/assets/index-DM212ZbV.js +0 -29
@@ -12,18 +12,18 @@ import {
12
12
  readDrawio,
13
13
  readMermaid,
14
14
  resolveNames
15
- } from "./chunk-NIXVDQVO.js";
15
+ } from "./chunk-5V5BJACL.js";
16
16
  import {
17
17
  openapiExtractor,
18
18
  readOpenApiDocument
19
- } from "./chunk-UR7RMZ3R.js";
19
+ } from "./chunk-GVFUEGGM.js";
20
20
  import {
21
21
  combine,
22
22
  formatOf,
23
23
  screenDiagramXml,
24
24
  screenOfficeXml,
25
25
  screenText
26
- } from "./chunk-5XDNUJ4P.js";
26
+ } from "./chunk-BKFGGJKA.js";
27
27
  import {
28
28
  TrafficFile,
29
29
  endpointId,
@@ -42,10 +42,10 @@ import {
42
42
  routeScore,
43
43
  toCanonicalYaml,
44
44
  trafficFileText
45
- } from "./chunk-577AJVRS.js";
45
+ } from "./chunk-JMOLB347.js";
46
46
  import {
47
47
  writeFileAtomic
48
- } from "./chunk-D3PO4DOZ.js";
48
+ } from "./chunk-MMB2OHUY.js";
49
49
  import {
50
50
  __toESM
51
51
  } from "./chunk-TV45EUGM.js";
@@ -168,6 +168,10 @@ function classify(fileName, bytes) {
168
168
  return { classification: "diagram" };
169
169
  if (/^<(!doctype html|html)\b/i.test(head))
170
170
  return { classification: "document" };
171
+ if (ext === "proto" || /^(syntax\s*=\s*["']proto[23]["']|package\s+[\w.]+\s*;)/m.test(head))
172
+ return { classification: "protobuf" };
173
+ if (ext === "avsc" || /^\{/.test(head) && /"type"\s*:\s*"record"/.test(head) && /"fields"\s*:/.test(head))
174
+ return { classification: "avro" };
171
175
  if (["json", "yaml", "yml"].includes(ext) || /^[[{]/.test(head)) {
172
176
  let data;
173
177
  try {
@@ -200,7 +204,10 @@ import { createHash } from "node:crypto";
200
204
  var READERS = {
201
205
  openapi: `${openapiExtractor.id}@${openapiExtractor.version}`,
202
206
  asyncapi: "asyncapi@0.1.0",
203
- payload: "payload@0.1.0"
207
+ payload: "payload@0.1.0",
208
+ // ADR 0164: a topic's message spec.
209
+ protobuf: "protobuf@0.1.0",
210
+ avro: "avro@0.1.0"
204
211
  };
205
212
  var short = (s) => createHash("sha256").update(s).digest("hex").slice(0, 6);
206
213
  function oneFile(path, text3) {
@@ -416,9 +423,9 @@ var opt = {
416
423
  };
417
424
 
418
425
  // packages/intake/dist/scan-inputs.js
419
- import { createHash as createHash4 } from "node:crypto";
420
- import { readdir, readFile, stat } from "node:fs/promises";
421
- import { join, relative, resolve, sep } from "node:path";
426
+ import { createHash as createHash5 } from "node:crypto";
427
+ import { readdir as readdir2, readFile as readFile2, stat as stat2 } from "node:fs/promises";
428
+ import { join as join2, relative, resolve, sep } from "node:path";
422
429
 
423
430
  // packages/intake/dist/screen-file.js
424
431
  var PK = (b) => b[0] === 80 && b[1] === 75;
@@ -460,10 +467,314 @@ function screenFile(path, bytes) {
460
467
  }
461
468
  }
462
469
 
470
+ // packages/intake/dist/contract-specs.js
471
+ var import_yaml4 = __toESM(require_dist(), 1);
472
+ import { readdir, readFile, stat } from "node:fs/promises";
473
+ import { join } from "node:path";
474
+
475
+ // packages/intake/dist/traffic.js
476
+ import { createHash as createHash3 } from "node:crypto";
477
+ var cmp = (a, b) => a < b ? -1 : a > b ? 1 : 0;
478
+ var key = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
479
+ var sha = (s) => createHash3("sha256").update(s, "utf8").digest("hex");
480
+ var IPV4 = /\b\d{1,3}(?:\.\d{1,3}){3}\b/;
481
+ var IPV6 = /[0-9a-f]{0,4}::[0-9a-f]{0,4}|\b[0-9a-f]{1,4}(?::[0-9a-f]{1,4}){2,7}\b/i;
482
+ var EMAIL = /[^\s@/]+@[^\s@/]+/;
483
+ var JWT = /\beyJ[A-Za-z0-9_-]{6,}/;
484
+ var OPAQUE = /\b(?=[A-Za-z0-9+_-]*\d)(?=[A-Za-z0-9+_-]*[A-Za-z])[A-Za-z0-9+_-]{24,}={0,2}/;
485
+ var UUID = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i;
486
+ var HEX = /\b[0-9a-f]{16,}\b/i;
487
+ function looksSensitive(v) {
488
+ return [IPV4, IPV6, EMAIL, JWT, OPAQUE, UUID, HEX].some((re) => re.test(v));
489
+ }
490
+ function rowsOf(text3) {
491
+ const t = text3.replace(/^\uFEFF/, "").trim();
492
+ if (!t)
493
+ return void 0;
494
+ if (t.startsWith("[") || t.startsWith("{")) {
495
+ let v;
496
+ try {
497
+ v = JSON.parse(t);
498
+ } catch {
499
+ return void 0;
500
+ }
501
+ const list2 = Array.isArray(v) ? v : v && typeof v === "object" ? ["rows", "data", "records", "items"].map((k) => v[k]).find((x) => Array.isArray(x)) : void 0;
502
+ if (!Array.isArray(list2) || !list2.length)
503
+ return void 0;
504
+ const out = [];
505
+ for (const r of list2) {
506
+ if (!r || typeof r !== "object" || Array.isArray(r))
507
+ return void 0;
508
+ const row = {};
509
+ for (const [k, x] of Object.entries(r))
510
+ if (typeof x === "string" || typeof x === "number")
511
+ row[k] = String(x);
512
+ out.push(row);
513
+ }
514
+ return out;
515
+ }
516
+ const recs = parseCsv(t);
517
+ if (recs.length < 2)
518
+ return void 0;
519
+ const head = recs[0].cells.map((c) => c.trim());
520
+ if (head.length < 2)
521
+ return void 0;
522
+ return recs.slice(1).map((r) => {
523
+ const row = {};
524
+ head.forEach((h, i) => row[h] = (r.cells[i] ?? "").trim());
525
+ return row;
526
+ });
527
+ }
528
+ function dayOf(v) {
529
+ const m = /^(\d{4}-\d{2}-\d{2})/.exec(v.trim());
530
+ if (m)
531
+ return m[1];
532
+ if (/^\d{12,13}$/.test(v.trim()))
533
+ return new Date(Number(v)).toISOString().slice(0, 10);
534
+ return void 0;
535
+ }
536
+ var VERSION = /^v\d+(?:\.\d+)*$/i;
537
+ var PARAM = /^(?:\{[A-Za-z_][A-Za-z0-9_.-]{0,40}\}|:[A-Za-z_][A-Za-z0-9_]{0,40}|<[A-Za-z_][A-Za-z0-9_:]{0,40}>)$/;
538
+ var segmentOf = (s) => VERSION.test(s) || PARAM.test(s) || /^[a-z][a-z._-]*$/.test(s) && s.length <= 20 && /[aeiou]/.test(s) && !looksSensitive(s) ? s : "{id}";
539
+ function barePath(path) {
540
+ let p = path.trim().split(/[?#]/, 1)[0] ?? "";
541
+ p = p.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]*/i, "");
542
+ return p.replace(/;[^/]*/g, "");
543
+ }
544
+ function safePathOf(path) {
545
+ const p = barePath(path);
546
+ if (!p.startsWith("/"))
547
+ return void 0;
548
+ return `/${p.split("/").filter(Boolean).map(segmentOf).join("/")}`;
549
+ }
550
+ var MATCH = 100;
551
+ function pathTemplateOf(path, templates) {
552
+ const p = barePath(path);
553
+ if (!p.startsWith("/"))
554
+ return void 0;
555
+ const sorted2 = [...templates].sort();
556
+ let best;
557
+ let score = 0;
558
+ for (const t of sorted2) {
559
+ const s = routeScore(p, t);
560
+ if (s > MATCH && s > score) {
561
+ score = s;
562
+ best = t;
563
+ }
564
+ }
565
+ if (best)
566
+ return best;
567
+ const segs = p.split("/").filter(Boolean);
568
+ let prefix;
569
+ let len = 0;
570
+ score = 0;
571
+ for (const t of sorted2) {
572
+ const n = t.split("/").filter(Boolean).length;
573
+ if (n === 0 || n >= segs.length || n < len)
574
+ continue;
575
+ const s = routeScore(`/${segs.slice(0, n).join("/")}`, t);
576
+ if (s <= MATCH)
577
+ continue;
578
+ if (n > len || s > score) {
579
+ len = n;
580
+ score = s;
581
+ prefix = t;
582
+ }
583
+ }
584
+ return prefix ? `${prefix.replace(/\/+$/, "")}/**` : void 0;
585
+ }
586
+ var appLabelOf = (name) => `app-${sha(name).slice(0, 8)}`;
587
+ function denyListHits(text3, hashes) {
588
+ const hits = [];
589
+ text3.toLowerCase().split("\n").forEach((line, i) => {
590
+ const w = line.match(/[a-z0-9]+/g) ?? [];
591
+ for (let k = 0; k < w.length; k++)
592
+ if (hashes.has(sha(w[k])) || k + 1 < w.length && hashes.has(sha(`${w[k]} ${w[k + 1]}`))) {
593
+ hits.push(i + 1);
594
+ break;
595
+ }
596
+ });
597
+ return hits;
598
+ }
599
+ function aggregateTraffic(input) {
600
+ const text3 = Buffer.from(input.bytes).toString("utf8");
601
+ const rows = rowsOf(text3);
602
+ const shape = `a CSV with a header row, or a JSON list of rows, with an app, a method and a path column (${input.source}: app ${input.columns.app.join("/")}; method ${input.columns.method.join("/")}; path ${[...input.columns.path, ...input.columns.basepath].join("/")})`;
603
+ if (!rows)
604
+ return { ok: false, message: `The file doesn't read as a traffic export: give ${shape}.` };
605
+ const names = [...new Set(rows.flatMap((r) => Object.keys(r)))];
606
+ const col = (aliases) => {
607
+ for (const a of aliases) {
608
+ const hit = names.find((n) => key(n) === key(a));
609
+ if (hit)
610
+ return hit;
611
+ }
612
+ return void 0;
613
+ };
614
+ const c = {
615
+ app: col(input.columns.app),
616
+ method: col(input.columns.method),
617
+ basepath: col(input.columns.basepath),
618
+ suffix: col(input.columns.suffix),
619
+ proxy: col(input.columns.proxy),
620
+ count: col(input.columns.count),
621
+ time: col(input.columns.time),
622
+ path: void 0
623
+ };
624
+ if (!c.basepath || !c.suffix)
625
+ c.path = col(input.columns.path);
626
+ const missing = [
627
+ !c.app ? "app" : "",
628
+ !c.method ? "method" : "",
629
+ !c.path && !(c.basepath && c.suffix) ? "path" : ""
630
+ ].filter(Boolean);
631
+ if (missing.length)
632
+ return {
633
+ ok: false,
634
+ message: `The file has no ${missing.join(", ")} column, so it can't be kept as aggregates: give ${shape}.`
635
+ };
636
+ const range = (v) => v && /^\d{4}-\d{2}-\d{2}$/.test(v) ? v : void 0;
637
+ if (input.from && !range(input.from) || input.to && !range(input.to))
638
+ return { ok: false, message: "--from and --to are days: YYYY-MM-DD." };
639
+ if ((!input.from || !input.to) && !c.time)
640
+ return {
641
+ ok: false,
642
+ message: "The export has no date column: give --from and --to (YYYY-MM-DD) for the range it covers."
643
+ };
644
+ const kept = new Set(Object.values(c).filter((x) => !!x));
645
+ const dropped = names.filter((n) => !kept.has(n)).sort();
646
+ const secrets = /* @__PURE__ */ new Set();
647
+ const keptValues = /* @__PURE__ */ new Set();
648
+ const agg = /* @__PURE__ */ new Map();
649
+ let outOfRange = 0;
650
+ let skipped2 = 0;
651
+ let unmatched = 0;
652
+ const known = /* @__PURE__ */ new Map();
653
+ for (const a of input.apps ?? [])
654
+ if (a.trim() && !known.has(key(a)))
655
+ known.set(key(a), a.trim());
656
+ const days = [];
657
+ for (const r of rows) {
658
+ for (const n of dropped) {
659
+ const v = (r[n] ?? "").trim();
660
+ const q = /^(?:[a-z][a-z0-9+.-]*:\/\/|\/)/i.test(v) ? v.split(/[?#]/)[1] ?? "" : v;
661
+ if (q.length >= 6)
662
+ secrets.add(q);
663
+ }
664
+ for (const n of [c.path, c.suffix, c.basepath]) {
665
+ const v = n ? r[n] ?? "" : "";
666
+ const q = v.split(/[?#]/)[1] ?? "";
667
+ if (q.length >= 4)
668
+ secrets.add(q);
669
+ for (const m of (v.split(/[?#]/, 1)[0] ?? "").match(/;[^/]*/g) ?? [])
670
+ if (m.length >= 5)
671
+ secrets.add(m.slice(1));
672
+ }
673
+ if (c.time) {
674
+ const d = dayOf(r[c.time] ?? "");
675
+ if (d) {
676
+ if (input.from && d < input.from || input.to && d > input.to) {
677
+ outOfRange++;
678
+ continue;
679
+ }
680
+ days.push(d);
681
+ } else if (!input.from || !input.to) {
682
+ skipped2++;
683
+ continue;
684
+ }
685
+ }
686
+ const method = (r[c.method] ?? "").trim().toUpperCase();
687
+ const rawPath = c.path ? r[c.path] ?? "" : `${(r[c.basepath] ?? "").replace(/\/+$/, "")}/${(r[c.suffix] ?? "").replace(/^\/+/, "")}`;
688
+ const countText = c.count ? (r[c.count] ?? "").trim() : "1";
689
+ const count = Number(countText);
690
+ if (!/^[A-Z]{3,10}$/.test(method) || !barePath(rawPath).startsWith("/") || !Number.isInteger(count) || count < 0) {
691
+ skipped2++;
692
+ continue;
693
+ }
694
+ const path = pathTemplateOf(rawPath, input.templates);
695
+ if (!path) {
696
+ unmatched++;
697
+ continue;
698
+ }
699
+ if (count === 0)
700
+ continue;
701
+ const appRaw = (r[c.app] ?? "").trim();
702
+ const app = !appRaw ? "(none)" : known.get(key(appRaw)) ?? appLabelOf(appRaw);
703
+ const proxyRaw = c.proxy ? (r[c.proxy] ?? "").trim() : "";
704
+ const proxy = proxyRaw && !looksSensitive(proxyRaw) ? proxyRaw : void 0;
705
+ const baseRaw = c.basepath ? (r[c.basepath] ?? "").trim() : "";
706
+ const basepath = baseRaw ? safePathOf(baseRaw) : void 0;
707
+ for (const v of [app, proxy, basepath, path])
708
+ if (v)
709
+ keptValues.add(v);
710
+ const k = [app, method, path, proxy ?? "", basepath ?? ""].join("\0");
711
+ const row = agg.get(k) ?? {
712
+ app,
713
+ method,
714
+ path,
715
+ ...proxy ? { proxy } : {},
716
+ ...basepath ? { basepath } : {},
717
+ count: 0
718
+ };
719
+ row.count += count;
720
+ agg.set(k, row);
721
+ }
722
+ if (!agg.size)
723
+ return {
724
+ ok: false,
725
+ message: `No row of the file is a request in the range to a route of the estate (${rows.length} read, ${outOfRange} outside it, ${skipped2} without a method, path or count, ${unmatched} matching no route template of the estate): nothing to keep.`
726
+ };
727
+ days.sort();
728
+ const from = input.from ?? days[0];
729
+ const to = input.to ?? days[days.length - 1];
730
+ if (!from || !to)
731
+ return { ok: false, message: "The rows carry no dates: give --from and --to (YYYY-MM-DD)." };
732
+ const parsed = TrafficFile.safeParse({
733
+ schemaVersion: 1,
734
+ source: input.source,
735
+ from,
736
+ to,
737
+ inputSha256: createHash3("sha256").update(input.bytes).digest("hex"),
738
+ rows: [...agg.values()].sort((a, b) => cmp(a.app, b.app) || cmp(a.proxy ?? "", b.proxy ?? "") || cmp(a.path, b.path) || cmp(a.method, b.method))
739
+ });
740
+ if (!parsed.success)
741
+ return { ok: false, message: `The aggregate isn't valid: ${parsed.error.issues[0]?.message}.` };
742
+ const out = trafficFileText(parsed.data);
743
+ const lower = out.toLowerCase();
744
+ const leaked = [...secrets].filter((s) => !keptValues.has(s) && lower.includes(s.toLowerCase()));
745
+ if (leaked.length)
746
+ return {
747
+ ok: false,
748
+ message: `Refused: ${leaked.length} value${leaked.length === 1 ? "" : "s"} of the export's dropped columns would be written. Nothing was written.`
749
+ };
750
+ const body = out.replace(/^inputSha256: .*$/m, "");
751
+ if ([IPV4, IPV6, EMAIL, JWT, OPAQUE, UUID, HEX].some((re) => re.test(body)))
752
+ return {
753
+ ok: false,
754
+ message: "Refused: the aggregate would hold an IP, an email or a token-looking value. Nothing was written."
755
+ };
756
+ const hits = input.denyHashes?.size ? denyListHits(out, input.denyHashes) : [];
757
+ if (hits.length)
758
+ return {
759
+ ok: false,
760
+ message: `Refused: the deny-list names a word on line${hits.length === 1 ? "" : "s"} ${hits.join(", ")} of the aggregate. Nothing was written.`
761
+ };
762
+ return {
763
+ ok: true,
764
+ file: parsed.data,
765
+ text: out,
766
+ read: rows.length,
767
+ outOfRange,
768
+ skipped: skipped2,
769
+ unmatched,
770
+ dropped
771
+ };
772
+ }
773
+
463
774
  // packages/intake/dist/vendor-ops.js
464
775
  var import_yaml3 = __toESM(require_dist(), 1);
465
- import { createHash as createHash3 } from "node:crypto";
466
- var short2 = (s) => createHash3("sha256").update(s).digest("hex").slice(0, 6);
776
+ import { createHash as createHash4 } from "node:crypto";
777
+ var short2 = (s) => createHash4("sha256").update(s).digest("hex").slice(0, 6);
467
778
  function specEndpointIds(component, ops) {
468
779
  const ids = ops.map((o) => endpointId(component, o.method, o.normalizedPath));
469
780
  const count = /* @__PURE__ */ new Map();
@@ -775,12 +1086,442 @@ function operationSchemas(spec) {
775
1086
  });
776
1087
  }
777
1088
 
1089
+ // packages/intake/dist/contract-specs.js
1090
+ var MAX_BYTES = 1024 * 1024;
1091
+ var SKIP = /* @__PURE__ */ new Set([
1092
+ ".git",
1093
+ "node_modules",
1094
+ "vendor",
1095
+ "target",
1096
+ "build",
1097
+ "dist",
1098
+ "out",
1099
+ "bin",
1100
+ "obj",
1101
+ ".gradle",
1102
+ ".idea",
1103
+ ".venv",
1104
+ "__pycache__"
1105
+ ]);
1106
+ var cmp2 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
1107
+ function readProtoSpecs(path, text3) {
1108
+ const proto3 = /^\s*syntax\s*=\s*["']proto3["']/m.test(text3);
1109
+ let pkg = "";
1110
+ const out = [];
1111
+ const stack = [];
1112
+ let inComment = false;
1113
+ text3.split(/\r?\n/).forEach((raw, i) => {
1114
+ let line = raw;
1115
+ if (inComment) {
1116
+ const end = line.indexOf("*/");
1117
+ if (end < 0)
1118
+ return;
1119
+ line = line.slice(end + 2);
1120
+ inComment = false;
1121
+ }
1122
+ line = line.replace(/\/\*.*?\*\//g, "").replace(/\/\/.*$/, "");
1123
+ const open = line.indexOf("/*");
1124
+ if (open >= 0) {
1125
+ inComment = true;
1126
+ line = line.slice(0, open);
1127
+ }
1128
+ const n = i + 1;
1129
+ const p = /^\s*package\s+([\w.]+)\s*;/.exec(line);
1130
+ if (p)
1131
+ pkg = p[1];
1132
+ const message = /^\s*message\s+(\w+)\s*\{/.exec(line);
1133
+ const oneof = /^\s*oneof\s+(\w+)\s*\{/.exec(line);
1134
+ const other = /^\s*(enum|service|extend|extensions)\b[^{]*\{/.exec(line);
1135
+ let rest = line;
1136
+ if (message) {
1137
+ const outer = stack.filter((f) => f.kind === "message").map((f) => f.name);
1138
+ const name = [...outer, message[1]].join(".");
1139
+ const spec = {
1140
+ kind: "message",
1141
+ format: "protobuf",
1142
+ role: "schema",
1143
+ file: path,
1144
+ line: n,
1145
+ name: pkg ? `${pkg}.${name}` : name,
1146
+ fields: []
1147
+ };
1148
+ out.push(spec);
1149
+ stack.push({ kind: "message", name: message[1], spec });
1150
+ rest = line.slice(line.indexOf("{") + 1);
1151
+ } else if (oneof || other) {
1152
+ stack.push({ kind: oneof ? "oneof" : "other", name: "" });
1153
+ rest = line.slice(line.indexOf("{") + 1);
1154
+ } else {
1155
+ const top = stack.at(-1);
1156
+ const owner = top?.kind === "message" ? top : top?.kind === "oneof" ? stack.at(-2) : void 0;
1157
+ const f = /^\s*(optional|required|repeated)?\s*(map\s*<[^>]+>|[\w.]+)\s+(\w+)\s*=\s*(\d+)\s*(\[[^\]]*\])?\s*;/.exec(line);
1158
+ if (f && owner?.kind === "message" && owner.spec && !["reserved", "option"].includes(f[2])) {
1159
+ const label = f[1];
1160
+ owner.spec.fields.push({
1161
+ side: "message",
1162
+ name: f[3],
1163
+ type: label === "repeated" ? `repeated ${f[2]}` : f[2].replace(/\s+/g, ""),
1164
+ // proto2's `required` must be there; anything else may be left out (proto3 has no required).
1165
+ required: label === "required" && !proto3,
1166
+ number: Number(f[4]),
1167
+ at: `${path}:${n}`
1168
+ });
1169
+ }
1170
+ }
1171
+ for (const _ of rest.matchAll(/\}/g))
1172
+ stack.pop();
1173
+ });
1174
+ return out;
1175
+ }
1176
+ function lineOfName(lines, from, name) {
1177
+ const re = new RegExp(`"name"\\s*:\\s*"${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}"`);
1178
+ for (let i = Math.max(0, from); i < lines.length; i++)
1179
+ if (re.test(lines[i]))
1180
+ return i + 1;
1181
+ return from + 1;
1182
+ }
1183
+ function readAvroSpecs(path, text3) {
1184
+ let data;
1185
+ try {
1186
+ data = JSON.parse(text3);
1187
+ } catch {
1188
+ return [];
1189
+ }
1190
+ const lines = text3.split(/\r?\n/);
1191
+ const out = [];
1192
+ let cursor = 0;
1193
+ const typeName = (t) => {
1194
+ if (typeof t === "string")
1195
+ return t;
1196
+ if (Array.isArray(t))
1197
+ return t.map(typeName).join("|");
1198
+ if (t && typeof t === "object") {
1199
+ const o = t;
1200
+ if (o.type === "array")
1201
+ return `repeated ${typeName(o.items)}`;
1202
+ if (o.type === "map")
1203
+ return `map<string,${typeName(o.values)}>`;
1204
+ if (typeof o.logicalType === "string")
1205
+ return String(o.type);
1206
+ if (typeof o.name === "string")
1207
+ return o.name;
1208
+ return typeName(o.type);
1209
+ }
1210
+ return "";
1211
+ };
1212
+ const record = (r, ns) => {
1213
+ if (r.type !== "record" || typeof r.name !== "string" || !Array.isArray(r.fields))
1214
+ return;
1215
+ const space = typeof r.namespace === "string" ? r.namespace : ns;
1216
+ const line = lineOfName(lines, cursor, r.name);
1217
+ cursor = line;
1218
+ const spec = {
1219
+ kind: "message",
1220
+ format: "avro",
1221
+ role: "schema",
1222
+ file: path,
1223
+ line,
1224
+ name: space ? `${space}.${r.name}` : r.name,
1225
+ fields: []
1226
+ };
1227
+ out.push(spec);
1228
+ r.fields.forEach((f, i) => {
1229
+ if (!f || typeof f !== "object")
1230
+ return;
1231
+ const x = f;
1232
+ if (typeof x.name !== "string")
1233
+ return;
1234
+ const at = lineOfName(lines, cursor, x.name);
1235
+ cursor = at;
1236
+ const nullable = Array.isArray(x.type) && x.type.includes("null");
1237
+ const type = typeName(Array.isArray(x.type) ? x.type.filter((t) => t !== "null") : x.type);
1238
+ spec.fields.push({
1239
+ side: "message",
1240
+ name: x.name,
1241
+ ...type ? { type } : {},
1242
+ required: !nullable && !("default" in x),
1243
+ number: i,
1244
+ at: `${path}:${at}`
1245
+ });
1246
+ const inner = Array.isArray(x.type) ? x.type : [x.type];
1247
+ for (const t of inner)
1248
+ if (t && typeof t === "object")
1249
+ record(t, space);
1250
+ });
1251
+ };
1252
+ for (const r of Array.isArray(data) ? data : [data])
1253
+ if (r && typeof r === "object")
1254
+ record(r, "");
1255
+ return out;
1256
+ }
1257
+ var lineAt = (d, node) => {
1258
+ const r = node?.range;
1259
+ return r ? d.lc.linePos(r[0]).line : 1;
1260
+ };
1261
+ function deref2(d, node, depth = 0) {
1262
+ if (!(0, import_yaml4.isMap)(node) || depth > 8)
1263
+ return node;
1264
+ const ref = node.get("$ref");
1265
+ if (typeof ref !== "string" || !ref.startsWith("#/"))
1266
+ return node;
1267
+ let at = d.root;
1268
+ for (const p of ref.slice(2).split("/"))
1269
+ at = (0, import_yaml4.isMap)(at) ? at.get(p.replace(/~1/g, "/").replace(/~0/g, "~"), true) : void 0;
1270
+ return deref2(d, at, depth + 1);
1271
+ }
1272
+ function propsOf(d, schema, prefix, depth, out) {
1273
+ const s = deref2(d, schema);
1274
+ if (!(0, import_yaml4.isMap)(s) || depth > 6)
1275
+ return;
1276
+ const props = s.get("properties", true);
1277
+ const req = s.get("required", true);
1278
+ const required = new Set((0, import_yaml4.isSeq)(req) ? req.items.map((x) => (0, import_yaml4.isScalar)(x) ? String(x.value) : "") : []);
1279
+ if (!(0, import_yaml4.isMap)(props))
1280
+ return;
1281
+ for (const p of props.items) {
1282
+ if (!(0, import_yaml4.isScalar)(p.key))
1283
+ continue;
1284
+ const name = prefix ? `${prefix}.${String(p.key.value)}` : String(p.key.value);
1285
+ const v = deref2(d, p.value);
1286
+ const type = (0, import_yaml4.isMap)(v) ? v.get("type") : void 0;
1287
+ out.push({
1288
+ side: "message",
1289
+ name,
1290
+ ...typeof type === "string" ? { type } : {},
1291
+ required: required.has(String(p.key.value)),
1292
+ at: `${d.path}:${lineAt(d, p.key)}`
1293
+ });
1294
+ if ((0, import_yaml4.isMap)(v)) {
1295
+ if (type === "array")
1296
+ propsOf(d, v.get("items", true), `${name}[]`, depth + 1, out);
1297
+ else
1298
+ propsOf(d, v, name, depth + 1, out);
1299
+ }
1300
+ }
1301
+ }
1302
+ function docOf(path, text3) {
1303
+ const lc = new import_yaml4.LineCounter();
1304
+ const doc = (0, import_yaml4.parseDocument)(text3, { lineCounter: lc });
1305
+ return (0, import_yaml4.isMap)(doc.contents) ? { path, lc, root: doc.contents } : void 0;
1306
+ }
1307
+ function readJsonSchemaSpecs(path, text3) {
1308
+ const d = docOf(path, text3);
1309
+ if (!d)
1310
+ return [];
1311
+ const title = d.root.get("title");
1312
+ const id = d.root.get("$id");
1313
+ const fields = [];
1314
+ propsOf(d, d.root, "", 0, fields);
1315
+ if (!fields.length)
1316
+ return [];
1317
+ const name = typeof title === "string" && title ? title : typeof id === "string" && id ? (id.split("/").pop() ?? id).replace(/\.json$/, "") : (path.split("/").pop() ?? path).replace(/\.(schema\.)?json$|\.ya?ml$/i, "");
1318
+ return [
1319
+ { kind: "message", format: "json-schema", role: "schema", file: path, line: 1, name, fields }
1320
+ ];
1321
+ }
1322
+ function readAsyncApiSpecs(path, text3) {
1323
+ const d = docOf(path, text3);
1324
+ if (!d || d.root.get("asyncapi") === void 0)
1325
+ return [];
1326
+ const out = [];
1327
+ const channels = d.root.get("channels", true);
1328
+ if (!(0, import_yaml4.isMap)(channels))
1329
+ return out;
1330
+ const add = (topic, message) => {
1331
+ const m = deref2(d, message);
1332
+ if (!(0, import_yaml4.isMap)(m))
1333
+ return;
1334
+ const oneOf = m.get("oneOf", true);
1335
+ if ((0, import_yaml4.isSeq)(oneOf)) {
1336
+ for (const x of oneOf.items)
1337
+ add(topic, x);
1338
+ return;
1339
+ }
1340
+ const payload = m.get("payload", true);
1341
+ const fields = [];
1342
+ propsOf(d, payload, "", 0, fields);
1343
+ const p = deref2(d, payload);
1344
+ const title = (0, import_yaml4.isMap)(p) ? p.get("title") : void 0;
1345
+ const name = m.get("name") ?? m.get("title") ?? title;
1346
+ out.push({
1347
+ kind: "message",
1348
+ format: "asyncapi",
1349
+ role: "schema",
1350
+ file: path,
1351
+ line: lineAt(d, m),
1352
+ topic,
1353
+ ...typeof name === "string" && name ? { name } : {},
1354
+ fields
1355
+ });
1356
+ };
1357
+ for (const c of channels.items) {
1358
+ if (!(0, import_yaml4.isScalar)(c.key))
1359
+ continue;
1360
+ const ch = deref2(d, c.value);
1361
+ if (!(0, import_yaml4.isMap)(ch))
1362
+ continue;
1363
+ const address = ch.get("address");
1364
+ const topic = typeof address === "string" && address ? address : String(c.key.value);
1365
+ for (const op of ["publish", "subscribe"]) {
1366
+ const o = ch.get(op, true);
1367
+ if ((0, import_yaml4.isMap)(o))
1368
+ add(topic, o.get("message", true));
1369
+ }
1370
+ const msgs = ch.get("messages", true);
1371
+ if ((0, import_yaml4.isMap)(msgs))
1372
+ for (const m of msgs.items)
1373
+ add(topic, m.value);
1374
+ }
1375
+ return out;
1376
+ }
1377
+ function openApiContractSpecs(spec) {
1378
+ return spec.operations.map((o) => {
1379
+ const [file, line] = splitAt(o.cite, spec.path);
1380
+ const field2 = (side) => (f) => ({
1381
+ side,
1382
+ name: f.name,
1383
+ ...f.type ? { type: f.type } : {},
1384
+ ...f.required !== void 0 ? { required: f.required } : {},
1385
+ ...f.in ? { in: f.in } : {},
1386
+ at: f.cite
1387
+ });
1388
+ return {
1389
+ kind: "operation",
1390
+ format: "openapi",
1391
+ role: "consumer",
1392
+ file,
1393
+ line,
1394
+ method: o.method,
1395
+ path: o.fullPath,
1396
+ id: o.id,
1397
+ fields: [...o.request.map(field2("request")), ...o.response.map(field2("response"))],
1398
+ ...o.errors?.length ? { errors: o.errors.map((e) => ({ status: e.status, at: e.cite })) } : {}
1399
+ };
1400
+ });
1401
+ }
1402
+ function splitAt(cite, path) {
1403
+ const m = /^(.*):(\d+)$/.exec(cite);
1404
+ return m ? [m[1], Number(m[2])] : [path, 1];
1405
+ }
1406
+ function specFormatOf(name, text3) {
1407
+ const lower = name.toLowerCase();
1408
+ if (lower.endsWith(".proto"))
1409
+ return "protobuf";
1410
+ if (lower.endsWith(".avsc"))
1411
+ return "avro";
1412
+ if (!/\.(ya?ml|json)$/.test(lower))
1413
+ return void 0;
1414
+ const head = text3.slice(0, 4e3);
1415
+ if (/^\s*["']?(openapi|swagger)["']?\s*:/m.test(head))
1416
+ return "openapi";
1417
+ if (/^\s*["']?asyncapi["']?\s*:/m.test(head))
1418
+ return "asyncapi";
1419
+ if (/"type"\s*:\s*"record"/.test(head) && /"fields"\s*:/.test(head))
1420
+ return "avro";
1421
+ if (/["']?\$schema["']?\s*:/.test(head) && /json-schema\.org/.test(head))
1422
+ return "json-schema";
1423
+ return void 0;
1424
+ }
1425
+ function readContractSpecs(path, text3) {
1426
+ switch (specFormatOf(path, text3)) {
1427
+ case "protobuf":
1428
+ return readProtoSpecs(path, text3);
1429
+ case "avro":
1430
+ return readAvroSpecs(path, text3);
1431
+ case "json-schema":
1432
+ return readJsonSchemaSpecs(path, text3);
1433
+ case "asyncapi":
1434
+ return readAsyncApiSpecs(path, text3);
1435
+ case "openapi": {
1436
+ const spec = readVendorSpec(path, text3, "spec");
1437
+ return spec ? openApiContractSpecs(spec) : [];
1438
+ }
1439
+ default:
1440
+ return [];
1441
+ }
1442
+ }
1443
+ var sameShape = (a, b) => normalizePath(a).replace(/\{[^}]*\}/g, "{}") === normalizePath(b).replace(/\{[^}]*\}/g, "{}");
1444
+ var SPEC_FILE = /\.(proto|avsc|ya?ml|json)$/i;
1445
+ function cmpPath(a, b) {
1446
+ const x = a.split("/");
1447
+ const y = b.split("/");
1448
+ for (let i = 0; i < Math.min(x.length, y.length); i++) {
1449
+ const c = cmp2(x[i], y[i]);
1450
+ if (c)
1451
+ return c;
1452
+ }
1453
+ return x.length - y.length;
1454
+ }
1455
+ var skipped = (p) => p.split("/").slice(0, -1).some((d) => SKIP.has(d) || d.startsWith("."));
1456
+ function folderTree(dir) {
1457
+ return {
1458
+ async files() {
1459
+ const out = [];
1460
+ const walk2 = async (rel) => {
1461
+ const entries = await readdir(join(dir, ...rel.split("/").filter(Boolean)), {
1462
+ withFileTypes: true
1463
+ }).catch(() => []);
1464
+ for (const e of [...entries].sort((a, b) => cmp2(a.name, b.name))) {
1465
+ const p = rel ? `${rel}/${e.name}` : e.name;
1466
+ if (e.isDirectory()) {
1467
+ if (!SKIP.has(e.name) && !e.name.startsWith("."))
1468
+ await walk2(p);
1469
+ } else if (e.isFile() && SPEC_FILE.test(e.name)) {
1470
+ const size = (await stat(join(dir, ...p.split("/"))).catch(() => void 0))?.size;
1471
+ out.push({ path: p, size: size ?? 0 });
1472
+ }
1473
+ }
1474
+ };
1475
+ await walk2("");
1476
+ return out;
1477
+ },
1478
+ read: (p) => readFile(join(dir, ...p.split("/")), "utf8").catch(() => void 0)
1479
+ };
1480
+ }
1481
+ async function readRepoSpecs(dir, o) {
1482
+ const tree = o.tree ?? folderTree(dir);
1483
+ const files = (await tree.files()).filter((f) => SPEC_FILE.test(f.path) && !skipped(f.path) && f.size > 0 && f.size <= MAX_BYTES).sort((a, b) => cmpPath(a.path, b.path)).map((f) => f.path);
1484
+ const own = o.facts.filter((f) => f.kind === "entry" && f.entryType === "rest");
1485
+ const specs = [];
1486
+ for (const p of files) {
1487
+ const text3 = await tree.read(p);
1488
+ if (text3 === void 0 || !specFormatOf(p, text3))
1489
+ continue;
1490
+ const got = readContractSpecs(p, text3);
1491
+ if (!got.length)
1492
+ continue;
1493
+ if (o.denyHashes?.size && denyListHits(text3, o.denyHashes).length) {
1494
+ o.onRefused?.(`${p}: the deny-list names a word in it, so its specs are left out.`);
1495
+ continue;
1496
+ }
1497
+ for (const s of got) {
1498
+ if (s.kind !== "operation") {
1499
+ specs.push(s);
1500
+ continue;
1501
+ }
1502
+ const vendorPath = readVendorSpec(p, text3, "spec")?.operations.find((x) => x.id === s.id);
1503
+ const paths = [s.path ?? "", vendorPath?.path ?? ""].filter(Boolean);
1504
+ const entry = own.filter((e) => (!e.method || !s.method || e.method.toUpperCase() === s.method) && paths.some((x) => sameShape(x, e.path))).sort((a, b) => cmp2(a.id, b.id))[0];
1505
+ const { id: _id, ...rest } = s;
1506
+ specs.push(entry ? { ...rest, role: "own", entry: entry.id } : rest);
1507
+ }
1508
+ }
1509
+ return {
1510
+ schemaVersion: 1,
1511
+ repo: o.repo,
1512
+ ...o.commit ? { commit: o.commit } : {},
1513
+ specs
1514
+ };
1515
+ }
1516
+
778
1517
  // packages/intake/dist/scan-inputs.js
779
1518
  var SPECS = ["openapi", "swagger", "asyncapi"];
780
1519
  var EVIDENCE_SOURCE = {
781
1520
  openapi: "spec",
782
1521
  swagger: "spec",
783
1522
  asyncapi: "spec",
1523
+ protobuf: "spec",
1524
+ avro: "spec",
784
1525
  diagram: "diagram",
785
1526
  image: "document",
786
1527
  document: "document",
@@ -798,14 +1539,14 @@ async function walk(dir, skip) {
798
1539
  return;
799
1540
  let entries;
800
1541
  try {
801
- entries = await readdir(d, { withFileTypes: true });
1542
+ entries = await readdir2(d, { withFileTypes: true });
802
1543
  } catch {
803
1544
  return;
804
1545
  }
805
1546
  for (const e of entries.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
806
1547
  if (e.name.startsWith("."))
807
1548
  continue;
808
- const full = join(d, e.name);
1549
+ const full = join2(d, e.name);
809
1550
  if (e.isDirectory())
810
1551
  await go(full);
811
1552
  else if (e.isFile())
@@ -816,7 +1557,7 @@ async function walk(dir, skip) {
816
1557
  return out;
817
1558
  }
818
1559
  var DATE = /(?:^|[-_ .])((\d{4})-?(\d{2})-?(\d{2}))(?=$|[-_ .])/;
819
- var VERSION = /(?:^|[-_ .])v(\d+(?:[._]\d+)*)(?=$|[-_ .])/i;
1560
+ var VERSION2 = /(?:^|[-_ .])v(\d+(?:[._]\d+)*)(?=$|[-_ .])/i;
820
1561
  function nameParts(stem) {
821
1562
  let rest = stem;
822
1563
  let date;
@@ -829,7 +1570,7 @@ function nameParts(stem) {
829
1570
  }
830
1571
  }
831
1572
  let version;
832
- const v = VERSION.exec(rest);
1573
+ const v = VERSION2.exec(rest);
833
1574
  if (v) {
834
1575
  version = v[1].replace(/_/g, ".");
835
1576
  rest = rest.replace(v[0], "");
@@ -855,23 +1596,23 @@ function systemsInName(stem, systems) {
855
1596
  return systems.filter((sys) => [sys.id, sys.name, ...sys.aliases].some((n) => slug(n) && s.includes(`-${slug(n)}-`))).map((sys) => sys.id).sort();
856
1597
  }
857
1598
  async function scanInputs(o) {
858
- const orgPackDir = typeof o.orgPack === "string" ? o.orgPack : join(orgPackDirOf(o.root));
1599
+ const orgPackDir = typeof o.orgPack === "string" ? o.orgPack : join2(orgPackDirOf(o.root));
859
1600
  const op = typeof o.orgPack === "object" ? o.orgPack : await loadOrgPack(orgPackDir);
860
1601
  const systems = op.profiles.flatMap((p) => p.profile?.systems ?? []);
861
1602
  const legend = op.profiles.find((p) => p.profile?.legend)?.profile?.legend;
862
1603
  const records = o.records ?? [];
863
1604
  const ingestors = o.ingestors ?? [drawioIngestor];
864
1605
  const scannedAt = o.scannedAt ?? (/* @__PURE__ */ new Date()).toISOString();
865
- const inputsDir = o.inputsDir ?? join(o.root, "inputs");
1606
+ const inputsDir = o.inputsDir ?? join2(o.root, "inputs");
866
1607
  const problems = [];
867
1608
  const triage = [];
868
1609
  const authors = /* @__PURE__ */ new Map();
869
1610
  const wikiDirs = op.sources.wikis.flatMap((w) => /^[a-z][a-z0-9+.-]*:\/\//i.test(w.location) ? [] : [resolve(orgPackDir, w.location), resolve(o.root, w.location)]);
870
- const st = await stat(inputsDir).catch(() => void 0);
1611
+ const st = await stat2(inputsDir).catch(() => void 0);
871
1612
  const paths = st?.isDirectory() ? await walk(inputsDir, wikiDirs) : [];
872
1613
  const files = [];
873
1614
  for (const abs of paths) {
874
- const bytes = new Uint8Array(await readFile(abs));
1615
+ const bytes = new Uint8Array(await readFile2(abs));
875
1616
  const path = `inputs/${posix(relative(inputsDir, abs))}`;
876
1617
  const name = path.split("/").pop();
877
1618
  const c = classify(name, bytes);
@@ -879,7 +1620,7 @@ async function scanInputs(o) {
879
1620
  abs,
880
1621
  path,
881
1622
  bytes,
882
- hash: createHash4("sha256").update(bytes).digest("hex"),
1623
+ hash: createHash5("sha256").update(bytes).digest("hex"),
883
1624
  stem: name.includes(".") ? name.slice(0, name.lastIndexOf(".")) : name,
884
1625
  inbox: path.startsWith("inputs/inbox/"),
885
1626
  ...c.data !== void 0 ? { data: c.data } : {},
@@ -949,7 +1690,7 @@ async function scanInputs(o) {
949
1690
  const heads = members.filter((m) => !m.doc.supersededBy);
950
1691
  if (heads.length < 2)
951
1692
  continue;
952
- const distinct = (vals, cmp4) => vals.every((v) => v !== void 0) && vals.every((v, i) => vals.every((w, j) => i === j || cmp4(v, w) !== 0));
1693
+ const distinct = (vals, cmp5) => vals.every((v) => v !== void 0) && vals.every((v, i) => vals.every((w, j) => i === j || cmp5(v, w) !== 0));
953
1694
  const byVersion = distinct(heads.map((h) => h.doc.version), compareVersions);
954
1695
  const byDate = !byVersion && distinct(heads.map((h) => h.doc.date), (a, b) => a < b ? -1 : a > b ? 1 : 0);
955
1696
  if (byVersion || byDate) {
@@ -1106,6 +1847,43 @@ async function scanInputs(o) {
1106
1847
  } catch {
1107
1848
  }
1108
1849
  }
1850
+ if (cls === "protobuf" || cls === "avro") {
1851
+ const specs = cls === "protobuf" ? readProtoSpecs(f.path, text3()) : readAvroSpecs(f.path, text3());
1852
+ const named = new Set(systemsInName(f.stem, systems));
1853
+ for (const s of specs) {
1854
+ const res = s.name ? resolveName(s.name.split(".").slice(0, -1).join(" ")) : void 0;
1855
+ if (res?.id && !named.size)
1856
+ named.add(systemOf(res.id));
1857
+ }
1858
+ for (const s of named)
1859
+ linked.add(s);
1860
+ if (current && specs.length) {
1861
+ for (const s of specs) {
1862
+ const p = parseRecord({
1863
+ schemaVersion: 1,
1864
+ kind: "Schema",
1865
+ id: boundedId("schema.", slug(s.name ?? f.stem)),
1866
+ status: "current",
1867
+ confidence: "verified",
1868
+ format: cls,
1869
+ ref: `${f.path}#${s.name ?? ""}`,
1870
+ fields: s.fields.map((x) => ({
1871
+ name: x.name,
1872
+ ...x.type ? { type: x.type } : {},
1873
+ ...x.required !== void 0 ? { required: x.required } : {}
1874
+ })),
1875
+ evidence: [{ source: "spec", path: f.path, line: s.line, side: "definition" }]
1876
+ });
1877
+ if (!p.ok)
1878
+ continue;
1879
+ const schema = p.record;
1880
+ out.push(schema);
1881
+ f.doc.records.push(schema.id);
1882
+ }
1883
+ f.doc.status = "read";
1884
+ f.doc.reader = cls === "protobuf" ? READERS.protobuf : READERS.avro;
1885
+ }
1886
+ }
1109
1887
  if (current && cls === "payload" && f.data !== void 0) {
1110
1888
  const schema = readPayload(f.path, boundedId("payload.", f.doc.id.slice(4)), f.data);
1111
1889
  out.push(schema);
@@ -1415,11 +2193,11 @@ function imageItems(records) {
1415
2193
  };
1416
2194
  });
1417
2195
  }
1418
- var key = (action, target, value) => `${action}|${target}|${JSON.stringify(value ?? null)}`;
2196
+ var key2 = (action, target, value) => `${action}|${target}|${JSON.stringify(value ?? null)}`;
1419
2197
  function buildTriage(input) {
1420
2198
  const decisions = (input.decisions ?? []).filter((d) => d.kind === "CuratedDecision" && d.status === "current");
1421
2199
  const decidedIds = new Set(decisions.map((d) => d.id));
1422
- const decidedKeys = new Set(decisions.map((d) => key(d.action, d.target, d.value)));
2200
+ const decidedKeys = new Set(decisions.map((d) => key2(d.action, d.target, d.value)));
1423
2201
  const docs = new Map((input.inputs?.documents ?? []).map((d) => [d.path, d.id]));
1424
2202
  const docIdOf = (path) => docs.get(path) ?? boundedId("doc.", slug(path.split("/").pop().replace(/\.[^.]+$/, "")));
1425
2203
  const records = input.records;
@@ -1432,7 +2210,7 @@ function buildTriage(input) {
1432
2210
  ...imageItems([...records, ...inputRecords]),
1433
2211
  ...readingItems(input)
1434
2212
  ];
1435
- const open = all.filter((i) => !i.options.some((o) => decidedIds.has(o.decision.id) || decidedKeys.has(key(o.decision.action, o.decision.target, o.decision.value))));
2213
+ const open = all.filter((i) => !i.options.some((o) => decidedIds.has(o.decision.id) || decidedKeys.has(key2(o.decision.action, o.decision.target, o.decision.value))));
1436
2214
  const items = sortItems(open);
1437
2215
  return {
1438
2216
  items,
@@ -1473,9 +2251,9 @@ function buildTriage(input) {
1473
2251
  }
1474
2252
 
1475
2253
  // packages/intake/dist/work-items.js
1476
- var import_yaml4 = __toESM(require_dist(), 1);
1477
- import { readdir as readdir2, readFile as readFile2 } from "node:fs/promises";
1478
- import { join as join2, relative as relative2, sep as sep2 } from "node:path";
2254
+ var import_yaml5 = __toESM(require_dist(), 1);
2255
+ import { readdir as readdir3, readFile as readFile3 } from "node:fs/promises";
2256
+ import { join as join3, relative as relative2, sep as sep2 } from "node:path";
1479
2257
  var WORK_ITEM_READER = "work-items@0.1.0";
1480
2258
  var isObj3 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
1481
2259
  var text = (v) => {
@@ -1654,7 +2432,7 @@ function readWorkItemExport(path, bytes) {
1654
2432
  return void 0;
1655
2433
  let data;
1656
2434
  try {
1657
- data = (0, import_yaml4.parse)(content);
2435
+ data = (0, import_yaml5.parse)(content);
1658
2436
  } catch {
1659
2437
  return void 0;
1660
2438
  }
@@ -1677,19 +2455,19 @@ function readWorkItemExport(path, bytes) {
1677
2455
  return items;
1678
2456
  }
1679
2457
  async function readWorkItemExports(o) {
1680
- const dir = o.inputsDir ?? join2(o.root, "inputs");
2458
+ const dir = o.inputsDir ?? join3(o.root, "inputs");
1681
2459
  const files = [];
1682
2460
  async function walk2(d) {
1683
2461
  let entries;
1684
2462
  try {
1685
- entries = await readdir2(d, { withFileTypes: true });
2463
+ entries = await readdir3(d, { withFileTypes: true });
1686
2464
  } catch {
1687
2465
  return;
1688
2466
  }
1689
2467
  for (const e of entries.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
1690
2468
  if (e.name.startsWith("."))
1691
2469
  continue;
1692
- const full = join2(d, e.name);
2470
+ const full = join3(d, e.name);
1693
2471
  if (e.isDirectory())
1694
2472
  await walk2(full);
1695
2473
  else if (/\.(json|ya?ml|csv)$/i.test(e.name))
@@ -1706,7 +2484,7 @@ async function readWorkItemExports(o) {
1706
2484
  const path = `inputs/${relative2(dir, full).split(sep2).join("/")}`;
1707
2485
  let bytes;
1708
2486
  try {
1709
- bytes = new Uint8Array(await readFile2(full));
2487
+ bytes = new Uint8Array(await readFile3(full));
1710
2488
  } catch (e) {
1711
2489
  out.problems.push({ path, message: `can't read it: ${e.message}` });
1712
2490
  continue;
@@ -1721,9 +2499,9 @@ async function readWorkItemExports(o) {
1721
2499
  }
1722
2500
 
1723
2501
  // packages/intake/dist/service-requests.js
1724
- var import_yaml5 = __toESM(require_dist(), 1);
1725
- import { readdir as readdir3, readFile as readFile3 } from "node:fs/promises";
1726
- import { join as join3, relative as relative3, sep as sep3 } from "node:path";
2502
+ var import_yaml6 = __toESM(require_dist(), 1);
2503
+ import { readdir as readdir4, readFile as readFile4 } from "node:fs/promises";
2504
+ import { join as join4, relative as relative3, sep as sep3 } from "node:path";
1727
2505
  var SERVICE_REQUEST_READER = "service-requests@0.1.0";
1728
2506
  var isObj4 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
1729
2507
  var text2 = (v) => {
@@ -1874,7 +2652,7 @@ function readServiceRequestExport(path, bytes) {
1874
2652
  return void 0;
1875
2653
  let data;
1876
2654
  try {
1877
- data = (0, import_yaml5.parse)(content);
2655
+ data = (0, import_yaml6.parse)(content);
1878
2656
  } catch {
1879
2657
  return void 0;
1880
2658
  }
@@ -1904,19 +2682,19 @@ function readServiceRequestExport(path, bytes) {
1904
2682
  return out;
1905
2683
  }
1906
2684
  async function readServiceRequestExports(o) {
1907
- const dir = o.inputsDir ?? join3(o.root, "inputs");
2685
+ const dir = o.inputsDir ?? join4(o.root, "inputs");
1908
2686
  const found = [];
1909
2687
  async function walk2(d) {
1910
2688
  let entries;
1911
2689
  try {
1912
- entries = await readdir3(d, { withFileTypes: true });
2690
+ entries = await readdir4(d, { withFileTypes: true });
1913
2691
  } catch {
1914
2692
  return;
1915
2693
  }
1916
2694
  for (const e of entries.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
1917
2695
  if (e.name.startsWith("."))
1918
2696
  continue;
1919
- const full = join3(d, e.name);
2697
+ const full = join4(d, e.name);
1920
2698
  if (e.isDirectory())
1921
2699
  await walk2(full);
1922
2700
  else if (/\.(json|ya?ml|csv)$/i.test(e.name))
@@ -1933,7 +2711,7 @@ async function readServiceRequestExports(o) {
1933
2711
  const path = `inputs/${relative3(dir, full).split(sep3).join("/")}`;
1934
2712
  let bytes;
1935
2713
  try {
1936
- bytes = new Uint8Array(await readFile3(full));
2714
+ bytes = new Uint8Array(await readFile4(full));
1937
2715
  } catch (e) {
1938
2716
  out.problems.push({ path, message: `can't read it: ${e.message}` });
1939
2717
  continue;
@@ -1948,15 +2726,15 @@ async function readServiceRequestExports(o) {
1948
2726
  }
1949
2727
 
1950
2728
  // packages/intake/dist/change-inputs.js
1951
- var import_yaml6 = __toESM(require_dist(), 1);
1952
- import { createHash as createHash5 } from "node:crypto";
1953
- import { mkdir, readdir as readdir4, readFile as readFile4 } from "node:fs/promises";
1954
- import { join as join4 } from "node:path";
2729
+ var import_yaml7 = __toESM(require_dist(), 1);
2730
+ import { createHash as createHash6 } from "node:crypto";
2731
+ import { mkdir, readdir as readdir5, readFile as readFile5 } from "node:fs/promises";
2732
+ import { join as join5 } from "node:path";
1955
2733
  var INPUTS_DIR = "inputs";
1956
2734
  var INPUTS_INDEX = "inputs/index.yaml";
1957
2735
  var INPUTS_READ_DIR = "inputs/read";
1958
2736
  var CHANGE_INPUTS_SCHEMA_VERSION = 1;
1959
- var sha256 = (b) => createHash5("sha256").update(b).digest("hex");
2737
+ var sha256 = (b) => createHash6("sha256").update(b).digest("hex");
1960
2738
  var KEYS = [
1961
2739
  "path",
1962
2740
  "name",
@@ -1976,10 +2754,10 @@ var KEYS = [
1976
2754
  "defences"
1977
2755
  ];
1978
2756
  async function readChangeInputs(dir) {
1979
- const text3 = await readFile4(join4(dir, ...INPUTS_INDEX.split("/")), "utf8").catch(() => "");
2757
+ const text3 = await readFile5(join5(dir, ...INPUTS_INDEX.split("/")), "utf8").catch(() => "");
1980
2758
  let data;
1981
2759
  try {
1982
- data = text3 ? (0, import_yaml6.parse)(text3) : void 0;
2760
+ data = text3 ? (0, import_yaml7.parse)(text3) : void 0;
1983
2761
  } catch {
1984
2762
  data = void 0;
1985
2763
  }
@@ -2000,7 +2778,7 @@ async function writeIndex(dir, index) {
2000
2778
  o[k] = f[k];
2001
2779
  return o;
2002
2780
  });
2003
- await writeFileAtomic(join4(dir, ...INPUTS_INDEX.split("/")), `# Files attached to this change (ADR 0113): atticus change attach writes this file.
2781
+ await writeFileAtomic(join5(dir, ...INPUTS_INDEX.split("/")), `# Files attached to this change (ADR 0113): atticus change attach writes this file.
2004
2782
  ${toCanonicalYaml({ schemaVersion: index.schemaVersion, files }, ["schemaVersion", "files"])}`);
2005
2783
  }
2006
2784
  var isText = (b) => {
@@ -2091,7 +2869,7 @@ function readText(input, bytes, older) {
2091
2869
  async function attachToChange(dir, files, o) {
2092
2870
  const index = await readChangeInputs(dir);
2093
2871
  const out = { added: [], refused: [], notes: [] };
2094
- const taken = new Set(await readdir4(join4(dir, INPUTS_DIR)).catch(() => []));
2872
+ const taken = new Set(await readdir5(join5(dir, INPUTS_DIR)).catch(() => []));
2095
2873
  taken.add("index.yaml").add("read");
2096
2874
  const replaced = o.replaces ? index.files.find((x) => x.path === o.replaces.trim().replace(/\\/g, "/")) : void 0;
2097
2875
  let changed = false;
@@ -2178,11 +2956,11 @@ async function attachToChange(dir, files, o) {
2178
2956
  const where = o.elsewhere?.(hash);
2179
2957
  if (where)
2180
2958
  out.notes.push(`${name} is also in the metarepo's inputs as ${where}.`);
2181
- await mkdir(join4(dir, INPUTS_DIR), { recursive: true });
2182
- await writeFileAtomic(join4(dir, INPUTS_DIR, target), f.bytes);
2959
+ await mkdir(join5(dir, INPUTS_DIR), { recursive: true });
2960
+ await writeFileAtomic(join5(dir, INPUTS_DIR, target), f.bytes);
2183
2961
  const text3 = readText(input, f.bytes, older);
2184
2962
  if (text3 !== void 0)
2185
- await writeFileAtomic(join4(dir, ...input.readAs.split("/")), text3);
2963
+ await writeFileAtomic(join5(dir, ...input.readAs.split("/")), text3);
2186
2964
  index.files.push(input);
2187
2965
  out.added.push(input);
2188
2966
  }
@@ -2208,7 +2986,7 @@ async function changeInputSources(dir, rel) {
2208
2986
  for (const f of (await readChangeInputs(dir)).files) {
2209
2987
  if (f.supersededBy || f.defences?.risk === "high")
2210
2988
  continue;
2211
- const read = f.readAs ? await readFile4(join4(dir, ...f.readAs.split("/")), "utf8").catch(() => void 0) : void 0;
2989
+ const read = f.readAs ? await readFile5(join5(dir, ...f.readAs.split("/")), "utf8").catch(() => void 0) : void 0;
2212
2990
  const text3 = read ?? `${f.path} (${f.name}) is ${f.kind === "image" ? "a picture; Atticus doesn't read pictures" : `a ${f.format} file no reader takes`}. Open it to see it; say what you rely on from it, citing ${f.path}.`;
2213
2991
  out.push({
2214
2992
  id: f.path,
@@ -2237,7 +3015,7 @@ var KIND_ORDER2 = [
2237
3015
  "error-schema",
2238
3016
  "error-removed"
2239
3017
  ];
2240
- var cmp = (a, b) => a < b ? -1 : a > b ? 1 : 0;
3018
+ var cmp3 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
2241
3019
  var opKey = (o) => `${o.method} ${normalizePath(o.fullPath)}`;
2242
3020
  var opName = (o) => `${o.method} ${o.path}`;
2243
3021
  var list = (xs) => xs.length <= 1 ? xs[0] ?? "" : `${xs.slice(0, -1).join(", ")} and ${xs.at(-1)}`;
@@ -2302,7 +3080,7 @@ function diffVendorSpecs(older, newer) {
2302
3080
  });
2303
3081
  for (const [o, n] of pairs)
2304
3082
  out.push(...operationChanges(o, n));
2305
- return out.sort((a, b) => cmp(a.severity === "breaking" ? "0" : "1", b.severity === "breaking" ? "0" : "1") || cmp(a.operation.path, b.operation.path) || cmp(a.operation.method, b.operation.method) || KIND_ORDER2.indexOf(a.kind) - KIND_ORDER2.indexOf(b.kind) || cmp(a.side ?? "", b.side ?? "") || cmp(a.field ?? "", b.field ?? ""));
3083
+ return out.sort((a, b) => cmp3(a.severity === "breaking" ? "0" : "1", b.severity === "breaking" ? "0" : "1") || cmp3(a.operation.path, b.operation.path) || cmp3(a.operation.method, b.operation.method) || KIND_ORDER2.indexOf(a.kind) - KIND_ORDER2.indexOf(b.kind) || cmp3(a.side ?? "", b.side ?? "") || cmp3(a.field ?? "", b.field ?? ""));
2306
3084
  }
2307
3085
  var opOf = (o) => ({
2308
3086
  method: o.method,
@@ -2493,7 +3271,7 @@ function fieldChanges(olds, news, side, at, base) {
2493
3271
 
2494
3272
  // packages/intake/dist/vendor-impact.js
2495
3273
  var MAX_UPSTREAM = 4;
2496
- var cmp2 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
3274
+ var cmp4 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
2497
3275
  var sorted = (xs) => [...new Set(xs)].sort();
2498
3276
  var joinVendorOf = (input, spec) => ({
2499
3277
  system: input.vendor.system,
@@ -2516,7 +3294,7 @@ var versionOf = (v) => ({
2516
3294
  function vendorImpact(input) {
2517
3295
  const diff = diffVendorSpecs(input.older.spec, input.newer.spec);
2518
3296
  const bundle = input.bundleFolders ? { bundleFolders: input.bundleFolders } : {};
2519
- const join6 = joinFacts({
3297
+ const join7 = joinFacts({
2520
3298
  repos: input.repos,
2521
3299
  ...input.targets ? { targets: input.targets } : {},
2522
3300
  ...input.facing ? { facing: input.facing } : {},
@@ -2556,8 +3334,8 @@ function vendorImpact(input) {
2556
3334
  const f = facts.get(k(call))?.fact;
2557
3335
  return f?.kind === "call" && f.from ? endOf(call.repo, f.from) : void 0;
2558
3336
  };
2559
- const hops = new Set(join6.joins.flatMap((j) => (j.gateway ?? []).map((h) => k(h.call))));
2560
- const joins = join6.joins.filter((j) => j.how !== "topic" && !hops.has(k(j.call)));
3337
+ const hops = new Set(join7.joins.flatMap((j) => (j.gateway ?? []).map((h) => k(h.call))));
3338
+ const joins = join7.joins.filter((j) => j.how !== "topic" && !hops.has(k(j.call)));
2561
3339
  const via = (j) => j.gateway?.length ? { via: j.gateway.map((h) => h.route) } : {};
2562
3340
  const upstreamOf = (start) => {
2563
3341
  const out = [];
@@ -2586,422 +3364,121 @@ function vendorImpact(input) {
2586
3364
  }
2587
3365
  return out;
2588
3366
  };
2589
- const fieldUse = (call, change) => {
2590
- if (!change.side || !change.field || change.status)
2591
- return void 0;
2592
- const side = change.side;
2593
- const mine = (input.repos.find((r) => r.repo === call.repo)?.facts ?? []).filter((f) => f.kind === "field" && f.owner === call.fact && (f.side ?? "request") === side).sort((a, b) => cmp2(a.id, b.id));
2594
- if (!mine.length)
2595
- return void 0;
2596
- const want = fieldNameKey(change.field);
2597
- const hit = mine.find((f) => fieldNameKey(f.name) === want);
2598
- const req = side === "request";
2599
- return hit ? { uses: req ? "sends" : "reads", at: `${hit.cite.file}:${hit.cite.line}` } : { uses: req ? "does-not-send" : "does-not-read" };
2600
- };
2601
- const changes = diff.map((c) => {
2602
- const older = c.endpoints.older;
2603
- const matches = older ? today.matches.filter((m) => m.operation === older) : next.matches.filter((m) => m.operation === c.endpoints.newer);
2604
- const forwards = matches.map((m) => {
2605
- if (m.direct) {
2606
- const f = facts.get(k(m.call))?.fact;
2607
- const field2 = fieldUse(m.call, c);
2608
- const self = {
2609
- call: m.call,
2610
- interface: interfaceId(m.call.component, factIdPart(f?.to ?? input.vendor.system), m.method, m.path),
2611
- ...field2 ? { field: field2 } : {},
2612
- ...m.route ? { under: m.route } : {},
2613
- upstream: upstreamOf(m.route)
2614
- };
2615
- return {
2616
- call: m.call,
2617
- ...m.route ? { route: m.route } : {},
2618
- operation: m.operation,
2619
- direct: true,
2620
- callers: [self]
2621
- };
2622
- }
2623
- const callers = m.route ? joins.filter((j) => k(j.entry) === k(m.route) || (j.gateway ?? []).some((h) => k(h.entry) === k(m.route))).map((j) => {
2624
- const u = under(j.call);
2625
- const field2 = fieldUse(j.call, c);
2626
- return {
2627
- call: j.call,
2628
- interface: j.interface,
2629
- ...via(j),
2630
- ...field2 ? { field: field2 } : {},
2631
- ...u ? { under: u } : {},
2632
- upstream: upstreamOf(u)
2633
- };
2634
- }) : [];
2635
- return {
2636
- call: m.call,
2637
- ...m.route ? { route: m.route } : {},
2638
- ...m.tie ? { tie: m.tie } : {},
2639
- operation: m.operation,
2640
- callers
2641
- };
2642
- });
2643
- return { id: c.id, severity: c.severity, says: c.says, forwards };
2644
- });
2645
- const repos = /* @__PURE__ */ new Set();
2646
- const interfaces = /* @__PURE__ */ new Set();
2647
- const endpoints = /* @__PURE__ */ new Set();
2648
- const entries = /* @__PURE__ */ new Set();
2649
- for (const c of changes)
2650
- for (const f of c.forwards) {
2651
- repos.add(f.call.repo);
2652
- endpoints.add(f.operation);
2653
- for (const s of f.callers) {
2654
- repos.add(s.call.repo);
2655
- interfaces.add(s.interface);
2656
- if (s.under)
2657
- entries.add(k(s.under));
2658
- for (const u of s.upstream) {
2659
- repos.add(u.call.repo);
2660
- interfaces.add(u.interface);
2661
- entries.add(k(u.reaches));
2662
- if (u.under)
2663
- entries.add(k(u.under));
2664
- }
2665
- }
2666
- }
2667
- const endpointIds = /* @__PURE__ */ new Set();
2668
- for (const e of entries) {
2669
- const got = facts.get(e);
2670
- if (got?.fact.kind === "entry")
2671
- endpointIds.add(entryEndpointId(got.fact, componentOf(got.repo, got.fact)));
2672
- }
2673
- const flows = (input.flows ?? []).filter((f) => f.trigger && endpointIds.has(f.trigger) || (f.refs ?? []).some((r) => endpointIds.has(r))).map((f) => ({ id: f.id, repo: f.repo })).sort((a, b) => cmp2(a.id, b.id));
2674
- for (const f of flows)
2675
- repos.add(f.repo);
2676
- const systems = /* @__PURE__ */ new Set([input.vendor.system]);
2677
- for (const r of repos) {
2678
- const s = input.systemOfRepo?.[r];
2679
- if (s)
2680
- systems.add(s);
2681
- }
2682
- return {
2683
- diff,
2684
- impact: {
2685
- vendor: input.vendor.system,
2686
- older: versionOf(input.older),
2687
- newer: versionOf(input.newer),
2688
- changes,
2689
- repos: sorted(repos),
2690
- systems: sorted(systems),
2691
- flows,
2692
- interfaces: sorted(interfaces),
2693
- endpoints: sorted(endpoints),
2694
- gaps: today.gaps,
2695
- asks: today.asks
2696
- }
2697
- };
2698
- }
2699
-
2700
- // packages/intake/dist/contract-files.js
2701
- var import_yaml7 = __toESM(require_dist(), 1);
2702
- import { readdir as readdir5, readFile as readFile5, stat as stat2 } from "node:fs/promises";
2703
- import { join as join5 } from "node:path";
2704
-
2705
- // packages/intake/dist/traffic.js
2706
- import { createHash as createHash6 } from "node:crypto";
2707
- var cmp3 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
2708
- var key2 = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
2709
- var sha = (s) => createHash6("sha256").update(s, "utf8").digest("hex");
2710
- var IPV4 = /\b\d{1,3}(?:\.\d{1,3}){3}\b/;
2711
- var IPV6 = /[0-9a-f]{0,4}::[0-9a-f]{0,4}|\b[0-9a-f]{1,4}(?::[0-9a-f]{1,4}){2,7}\b/i;
2712
- var EMAIL = /[^\s@/]+@[^\s@/]+/;
2713
- var JWT = /\beyJ[A-Za-z0-9_-]{6,}/;
2714
- var OPAQUE = /\b(?=[A-Za-z0-9+_-]*\d)(?=[A-Za-z0-9+_-]*[A-Za-z])[A-Za-z0-9+_-]{24,}={0,2}/;
2715
- var UUID = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i;
2716
- var HEX = /\b[0-9a-f]{16,}\b/i;
2717
- function looksSensitive(v) {
2718
- return [IPV4, IPV6, EMAIL, JWT, OPAQUE, UUID, HEX].some((re) => re.test(v));
2719
- }
2720
- function rowsOf(text3) {
2721
- const t = text3.replace(/^\uFEFF/, "").trim();
2722
- if (!t)
2723
- return void 0;
2724
- if (t.startsWith("[") || t.startsWith("{")) {
2725
- let v;
2726
- try {
2727
- v = JSON.parse(t);
2728
- } catch {
2729
- return void 0;
2730
- }
2731
- const list2 = Array.isArray(v) ? v : v && typeof v === "object" ? ["rows", "data", "records", "items"].map((k) => v[k]).find((x) => Array.isArray(x)) : void 0;
2732
- if (!Array.isArray(list2) || !list2.length)
2733
- return void 0;
2734
- const out = [];
2735
- for (const r of list2) {
2736
- if (!r || typeof r !== "object" || Array.isArray(r))
2737
- return void 0;
2738
- const row = {};
2739
- for (const [k, x] of Object.entries(r))
2740
- if (typeof x === "string" || typeof x === "number")
2741
- row[k] = String(x);
2742
- out.push(row);
2743
- }
2744
- return out;
2745
- }
2746
- const recs = parseCsv(t);
2747
- if (recs.length < 2)
2748
- return void 0;
2749
- const head = recs[0].cells.map((c) => c.trim());
2750
- if (head.length < 2)
2751
- return void 0;
2752
- return recs.slice(1).map((r) => {
2753
- const row = {};
2754
- head.forEach((h, i) => row[h] = (r.cells[i] ?? "").trim());
2755
- return row;
2756
- });
2757
- }
2758
- function dayOf(v) {
2759
- const m = /^(\d{4}-\d{2}-\d{2})/.exec(v.trim());
2760
- if (m)
2761
- return m[1];
2762
- if (/^\d{12,13}$/.test(v.trim()))
2763
- return new Date(Number(v)).toISOString().slice(0, 10);
2764
- return void 0;
2765
- }
2766
- var VERSION2 = /^v\d+(?:\.\d+)*$/i;
2767
- var PARAM = /^(?:\{[A-Za-z_][A-Za-z0-9_.-]{0,40}\}|:[A-Za-z_][A-Za-z0-9_]{0,40}|<[A-Za-z_][A-Za-z0-9_:]{0,40}>)$/;
2768
- var segmentOf = (s) => VERSION2.test(s) || PARAM.test(s) || /^[a-z][a-z._-]*$/.test(s) && s.length <= 20 && /[aeiou]/.test(s) && !looksSensitive(s) ? s : "{id}";
2769
- function barePath(path) {
2770
- let p = path.trim().split(/[?#]/, 1)[0] ?? "";
2771
- p = p.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]*/i, "");
2772
- return p.replace(/;[^/]*/g, "");
2773
- }
2774
- function safePathOf(path) {
2775
- const p = barePath(path);
2776
- if (!p.startsWith("/"))
2777
- return void 0;
2778
- return `/${p.split("/").filter(Boolean).map(segmentOf).join("/")}`;
2779
- }
2780
- var MATCH = 100;
2781
- function pathTemplateOf(path, templates) {
2782
- const p = barePath(path);
2783
- if (!p.startsWith("/"))
2784
- return void 0;
2785
- const sorted2 = [...templates].sort();
2786
- let best;
2787
- let score = 0;
2788
- for (const t of sorted2) {
2789
- const s = routeScore(p, t);
2790
- if (s > MATCH && s > score) {
2791
- score = s;
2792
- best = t;
2793
- }
2794
- }
2795
- if (best)
2796
- return best;
2797
- const segs = p.split("/").filter(Boolean);
2798
- let prefix;
2799
- let len = 0;
2800
- score = 0;
2801
- for (const t of sorted2) {
2802
- const n = t.split("/").filter(Boolean).length;
2803
- if (n === 0 || n >= segs.length || n < len)
2804
- continue;
2805
- const s = routeScore(`/${segs.slice(0, n).join("/")}`, t);
2806
- if (s <= MATCH)
2807
- continue;
2808
- if (n > len || s > score) {
2809
- len = n;
2810
- score = s;
2811
- prefix = t;
2812
- }
2813
- }
2814
- return prefix ? `${prefix.replace(/\/+$/, "")}/**` : void 0;
2815
- }
2816
- var appLabelOf = (name) => `app-${sha(name).slice(0, 8)}`;
2817
- function denyListHits(text3, hashes) {
2818
- const hits = [];
2819
- text3.toLowerCase().split("\n").forEach((line, i) => {
2820
- const w = line.match(/[a-z0-9]+/g) ?? [];
2821
- for (let k = 0; k < w.length; k++)
2822
- if (hashes.has(sha(w[k])) || k + 1 < w.length && hashes.has(sha(`${w[k]} ${w[k + 1]}`))) {
2823
- hits.push(i + 1);
2824
- break;
2825
- }
2826
- });
2827
- return hits;
2828
- }
2829
- function aggregateTraffic(input) {
2830
- const text3 = Buffer.from(input.bytes).toString("utf8");
2831
- const rows = rowsOf(text3);
2832
- const shape = `a CSV with a header row, or a JSON list of rows, with an app, a method and a path column (${input.source}: app ${input.columns.app.join("/")}; method ${input.columns.method.join("/")}; path ${[...input.columns.path, ...input.columns.basepath].join("/")})`;
2833
- if (!rows)
2834
- return { ok: false, message: `The file doesn't read as a traffic export: give ${shape}.` };
2835
- const names = [...new Set(rows.flatMap((r) => Object.keys(r)))];
2836
- const col = (aliases) => {
2837
- for (const a of aliases) {
2838
- const hit = names.find((n) => key2(n) === key2(a));
2839
- if (hit)
2840
- return hit;
2841
- }
2842
- return void 0;
2843
- };
2844
- const c = {
2845
- app: col(input.columns.app),
2846
- method: col(input.columns.method),
2847
- basepath: col(input.columns.basepath),
2848
- suffix: col(input.columns.suffix),
2849
- proxy: col(input.columns.proxy),
2850
- count: col(input.columns.count),
2851
- time: col(input.columns.time),
2852
- path: void 0
3367
+ const fieldUse = (call, change) => {
3368
+ if (!change.side || !change.field || change.status)
3369
+ return void 0;
3370
+ const side = change.side;
3371
+ const mine = (input.repos.find((r) => r.repo === call.repo)?.facts ?? []).filter((f) => f.kind === "field" && f.owner === call.fact && (f.side ?? "request") === side).sort((a, b) => cmp4(a.id, b.id));
3372
+ if (!mine.length)
3373
+ return void 0;
3374
+ const want = fieldNameKey(change.field);
3375
+ const hit = mine.find((f) => fieldNameKey(f.name) === want);
3376
+ const req = side === "request";
3377
+ return hit ? { uses: req ? "sends" : "reads", at: `${hit.cite.file}:${hit.cite.line}` } : { uses: req ? "does-not-send" : "does-not-read" };
2853
3378
  };
2854
- if (!c.basepath || !c.suffix)
2855
- c.path = col(input.columns.path);
2856
- const missing = [
2857
- !c.app ? "app" : "",
2858
- !c.method ? "method" : "",
2859
- !c.path && !(c.basepath && c.suffix) ? "path" : ""
2860
- ].filter(Boolean);
2861
- if (missing.length)
2862
- return {
2863
- ok: false,
2864
- message: `The file has no ${missing.join(", ")} column, so it can't be kept as aggregates: give ${shape}.`
2865
- };
2866
- const range = (v) => v && /^\d{4}-\d{2}-\d{2}$/.test(v) ? v : void 0;
2867
- if (input.from && !range(input.from) || input.to && !range(input.to))
2868
- return { ok: false, message: "--from and --to are days: YYYY-MM-DD." };
2869
- if ((!input.from || !input.to) && !c.time)
2870
- return {
2871
- ok: false,
2872
- message: "The export has no date column: give --from and --to (YYYY-MM-DD) for the range it covers."
2873
- };
2874
- const kept = new Set(Object.values(c).filter((x) => !!x));
2875
- const dropped = names.filter((n) => !kept.has(n)).sort();
2876
- const secrets = /* @__PURE__ */ new Set();
2877
- const keptValues = /* @__PURE__ */ new Set();
2878
- const agg = /* @__PURE__ */ new Map();
2879
- let outOfRange = 0;
2880
- let skipped = 0;
2881
- let unmatched = 0;
2882
- const known = /* @__PURE__ */ new Map();
2883
- for (const a of input.apps ?? [])
2884
- if (a.trim() && !known.has(key2(a)))
2885
- known.set(key2(a), a.trim());
2886
- const days = [];
2887
- for (const r of rows) {
2888
- for (const n of dropped) {
2889
- const v = (r[n] ?? "").trim();
2890
- const q = /^(?:[a-z][a-z0-9+.-]*:\/\/|\/)/i.test(v) ? v.split(/[?#]/)[1] ?? "" : v;
2891
- if (q.length >= 6)
2892
- secrets.add(q);
2893
- }
2894
- for (const n of [c.path, c.suffix, c.basepath]) {
2895
- const v = n ? r[n] ?? "" : "";
2896
- const q = v.split(/[?#]/)[1] ?? "";
2897
- if (q.length >= 4)
2898
- secrets.add(q);
2899
- for (const m of (v.split(/[?#]/, 1)[0] ?? "").match(/;[^/]*/g) ?? [])
2900
- if (m.length >= 5)
2901
- secrets.add(m.slice(1));
2902
- }
2903
- if (c.time) {
2904
- const d = dayOf(r[c.time] ?? "");
2905
- if (d) {
2906
- if (input.from && d < input.from || input.to && d > input.to) {
2907
- outOfRange++;
2908
- continue;
3379
+ const changes = diff.map((c) => {
3380
+ const older = c.endpoints.older;
3381
+ const matches = older ? today.matches.filter((m) => m.operation === older) : next.matches.filter((m) => m.operation === c.endpoints.newer);
3382
+ const forwards = matches.map((m) => {
3383
+ if (m.direct) {
3384
+ const f = facts.get(k(m.call))?.fact;
3385
+ const field2 = fieldUse(m.call, c);
3386
+ const self = {
3387
+ call: m.call,
3388
+ interface: interfaceId(m.call.component, factIdPart(f?.to ?? input.vendor.system), m.method, m.path),
3389
+ ...field2 ? { field: field2 } : {},
3390
+ ...m.route ? { under: m.route } : {},
3391
+ upstream: upstreamOf(m.route)
3392
+ };
3393
+ return {
3394
+ call: m.call,
3395
+ ...m.route ? { route: m.route } : {},
3396
+ operation: m.operation,
3397
+ direct: true,
3398
+ callers: [self]
3399
+ };
3400
+ }
3401
+ const callers = m.route ? joins.filter((j) => k(j.entry) === k(m.route) || (j.gateway ?? []).some((h) => k(h.entry) === k(m.route))).map((j) => {
3402
+ const u = under(j.call);
3403
+ const field2 = fieldUse(j.call, c);
3404
+ return {
3405
+ call: j.call,
3406
+ interface: j.interface,
3407
+ ...via(j),
3408
+ ...field2 ? { field: field2 } : {},
3409
+ ...u ? { under: u } : {},
3410
+ upstream: upstreamOf(u)
3411
+ };
3412
+ }) : [];
3413
+ return {
3414
+ call: m.call,
3415
+ ...m.route ? { route: m.route } : {},
3416
+ ...m.tie ? { tie: m.tie } : {},
3417
+ operation: m.operation,
3418
+ callers
3419
+ };
3420
+ });
3421
+ return { id: c.id, severity: c.severity, says: c.says, forwards };
3422
+ });
3423
+ const repos = /* @__PURE__ */ new Set();
3424
+ const interfaces = /* @__PURE__ */ new Set();
3425
+ const endpoints = /* @__PURE__ */ new Set();
3426
+ const entries = /* @__PURE__ */ new Set();
3427
+ for (const c of changes)
3428
+ for (const f of c.forwards) {
3429
+ repos.add(f.call.repo);
3430
+ endpoints.add(f.operation);
3431
+ for (const s of f.callers) {
3432
+ repos.add(s.call.repo);
3433
+ interfaces.add(s.interface);
3434
+ if (s.under)
3435
+ entries.add(k(s.under));
3436
+ for (const u of s.upstream) {
3437
+ repos.add(u.call.repo);
3438
+ interfaces.add(u.interface);
3439
+ entries.add(k(u.reaches));
3440
+ if (u.under)
3441
+ entries.add(k(u.under));
2909
3442
  }
2910
- days.push(d);
2911
- } else if (!input.from || !input.to) {
2912
- skipped++;
2913
- continue;
2914
3443
  }
2915
3444
  }
2916
- const method = (r[c.method] ?? "").trim().toUpperCase();
2917
- const rawPath = c.path ? r[c.path] ?? "" : `${(r[c.basepath] ?? "").replace(/\/+$/, "")}/${(r[c.suffix] ?? "").replace(/^\/+/, "")}`;
2918
- const countText = c.count ? (r[c.count] ?? "").trim() : "1";
2919
- const count = Number(countText);
2920
- if (!/^[A-Z]{3,10}$/.test(method) || !barePath(rawPath).startsWith("/") || !Number.isInteger(count) || count < 0) {
2921
- skipped++;
2922
- continue;
2923
- }
2924
- const path = pathTemplateOf(rawPath, input.templates);
2925
- if (!path) {
2926
- unmatched++;
2927
- continue;
2928
- }
2929
- if (count === 0)
2930
- continue;
2931
- const appRaw = (r[c.app] ?? "").trim();
2932
- const app = !appRaw ? "(none)" : known.get(key2(appRaw)) ?? appLabelOf(appRaw);
2933
- const proxyRaw = c.proxy ? (r[c.proxy] ?? "").trim() : "";
2934
- const proxy = proxyRaw && !looksSensitive(proxyRaw) ? proxyRaw : void 0;
2935
- const baseRaw = c.basepath ? (r[c.basepath] ?? "").trim() : "";
2936
- const basepath = baseRaw ? safePathOf(baseRaw) : void 0;
2937
- for (const v of [app, proxy, basepath, path])
2938
- if (v)
2939
- keptValues.add(v);
2940
- const k = [app, method, path, proxy ?? "", basepath ?? ""].join("\0");
2941
- const row = agg.get(k) ?? {
2942
- app,
2943
- method,
2944
- path,
2945
- ...proxy ? { proxy } : {},
2946
- ...basepath ? { basepath } : {},
2947
- count: 0
2948
- };
2949
- row.count += count;
2950
- agg.set(k, row);
3445
+ const endpointIds = /* @__PURE__ */ new Set();
3446
+ for (const e of entries) {
3447
+ const got = facts.get(e);
3448
+ if (got?.fact.kind === "entry")
3449
+ endpointIds.add(entryEndpointId(got.fact, componentOf(got.repo, got.fact)));
3450
+ }
3451
+ const flows = (input.flows ?? []).filter((f) => f.trigger && endpointIds.has(f.trigger) || (f.refs ?? []).some((r) => endpointIds.has(r))).map((f) => ({ id: f.id, repo: f.repo })).sort((a, b) => cmp4(a.id, b.id));
3452
+ for (const f of flows)
3453
+ repos.add(f.repo);
3454
+ const systems = /* @__PURE__ */ new Set([input.vendor.system]);
3455
+ for (const r of repos) {
3456
+ const s = input.systemOfRepo?.[r];
3457
+ if (s)
3458
+ systems.add(s);
2951
3459
  }
2952
- if (!agg.size)
2953
- return {
2954
- ok: false,
2955
- message: `No row of the file is a request in the range to a route of the estate (${rows.length} read, ${outOfRange} outside it, ${skipped} without a method, path or count, ${unmatched} matching no route template of the estate): nothing to keep.`
2956
- };
2957
- days.sort();
2958
- const from = input.from ?? days[0];
2959
- const to = input.to ?? days[days.length - 1];
2960
- if (!from || !to)
2961
- return { ok: false, message: "The rows carry no dates: give --from and --to (YYYY-MM-DD)." };
2962
- const parsed = TrafficFile.safeParse({
2963
- schemaVersion: 1,
2964
- source: input.source,
2965
- from,
2966
- to,
2967
- inputSha256: createHash6("sha256").update(input.bytes).digest("hex"),
2968
- rows: [...agg.values()].sort((a, b) => cmp3(a.app, b.app) || cmp3(a.proxy ?? "", b.proxy ?? "") || cmp3(a.path, b.path) || cmp3(a.method, b.method))
2969
- });
2970
- if (!parsed.success)
2971
- return { ok: false, message: `The aggregate isn't valid: ${parsed.error.issues[0]?.message}.` };
2972
- const out = trafficFileText(parsed.data);
2973
- const lower = out.toLowerCase();
2974
- const leaked = [...secrets].filter((s) => !keptValues.has(s) && lower.includes(s.toLowerCase()));
2975
- if (leaked.length)
2976
- return {
2977
- ok: false,
2978
- message: `Refused: ${leaked.length} value${leaked.length === 1 ? "" : "s"} of the export's dropped columns would be written. Nothing was written.`
2979
- };
2980
- const body = out.replace(/^inputSha256: .*$/m, "");
2981
- if ([IPV4, IPV6, EMAIL, JWT, OPAQUE, UUID, HEX].some((re) => re.test(body)))
2982
- return {
2983
- ok: false,
2984
- message: "Refused: the aggregate would hold an IP, an email or a token-looking value. Nothing was written."
2985
- };
2986
- const hits = input.denyHashes?.size ? denyListHits(out, input.denyHashes) : [];
2987
- if (hits.length)
2988
- return {
2989
- ok: false,
2990
- message: `Refused: the deny-list names a word on line${hits.length === 1 ? "" : "s"} ${hits.join(", ")} of the aggregate. Nothing was written.`
2991
- };
2992
3460
  return {
2993
- ok: true,
2994
- file: parsed.data,
2995
- text: out,
2996
- read: rows.length,
2997
- outOfRange,
2998
- skipped,
2999
- unmatched,
3000
- dropped
3461
+ diff,
3462
+ impact: {
3463
+ vendor: input.vendor.system,
3464
+ older: versionOf(input.older),
3465
+ newer: versionOf(input.newer),
3466
+ changes,
3467
+ repos: sorted(repos),
3468
+ systems: sorted(systems),
3469
+ flows,
3470
+ interfaces: sorted(interfaces),
3471
+ endpoints: sorted(endpoints),
3472
+ gaps: today.gaps,
3473
+ asks: today.asks
3474
+ }
3001
3475
  };
3002
3476
  }
3003
3477
 
3004
3478
  // packages/intake/dist/contract-files.js
3479
+ var import_yaml8 = __toESM(require_dist(), 1);
3480
+ import { readdir as readdir6, readFile as readFile6, stat as stat3 } from "node:fs/promises";
3481
+ import { join as join6 } from "node:path";
3005
3482
  function safeServerUrl(url) {
3006
3483
  const m = /^([a-z][a-z0-9+.-]*:\/\/)([^/?#]*)(.*)$/i.exec(url.trim());
3007
3484
  if (!m) {
@@ -3020,28 +3497,28 @@ var str2 = (m, key3) => {
3020
3497
  return typeof v === "string" && v.trim() ? v.trim() : void 0;
3021
3498
  };
3022
3499
  var mapAt = (m, key3) => {
3023
- const v = (0, import_yaml7.isMap)(m) ? m.get(key3, true) : void 0;
3024
- return (0, import_yaml7.isMap)(v) ? v : void 0;
3500
+ const v = (0, import_yaml8.isMap)(m) ? m.get(key3, true) : void 0;
3501
+ return (0, import_yaml8.isMap)(v) ? v : void 0;
3025
3502
  };
3026
3503
  function readPactFile(text3, file) {
3027
- const lc = new import_yaml7.LineCounter();
3504
+ const lc = new import_yaml8.LineCounter();
3028
3505
  let doc;
3029
3506
  try {
3030
- doc = (0, import_yaml7.parseDocument)(text3, { lineCounter: lc });
3507
+ doc = (0, import_yaml8.parseDocument)(text3, { lineCounter: lc });
3031
3508
  } catch {
3032
3509
  return void 0;
3033
3510
  }
3034
- if (doc.errors.length || !(0, import_yaml7.isMap)(doc.contents))
3511
+ if (doc.errors.length || !(0, import_yaml8.isMap)(doc.contents))
3035
3512
  return void 0;
3036
3513
  const root = doc.contents;
3037
3514
  const consumer = str2(mapAt(root, "consumer"), "name");
3038
3515
  const provider = str2(mapAt(root, "provider"), "name");
3039
3516
  const list2 = root.get("interactions", true);
3040
- if (!consumer || !provider || !(0, import_yaml7.isSeq)(list2))
3517
+ if (!consumer || !provider || !(0, import_yaml8.isSeq)(list2))
3041
3518
  return void 0;
3042
3519
  const out = [];
3043
3520
  for (const it of list2.items) {
3044
- if (!(0, import_yaml7.isMap)(it))
3521
+ if (!(0, import_yaml8.isMap)(it))
3045
3522
  continue;
3046
3523
  const type = str2(it, "type");
3047
3524
  if (type && !/http/i.test(type))
@@ -3050,8 +3527,8 @@ function readPactFile(text3, file) {
3050
3527
  if (!req)
3051
3528
  continue;
3052
3529
  const method = str2(req, "method");
3053
- const pair = req.items.find((p) => (0, import_yaml7.isScalar)(p.key) && p.key.value === "path");
3054
- const path = pair && (0, import_yaml7.isScalar)(pair.value) ? String(pair.value.value) : void 0;
3530
+ const pair = req.items.find((p) => (0, import_yaml8.isScalar)(p.key) && p.key.value === "path");
3531
+ const path = pair && (0, import_yaml8.isScalar)(pair.value) ? String(pair.value.value) : void 0;
3055
3532
  const safe = path?.startsWith("/") ? safePathOf(path) : void 0;
3056
3533
  if (!safe)
3057
3534
  continue;
@@ -3098,7 +3575,7 @@ function readConsumerOpenApi(text3, file, own) {
3098
3575
  ] : [];
3099
3576
  });
3100
3577
  }
3101
- var SKIP = /* @__PURE__ */ new Set([
3578
+ var SKIP2 = /* @__PURE__ */ new Set([
3102
3579
  ".git",
3103
3580
  "node_modules",
3104
3581
  "vendor",
@@ -3113,19 +3590,19 @@ var SKIP = /* @__PURE__ */ new Set([
3113
3590
  ".idea",
3114
3591
  ".atticus"
3115
3592
  ]);
3116
- var MAX_BYTES = 5 * 1024 * 1024;
3593
+ var MAX_BYTES2 = 5 * 1024 * 1024;
3117
3594
  var PACT = /pact/i;
3118
3595
  var SPEC = /(openapi|swagger)/i;
3119
3596
  async function readContractFiles(dir, o) {
3120
3597
  const files = [];
3121
3598
  const walk2 = async (rel) => {
3122
- const entries2 = await readdir5(join5(dir, ...rel.split("/").filter(Boolean)), {
3599
+ const entries2 = await readdir6(join6(dir, ...rel.split("/").filter(Boolean)), {
3123
3600
  withFileTypes: true
3124
3601
  }).catch(() => []);
3125
3602
  for (const e of [...entries2].sort((a, b) => a.name < b.name ? -1 : 1)) {
3126
3603
  const p = rel ? `${rel}/${e.name}` : e.name;
3127
3604
  if (e.isDirectory()) {
3128
- if (!SKIP.has(e.name))
3605
+ if (!SKIP2.has(e.name))
3129
3606
  await walk2(p);
3130
3607
  } else if (e.isFile()) {
3131
3608
  if (/\.json$/i.test(e.name) && PACT.test(p))
@@ -3138,11 +3615,11 @@ async function readContractFiles(dir, o) {
3138
3615
  await walk2("");
3139
3616
  const entries = [];
3140
3617
  for (const p of files) {
3141
- const full = join5(dir, ...p.split("/"));
3142
- const size = (await stat2(full).catch(() => void 0))?.size ?? 0;
3143
- if (size === 0 || size > MAX_BYTES)
3618
+ const full = join6(dir, ...p.split("/"));
3619
+ const size = (await stat3(full).catch(() => void 0))?.size ?? 0;
3620
+ if (size === 0 || size > MAX_BYTES2)
3144
3621
  continue;
3145
- const text3 = await readFile5(full, "utf8");
3622
+ const text3 = await readFile6(full, "utf8");
3146
3623
  const got = (/\.json$/i.test(p) && PACT.test(p) ? readPactFile(text3, p) : void 0) ?? (SPEC.test(p) ? readConsumerOpenApi(text3, p, o.own ?? []) : void 0);
3147
3624
  if (!got?.length)
3148
3625
  continue;
@@ -3177,9 +3654,24 @@ export {
3177
3654
  sortItems,
3178
3655
  opt,
3179
3656
  screenFile,
3657
+ looksSensitive,
3658
+ segmentOf,
3659
+ safePathOf,
3660
+ pathTemplateOf,
3661
+ appLabelOf,
3662
+ denyListHits,
3663
+ aggregateTraffic,
3180
3664
  specEndpointIds,
3181
3665
  readVendorSpec,
3182
3666
  operationSchemas,
3667
+ readProtoSpecs,
3668
+ readAvroSpecs,
3669
+ readJsonSchemaSpecs,
3670
+ readAsyncApiSpecs,
3671
+ openApiContractSpecs,
3672
+ specFormatOf,
3673
+ readContractSpecs,
3674
+ readRepoSpecs,
3183
3675
  nameParts,
3184
3676
  compareVersions,
3185
3677
  scanInputs,
@@ -3203,13 +3695,6 @@ export {
3203
3695
  diffVendorSpecs,
3204
3696
  MAX_UPSTREAM,
3205
3697
  vendorImpact,
3206
- looksSensitive,
3207
- segmentOf,
3208
- safePathOf,
3209
- pathTemplateOf,
3210
- appLabelOf,
3211
- denyListHits,
3212
- aggregateTraffic,
3213
3698
  safeServerUrl,
3214
3699
  readPactFile,
3215
3700
  readConsumerOpenApi,