@reddoorla/maintenance 0.85.2 → 0.87.0

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 (265) hide show
  1. package/README.md +8 -0
  2. package/dist/airtable-ZBUPQJSC.js +9 -0
  3. package/dist/{announce-GIAYN67S.js → announce-I2Z4JN3I.js} +58 -30
  4. package/dist/announce-I2Z4JN3I.js.map +1 -0
  5. package/dist/attachments-NLZIJ5NU.js +9 -0
  6. package/dist/{bump-deps-SWJB6H5V.js → bump-deps-CGVELRLK.js} +9 -9
  7. package/dist/{chunk-SDUJIANJ.js → chunk-2NJQLSEU.js} +3 -3
  8. package/dist/chunk-2NQUCS7O.js +243 -0
  9. package/dist/chunk-2NQUCS7O.js.map +1 -0
  10. package/dist/{chunk-ZTPPCHDB.js → chunk-3G25KIWW.js} +4 -4
  11. package/dist/{chunk-DTTIFYAM.js → chunk-3JQ2FO3D.js} +44 -405
  12. package/dist/chunk-3JQ2FO3D.js.map +1 -0
  13. package/dist/chunk-3SF7D4DY.js +359 -0
  14. package/dist/chunk-3SF7D4DY.js.map +1 -0
  15. package/dist/{chunk-37S6L6G4.js → chunk-5UINJNAJ.js} +72 -2
  16. package/dist/chunk-5UINJNAJ.js.map +1 -0
  17. package/dist/{chunk-THEFTZ7F.js → chunk-62CMMGEO.js} +5 -5
  18. package/dist/{chunk-FDIFTIXC.js → chunk-6TWWY7ZU.js} +2 -2
  19. package/dist/{chunk-PBWDDDQH.js → chunk-7BZUOZPU.js} +2 -2
  20. package/dist/{chunk-577HCGZO.js → chunk-7NYN2P6I.js} +44 -26
  21. package/dist/chunk-7NYN2P6I.js.map +1 -0
  22. package/dist/{chunk-UYCAF77E.js → chunk-7RJ2HMMJ.js} +3 -3
  23. package/dist/{chunk-Q276MZ7E.js → chunk-7UAYMAKR.js} +2 -2
  24. package/dist/{chunk-MGR2H7F4.js → chunk-BBUSGEES.js} +58 -45
  25. package/dist/chunk-BBUSGEES.js.map +1 -0
  26. package/dist/chunk-BNM5POSJ.js +284 -0
  27. package/dist/chunk-BNM5POSJ.js.map +1 -0
  28. package/dist/{chunk-R6FPFMOS.js → chunk-BQRFQSGY.js} +3 -3
  29. package/dist/{chunk-NWB4O5EY.js → chunk-C6CLRKPV.js} +5 -5
  30. package/dist/chunk-C6CLRKPV.js.map +1 -0
  31. package/dist/{chunk-7J53SUT6.js → chunk-CROKUHJB.js} +4 -4
  32. package/dist/chunk-DEWJMMG3.js +274 -0
  33. package/dist/chunk-DEWJMMG3.js.map +1 -0
  34. package/dist/{chunk-SEEA6RXF.js → chunk-DJZWYIPP.js} +2 -2
  35. package/dist/chunk-DJZWYIPP.js.map +1 -0
  36. package/dist/chunk-EVBCK2KC.js +68 -0
  37. package/dist/chunk-EVBCK2KC.js.map +1 -0
  38. package/dist/chunk-F3JWOPTG.js +202 -0
  39. package/dist/chunk-F3JWOPTG.js.map +1 -0
  40. package/dist/{chunk-GZNBCHAZ.js → chunk-HEWSRXYV.js} +4 -4
  41. package/dist/chunk-HHMMUR4P.js +335 -0
  42. package/dist/chunk-HHMMUR4P.js.map +1 -0
  43. package/dist/chunk-HSI6Q7MI.js +1238 -0
  44. package/dist/chunk-HSI6Q7MI.js.map +1 -0
  45. package/dist/{chunk-MPBXOJ3N.js → chunk-IY6256GK.js} +33 -2
  46. package/dist/chunk-IY6256GK.js.map +1 -0
  47. package/dist/{chunk-LS6QPANO.js → chunk-IYSEC543.js} +2 -2
  48. package/dist/{chunk-DC5H7KEQ.js → chunk-JHGHLKFS.js} +2 -2
  49. package/dist/{chunk-4DHQCN5H.js → chunk-LBYOLBW7.js} +17 -2
  50. package/dist/chunk-LBYOLBW7.js.map +1 -0
  51. package/dist/{chunk-6QRLRT3P.js → chunk-MT2JINSS.js} +16 -265
  52. package/dist/chunk-MT2JINSS.js.map +1 -0
  53. package/dist/{chunk-TP5M2NQB.js → chunk-NCMZMLY7.js} +3 -3
  54. package/dist/{chunk-COZPL62X.js → chunk-NDWYJLRF.js} +24 -139
  55. package/dist/chunk-NDWYJLRF.js.map +1 -0
  56. package/dist/{chunk-3YXDSCM6.js → chunk-NXNPDCF3.js} +29 -11
  57. package/dist/chunk-NXNPDCF3.js.map +1 -0
  58. package/dist/chunk-NYUYNYQL.js +48 -0
  59. package/dist/chunk-NYUYNYQL.js.map +1 -0
  60. package/dist/chunk-P6AORG32.js +415 -0
  61. package/dist/chunk-P6AORG32.js.map +1 -0
  62. package/dist/chunk-PTDMVGKL.js +31 -0
  63. package/dist/chunk-PTDMVGKL.js.map +1 -0
  64. package/dist/{chunk-D4FVAIEJ.js → chunk-PZR4EBPY.js} +5 -2
  65. package/dist/chunk-PZR4EBPY.js.map +1 -0
  66. package/dist/{chunk-LTB6KVJW.js → chunk-SDDPUAWH.js} +13 -11
  67. package/dist/{chunk-LTB6KVJW.js.map → chunk-SDDPUAWH.js.map} +1 -1
  68. package/dist/{chunk-WYYQK4D3.js → chunk-TD2NNXLZ.js} +13 -13
  69. package/dist/{chunk-ZMIPG6TR.js → chunk-TVL5MVUF.js} +4 -4
  70. package/dist/chunk-UDRHAQT7.js +172 -0
  71. package/dist/chunk-UDRHAQT7.js.map +1 -0
  72. package/dist/chunk-VAD43MOR.js +72 -0
  73. package/dist/chunk-VAD43MOR.js.map +1 -0
  74. package/dist/chunk-VSBFM7DS.js +229 -0
  75. package/dist/chunk-VSBFM7DS.js.map +1 -0
  76. package/dist/{chunk-VRWUL4TR.js → chunk-XHHMM5HX.js} +2 -2
  77. package/dist/{chunk-RJB3QUSP.js → chunk-XIDUYLSR.js} +3 -3
  78. package/dist/{chunk-QG6OSL4M.js → chunk-XUGSZP7Z.js} +2 -2
  79. package/dist/{chunk-S56JQJ4F.js → chunk-Y53WOQIJ.js} +3 -3
  80. package/dist/{chunk-62VF32IC.js → chunk-YFAXOD7Z.js} +10 -6
  81. package/dist/chunk-YFAXOD7Z.js.map +1 -0
  82. package/dist/{chunk-ICXV25N7.js → chunk-Z3KYFUN6.js} +3 -3
  83. package/dist/chunk-ZBDZTJUO.js +129 -0
  84. package/dist/chunk-ZBDZTJUO.js.map +1 -0
  85. package/dist/chunk-ZGBEIWSC.js +146 -0
  86. package/dist/chunk-ZGBEIWSC.js.map +1 -0
  87. package/dist/cli/bin.js +51 -28
  88. package/dist/cli/bin.js.map +1 -1
  89. package/dist/cli/commands/audit.d.ts +30 -1
  90. package/dist/cli/commands/audit.js +69 -33
  91. package/dist/cli/commands/audit.js.map +1 -1
  92. package/dist/client-AUE3XUPO.js +11 -0
  93. package/dist/{convert-to-pnpm-AT52NWZB.js → convert-to-pnpm-QFJOEP5V.js} +9 -9
  94. package/dist/db-UXNIZ2RG.js +217 -0
  95. package/dist/db-UXNIZ2RG.js.map +1 -0
  96. package/dist/{digest-UVHYZUYE.js → digest-FW6QMZZJ.js} +26 -22
  97. package/dist/{digest-UVHYZUYE.js.map → digest-FW6QMZZJ.js.map} +1 -1
  98. package/dist/dump-P6EBSIOH.js +68 -0
  99. package/dist/dump-P6EBSIOH.js.map +1 -0
  100. package/dist/email-KJXASVH5.js +195 -0
  101. package/dist/email-KJXASVH5.js.map +1 -0
  102. package/dist/{ensure-site-S25MDDHW.js → ensure-site-4DCEBAPM.js} +25 -16
  103. package/dist/ensure-site-4DCEBAPM.js.map +1 -0
  104. package/dist/fleet-events-cF2Om88w.d.ts +24 -0
  105. package/dist/fleet-state-7TJ2GYT2.js +39 -0
  106. package/dist/{forms-notify-target-TWN4EH6K.js → forms-notify-target-2EAWCWBW.js} +42 -133
  107. package/dist/forms-notify-target-2EAWCWBW.js.map +1 -0
  108. package/dist/{github-signals-G4ILZAJ6.js → github-signals-E2WPYTBK.js} +42 -21
  109. package/dist/github-signals-E2WPYTBK.js.map +1 -0
  110. package/dist/{header-image-T7XD37JL.js → header-image-6IC53W27.js} +36 -13
  111. package/dist/header-image-6IC53W27.js.map +1 -0
  112. package/dist/header-images-SQBCE5OD.js +88 -0
  113. package/dist/header-images-SQBCE5OD.js.map +1 -0
  114. package/dist/{health-endpoint-242WG2OJ.js → health-endpoint-RFXL2F4A.js} +9 -9
  115. package/dist/health-mirror-L5JBEJVA.js +41 -0
  116. package/dist/health-mirror-L5JBEJVA.js.map +1 -0
  117. package/dist/import-airtable-OHVY344G.js +37 -0
  118. package/dist/index.d.ts +324 -21
  119. package/dist/index.js +215 -76
  120. package/dist/index.js.map +1 -1
  121. package/dist/{init-JN26NTWF.js → init-XRAQZYID.js} +21 -18
  122. package/dist/{init-JN26NTWF.js.map → init-XRAQZYID.js.map} +1 -1
  123. package/dist/{launch-JA7Z4CIM.js → launch-IX4Y5JJC.js} +65 -30
  124. package/dist/launch-IX4Y5JJC.js.map +1 -0
  125. package/dist/lighthouse-VHI77PFB.js +11 -0
  126. package/dist/{lighthouse-airtable-BIPM26SZ.js → lighthouse-airtable-3GUWHETW.js} +3 -3
  127. package/dist/mailchimp-XYCTEEJY.js +72 -0
  128. package/dist/mailchimp-XYCTEEJY.js.map +1 -0
  129. package/dist/migrate-GQH237A6.js +7 -0
  130. package/dist/migrate-GQH237A6.js.map +1 -0
  131. package/dist/notify-C645PGD5.js +22 -0
  132. package/dist/notify-C645PGD5.js.map +1 -0
  133. package/dist/{onboard-53CITIM7.js → onboard-O4IAHJMO.js} +9 -9
  134. package/dist/orchestrate-YLWQ6KK2.js +31 -0
  135. package/dist/orchestrate-YLWQ6KK2.js.map +1 -0
  136. package/dist/parity-56KA2DGR.js +12 -0
  137. package/dist/parity-56KA2DGR.js.map +1 -0
  138. package/dist/pipeline-3AANZFCR.js +12 -0
  139. package/dist/pipeline-3AANZFCR.js.map +1 -0
  140. package/dist/{preflight-3XPDUHFJ.js → preflight-TNORKGCX.js} +17 -13
  141. package/dist/{preflight-3XPDUHFJ.js.map → preflight-TNORKGCX.js.map} +1 -1
  142. package/dist/{prismic-ci-UTQ6LRR3.js → prismic-ci-G2AK53VL.js} +12 -12
  143. package/dist/{prismic-models-PVES6R5V.js → prismic-models-O6Z3OK3A.js} +18 -13
  144. package/dist/prismic-models-O6Z3OK3A.js.map +1 -0
  145. package/dist/prospect/types.d.ts +267 -0
  146. package/dist/prospect/types.js +1 -0
  147. package/dist/prospect/types.js.map +1 -0
  148. package/dist/prospect-audit-KSXUNQ5J.js +174 -0
  149. package/dist/prospect-audit-KSXUNQ5J.js.map +1 -0
  150. package/dist/prospect-audits-3PMIO73D.js +19 -0
  151. package/dist/prospect-audits-3PMIO73D.js.map +1 -0
  152. package/dist/{protection-audit-64PLLBLI.js → protection-audit-SJO53MEQ.js} +3 -3
  153. package/dist/recipes/sync-configs.js +3 -3
  154. package/dist/render-IFOGFB5T.js +10 -0
  155. package/dist/render-IFOGFB5T.js.map +1 -0
  156. package/dist/render-from-row-BWSOIYDS.js +17 -0
  157. package/dist/render-from-row-BWSOIYDS.js.map +1 -0
  158. package/dist/{renovate-dispatch-ICJGSFCE.js → renovate-dispatch-6GQWTRKX.js} +12 -12
  159. package/dist/{renovate-dispatch-ICJGSFCE.js.map → renovate-dispatch-6GQWTRKX.js.map} +1 -1
  160. package/dist/replay-C2LXMJZP.js +66 -0
  161. package/dist/replay-C2LXMJZP.js.map +1 -0
  162. package/dist/{report-6CKSWJNG.js → report-R3E3Y7HR.js} +100 -32
  163. package/dist/report-R3E3Y7HR.js.map +1 -0
  164. package/dist/report-mirror-4MNORYQ4.js +49 -0
  165. package/dist/report-mirror-4MNORYQ4.js.map +1 -0
  166. package/dist/reports/header-image/assets/headline-announcement.png +0 -0
  167. package/dist/reports/header-image/assets/headline-launch.png +0 -0
  168. package/dist/reports/header-image/assets/headline-maintenance.png +0 -0
  169. package/dist/reports/header-image/assets/headline-testing.png +0 -0
  170. package/dist/reports/header-image/assets/plate-clean.png +0 -0
  171. package/dist/rerender-3FM6DNRH.js +32 -0
  172. package/dist/rerender-3FM6DNRH.js.map +1 -0
  173. package/dist/{self-updating-PPQVV6UA.js → self-updating-UCIWESAX.js} +9 -9
  174. package/dist/{selftest-CQ6NOX52.js → selftest-VGHWPN72.js} +31 -24
  175. package/dist/selftest-VGHWPN72.js.map +1 -0
  176. package/dist/site-mirror-NIREX5ME.js +52 -0
  177. package/dist/site-mirror-NIREX5ME.js.map +1 -0
  178. package/dist/smoke-B2GQOSIZ.js +20 -0
  179. package/dist/smoke-B2GQOSIZ.js.map +1 -0
  180. package/dist/{smoke-suite-TMCSOYRK.js → smoke-suite-U3UKD3NS.js} +9 -9
  181. package/dist/{submissions-GJ6ITBRH.js → submissions-IQEJX6FK.js} +3 -3
  182. package/dist/{svelte-codemods-ZOBDHIES.js → svelte-codemods-GOKXTBHW.js} +9 -9
  183. package/dist/sync-CTUVXMCK.js +44 -0
  184. package/dist/sync-CTUVXMCK.js.map +1 -0
  185. package/dist/{sync-configs-CJXUX6MD.js → sync-configs-SPTLFJCC.js} +9 -9
  186. package/dist/{upgrade-WLX27UPC.js → upgrade-W6ZR3FJH.js} +9 -9
  187. package/dist/webhook-VOGOW3W6.js +38 -0
  188. package/dist/webhook-VOGOW3W6.js.map +1 -0
  189. package/dist/{websites-SADZR4XQ.js → websites-D6WYFAES.js} +6 -2
  190. package/dist/websites-D6WYFAES.js.map +1 -0
  191. package/dist/{write-audits-to-airtable-7PH75YWY.js → write-audits-to-airtable-CMKHGJNQ.js} +4 -4
  192. package/dist/write-audits-to-airtable-CMKHGJNQ.js.map +1 -0
  193. package/package.json +9 -2
  194. package/dist/airtable-HRKSA7V4.js +0 -9
  195. package/dist/announce-GIAYN67S.js.map +0 -1
  196. package/dist/chunk-37S6L6G4.js.map +0 -1
  197. package/dist/chunk-3YXDSCM6.js.map +0 -1
  198. package/dist/chunk-4DHQCN5H.js.map +0 -1
  199. package/dist/chunk-4SOCPK7A.js +0 -108
  200. package/dist/chunk-4SOCPK7A.js.map +0 -1
  201. package/dist/chunk-577HCGZO.js.map +0 -1
  202. package/dist/chunk-62VF32IC.js.map +0 -1
  203. package/dist/chunk-6QRLRT3P.js.map +0 -1
  204. package/dist/chunk-COZPL62X.js.map +0 -1
  205. package/dist/chunk-D4FVAIEJ.js.map +0 -1
  206. package/dist/chunk-DTTIFYAM.js.map +0 -1
  207. package/dist/chunk-MGR2H7F4.js.map +0 -1
  208. package/dist/chunk-MPBXOJ3N.js.map +0 -1
  209. package/dist/chunk-NWB4O5EY.js.map +0 -1
  210. package/dist/chunk-SEEA6RXF.js.map +0 -1
  211. package/dist/chunk-U5SZ4FOP.js +0 -26
  212. package/dist/chunk-U5SZ4FOP.js.map +0 -1
  213. package/dist/client-X5WUJWDE.js +0 -11
  214. package/dist/db-JSIZYT23.js +0 -23
  215. package/dist/db-JSIZYT23.js.map +0 -1
  216. package/dist/ensure-site-S25MDDHW.js.map +0 -1
  217. package/dist/forms-notify-target-TWN4EH6K.js.map +0 -1
  218. package/dist/github-signals-G4ILZAJ6.js.map +0 -1
  219. package/dist/header-image-T7XD37JL.js.map +0 -1
  220. package/dist/launch-JA7Z4CIM.js.map +0 -1
  221. package/dist/migrate-LJUFGXQZ.js +0 -7
  222. package/dist/orchestrate-KDNXZQX7.js +0 -27
  223. package/dist/prismic-models-PVES6R5V.js.map +0 -1
  224. package/dist/report-6CKSWJNG.js.map +0 -1
  225. package/dist/reports/header-image/assets/plate.png +0 -0
  226. package/dist/selftest-CQ6NOX52.js.map +0 -1
  227. /package/dist/{airtable-HRKSA7V4.js.map → airtable-ZBUPQJSC.js.map} +0 -0
  228. /package/dist/{client-X5WUJWDE.js.map → attachments-NLZIJ5NU.js.map} +0 -0
  229. /package/dist/{bump-deps-SWJB6H5V.js.map → bump-deps-CGVELRLK.js.map} +0 -0
  230. /package/dist/{chunk-SDUJIANJ.js.map → chunk-2NJQLSEU.js.map} +0 -0
  231. /package/dist/{chunk-ZTPPCHDB.js.map → chunk-3G25KIWW.js.map} +0 -0
  232. /package/dist/{chunk-THEFTZ7F.js.map → chunk-62CMMGEO.js.map} +0 -0
  233. /package/dist/{chunk-FDIFTIXC.js.map → chunk-6TWWY7ZU.js.map} +0 -0
  234. /package/dist/{chunk-PBWDDDQH.js.map → chunk-7BZUOZPU.js.map} +0 -0
  235. /package/dist/{chunk-UYCAF77E.js.map → chunk-7RJ2HMMJ.js.map} +0 -0
  236. /package/dist/{chunk-Q276MZ7E.js.map → chunk-7UAYMAKR.js.map} +0 -0
  237. /package/dist/{chunk-R6FPFMOS.js.map → chunk-BQRFQSGY.js.map} +0 -0
  238. /package/dist/{chunk-7J53SUT6.js.map → chunk-CROKUHJB.js.map} +0 -0
  239. /package/dist/{chunk-GZNBCHAZ.js.map → chunk-HEWSRXYV.js.map} +0 -0
  240. /package/dist/{chunk-LS6QPANO.js.map → chunk-IYSEC543.js.map} +0 -0
  241. /package/dist/{chunk-DC5H7KEQ.js.map → chunk-JHGHLKFS.js.map} +0 -0
  242. /package/dist/{chunk-TP5M2NQB.js.map → chunk-NCMZMLY7.js.map} +0 -0
  243. /package/dist/{chunk-WYYQK4D3.js.map → chunk-TD2NNXLZ.js.map} +0 -0
  244. /package/dist/{chunk-ZMIPG6TR.js.map → chunk-TVL5MVUF.js.map} +0 -0
  245. /package/dist/{chunk-VRWUL4TR.js.map → chunk-XHHMM5HX.js.map} +0 -0
  246. /package/dist/{chunk-RJB3QUSP.js.map → chunk-XIDUYLSR.js.map} +0 -0
  247. /package/dist/{chunk-QG6OSL4M.js.map → chunk-XUGSZP7Z.js.map} +0 -0
  248. /package/dist/{chunk-S56JQJ4F.js.map → chunk-Y53WOQIJ.js.map} +0 -0
  249. /package/dist/{chunk-ICXV25N7.js.map → chunk-Z3KYFUN6.js.map} +0 -0
  250. /package/dist/{lighthouse-airtable-BIPM26SZ.js.map → client-AUE3XUPO.js.map} +0 -0
  251. /package/dist/{convert-to-pnpm-AT52NWZB.js.map → convert-to-pnpm-QFJOEP5V.js.map} +0 -0
  252. /package/dist/{migrate-LJUFGXQZ.js.map → fleet-state-7TJ2GYT2.js.map} +0 -0
  253. /package/dist/{health-endpoint-242WG2OJ.js.map → health-endpoint-RFXL2F4A.js.map} +0 -0
  254. /package/dist/{orchestrate-KDNXZQX7.js.map → import-airtable-OHVY344G.js.map} +0 -0
  255. /package/dist/{websites-SADZR4XQ.js.map → lighthouse-VHI77PFB.js.map} +0 -0
  256. /package/dist/{write-audits-to-airtable-7PH75YWY.js.map → lighthouse-airtable-3GUWHETW.js.map} +0 -0
  257. /package/dist/{onboard-53CITIM7.js.map → onboard-O4IAHJMO.js.map} +0 -0
  258. /package/dist/{prismic-ci-UTQ6LRR3.js.map → prismic-ci-G2AK53VL.js.map} +0 -0
  259. /package/dist/{protection-audit-64PLLBLI.js.map → protection-audit-SJO53MEQ.js.map} +0 -0
  260. /package/dist/{self-updating-PPQVV6UA.js.map → self-updating-UCIWESAX.js.map} +0 -0
  261. /package/dist/{smoke-suite-TMCSOYRK.js.map → smoke-suite-U3UKD3NS.js.map} +0 -0
  262. /package/dist/{submissions-GJ6ITBRH.js.map → submissions-IQEJX6FK.js.map} +0 -0
  263. /package/dist/{svelte-codemods-ZOBDHIES.js.map → svelte-codemods-GOKXTBHW.js.map} +0 -0
  264. /package/dist/{sync-configs-CJXUX6MD.js.map → sync-configs-SPTLFJCC.js.map} +0 -0
  265. /package/dist/{upgrade-WLX27UPC.js.map → upgrade-W6ZR3FJH.js.map} +0 -0
package/dist/index.js CHANGED
@@ -1,110 +1,124 @@
1
1
  import "./chunk-2SLED3NB.js";
2
- import "./chunk-TP5M2NQB.js";
2
+ import "./chunk-NCMZMLY7.js";
3
+ import {
4
+ draftReportForSite
5
+ } from "./chunk-BBUSGEES.js";
3
6
  import {
4
7
  approveBlockers
5
- } from "./chunk-LTB6KVJW.js";
8
+ } from "./chunk-SDDPUAWH.js";
9
+ import {
10
+ findDueReports
11
+ } from "./chunk-PZR4EBPY.js";
6
12
  import {
7
13
  DEFAULT_INIT_STEPS,
8
14
  a11yFixturesPage,
9
15
  init
10
- } from "./chunk-WYYQK4D3.js";
16
+ } from "./chunk-TD2NNXLZ.js";
17
+ import "./chunk-BQRFQSGY.js";
18
+ import "./chunk-Y53WOQIJ.js";
11
19
  import {
12
20
  onboard,
13
21
  selfCaretRange,
14
22
  selfPackageVersion
15
- } from "./chunk-UYCAF77E.js";
16
- import {
17
- findDueReports
18
- } from "./chunk-D4FVAIEJ.js";
19
- import {
20
- draftReportForSite
21
- } from "./chunk-MGR2H7F4.js";
22
- import "./chunk-62VF32IC.js";
23
+ } from "./chunk-7RJ2HMMJ.js";
24
+ import "./chunk-YFAXOD7Z.js";
23
25
  import {
24
- domainFromUrl,
25
- generateHeaderImage,
26
- loadPlate
27
- } from "./chunk-37S6L6G4.js";
26
+ bumpDeps
27
+ } from "./chunk-2NJQLSEU.js";
28
+ import "./chunk-R53VL3RI.js";
28
29
  import {
29
30
  upgradeSvelte4to5
30
- } from "./chunk-ICXV25N7.js";
31
+ } from "./chunk-Z3KYFUN6.js";
31
32
  import {
32
33
  convertToPnpm
33
- } from "./chunk-RJB3QUSP.js";
34
+ } from "./chunk-XIDUYLSR.js";
34
35
  import {
35
36
  svelteCodemods
36
- } from "./chunk-LS6QPANO.js";
37
+ } from "./chunk-IYSEC543.js";
37
38
  import "./chunk-J7SZQUCW.js";
38
- import "./chunk-R6FPFMOS.js";
39
- import "./chunk-S56JQJ4F.js";
40
- import "./chunk-R53VL3RI.js";
41
39
  import {
42
40
  parseAddresses,
43
41
  sendApprovedReports,
44
42
  withGlobalCc
45
- } from "./chunk-COZPL62X.js";
43
+ } from "./chunk-NDWYJLRF.js";
44
+ import "./chunk-NYUYNYQL.js";
45
+ import {
46
+ isPendingApproval
47
+ } from "./chunk-F3JWOPTG.js";
48
+ import {
49
+ checklistFor,
50
+ gatingFields,
51
+ isHealthGateClear
52
+ } from "./chunk-VAD43MOR.js";
53
+ import {
54
+ fromAirtableBase
55
+ } from "./chunk-C6CLRKPV.js";
56
+ import "./chunk-IY6256GK.js";
57
+ import "./chunk-HN6I2XWI.js";
58
+ import "./chunk-ZGBEIWSC.js";
46
59
  import "./chunk-GECESMVS.js";
47
60
  import {
48
61
  BLURRED_CID,
49
62
  CHECK_CID,
50
- checklistFor,
51
- gatingFields,
52
- isHealthGateClear,
53
- isPendingApproval,
54
63
  loadBundledImages,
55
- renderReportHtml
56
- } from "./chunk-6QRLRT3P.js";
57
- import "./chunk-MPBXOJ3N.js";
64
+ renderReportHtml,
65
+ rendersCommentary
66
+ } from "./chunk-MT2JINSS.js";
58
67
  import {
59
68
  escapeHtml,
60
69
  safeUrl
61
- } from "./chunk-SEEA6RXF.js";
62
- import "./chunk-WEKL2HYJ.js";
70
+ } from "./chunk-DJZWYIPP.js";
63
71
  import {
64
- bumpDeps
65
- } from "./chunk-SDUJIANJ.js";
72
+ domainFromUrl,
73
+ generateHeaderImage,
74
+ loadHeadline,
75
+ loadPlate
76
+ } from "./chunk-5UINJNAJ.js";
77
+ import {
78
+ CANONICAL_STATUSES,
79
+ SEVERITY_RANK,
80
+ siteSlug,
81
+ toAirtableStatus
82
+ } from "./chunk-7NYN2P6I.js";
83
+ import "./chunk-WEKL2HYJ.js";
66
84
  import {
67
85
  syncConfigs
68
- } from "./chunk-Q276MZ7E.js";
86
+ } from "./chunk-7UAYMAKR.js";
69
87
  import "./chunk-73UFRZKY.js";
70
- import "./chunk-ZTPPCHDB.js";
88
+ import "./chunk-3G25KIWW.js";
71
89
  import "./chunk-OTGB6YQO.js";
72
90
  import {
73
91
  ALL_AUDIT_NAMES,
74
92
  a11yAudit,
75
93
  depsAudit,
76
- lighthouseAudit,
77
94
  lintAudit,
78
95
  runAudits,
79
96
  runAuditsAcross,
80
97
  securityAudit
81
- } from "./chunk-DTTIFYAM.js";
98
+ } from "./chunk-3JQ2FO3D.js";
82
99
  import "./chunk-LKGVSM2O.js";
83
100
  import "./chunk-GASBX52O.js";
84
- import "./chunk-VRWUL4TR.js";
85
- import "./chunk-QG6OSL4M.js";
86
- import "./chunk-DC5H7KEQ.js";
87
- import "./chunk-4SOCPK7A.js";
101
+ import "./chunk-XHHMM5HX.js";
88
102
  import {
89
103
  fromJsonFile,
90
104
  localPath
91
- } from "./chunk-FDIFTIXC.js";
92
- import "./chunk-4DHQCN5H.js";
105
+ } from "./chunk-6TWWY7ZU.js";
106
+ import "./chunk-XUGSZP7Z.js";
107
+ import "./chunk-EVBCK2KC.js";
108
+ import "./chunk-JHGHLKFS.js";
109
+ import "./chunk-3SF7D4DY.js";
93
110
  import "./chunk-A3WDWNN5.js";
94
111
  import {
95
112
  isLeadFormType
96
113
  } from "./chunk-2OP4JKIQ.js";
97
- import "./chunk-XXTZBPUY.js";
98
114
  import "./chunk-XTK5VIQB.js";
99
115
  import {
100
- fromAirtableBase
101
- } from "./chunk-NWB4O5EY.js";
102
- import "./chunk-U5SZ4FOP.js";
103
- import {
104
- SEVERITY_RANK,
105
- siteSlug
106
- } from "./chunk-577HCGZO.js";
107
- import "./chunk-HN6I2XWI.js";
116
+ lighthouseAudit
117
+ } from "./chunk-2NQUCS7O.js";
118
+ import "./chunk-UDRHAQT7.js";
119
+ import "./chunk-PTDMVGKL.js";
120
+ import "./chunk-LBYOLBW7.js";
121
+ import "./chunk-XXTZBPUY.js";
108
122
  import "./chunk-6VAL7XJT.js";
109
123
  import "./chunk-NMAWXBJA.js";
110
124
  import "./chunk-C6B4RHXR.js";
@@ -128,6 +142,16 @@ function isRecipeName(value) {
128
142
  return ALL_RECIPE_NAMES.includes(value);
129
143
  }
130
144
 
145
+ // src/dashboard/favicon.ts
146
+ var REDDOOR_FAVICON_PNG_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAACXBIWXMAAAAnAAAAJwEqCZFPAAAAk1BMVEVHcEzkGTfjGDbjGTfjGTfjGTfjGTfjGDbjGDbjGTfjGTfjGTfkGTfjGTfjGDbjGDbkGTfjGDbjGDbjGTfjGTfjGDbjGTfjGDbjGTfjGDbjGTfjGTfjGDbjGDbjGDbjGDbjGTfjGTbjGDbjGDbjGDbjGDbjGTfjGTfjGTfjGDbjGDbjGTfjGDbjGDbjGTfjGTbkGTfxxbwzAAAALXRSTlMA4DABMOD8cOBwDltwi+bFLMlk54/BDVPk/I61/u2cFaBw9nqO1izBIQE+Becdo6eEAAABBElEQVQ4y91SCVYCMQwt4kxbcEHFfUFFcMGf9P6nM0kXEPEAmtdJs+cnU+f+He2fIIEAYuVgkmvDfTG9Rh+6LoRBUBqE7gi09l9eAeeTrZJoFd5uQWfj4VbPvRqwmj9zfzP6CYpyi48F6HW5A3WuMHsEPsfvO8cSkMPTe+pfRr/MTckdg+4enqL3PkYf/YFIqiiP8VAw6EZkH6QEO0xJLUhmdbY5+TjHkCVohprlcpzlnJw9GlNkrZC16uCmWIaAZItNrT4xV0T2yxrIWoNKy4rdVXOq0MycWp4r43FOMQWciibMYaOHCXKSPhapqTupGFAnwHoVuUUZq7jaSkqDb0/uD9MXqvJMDtU7lL0AAAAASUVORK5CYII=";
147
+ var FAVICON_LINK = `<link rel="icon" type="image/png" href="data:image/png;base64,${REDDOOR_FAVICON_PNG_BASE64}" />`;
148
+
149
+ // src/dashboard/auth/render.ts
150
+ function renderAuthChrome(email) {
151
+ if (!email) return "";
152
+ return `<div style="float:right;font-size:0.8rem;color:#666">${escapeHtml(email)} \xB7 <a href="/auth/logout">sign out</a></div>`;
153
+ }
154
+
131
155
  // src/dashboard/relative-time.ts
132
156
  function relativeTimeFromNow(iso, now = /* @__PURE__ */ new Date()) {
133
157
  if (!iso) return "\u2014";
@@ -147,10 +171,6 @@ function relativeTimeFromNow(iso, now = /* @__PURE__ */ new Date()) {
147
171
  return `${months}mo ago`;
148
172
  }
149
173
 
150
- // src/dashboard/favicon.ts
151
- var REDDOOR_FAVICON_PNG_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAACXBIWXMAAAAnAAAAJwEqCZFPAAAAk1BMVEVHcEzkGTfjGDbjGTfjGTfjGTfjGTfjGDbjGDbjGTfjGTfjGTfkGTfjGTfjGDbjGDbkGTfjGDbjGDbjGTfjGTfjGDbjGTfjGDbjGTfjGDbjGTfjGTfjGDbjGDbjGDbjGDbjGTfjGTbjGDbjGDbjGDbjGDbjGTfjGTfjGTfjGDbjGDbjGTfjGDbjGDbjGTfjGTbkGTfxxbwzAAAALXRSTlMA4DABMOD8cOBwDltwi+bFLMlk54/BDVPk/I61/u2cFaBw9nqO1izBIQE+Becdo6eEAAABBElEQVQ4y91SCVYCMQwt4kxbcEHFfUFFcMGf9P6nM0kXEPEAmtdJs+cnU+f+He2fIIEAYuVgkmvDfTG9Rh+6LoRBUBqE7gi09l9eAeeTrZJoFd5uQWfj4VbPvRqwmj9zfzP6CYpyi48F6HW5A3WuMHsEPsfvO8cSkMPTe+pfRr/MTckdg+4enqL3PkYf/YFIqiiP8VAw6EZkH6QEO0xJLUhmdbY5+TjHkCVohprlcpzlnJw9GlNkrZC16uCmWIaAZItNrT4xV0T2yxrIWoNKy4rdVXOq0MycWp4r43FOMQWciibMYaOHCXKSPhapqTupGFAnwHoVuUUZq7jaSkqDb0/uD9MXqvJMDtU7lL0AAAAASUVORK5CYII=";
152
- var FAVICON_LINK = `<link rel="icon" type="image/png" href="data:image/png;base64,${REDDOOR_FAVICON_PNG_BASE64}" />`;
153
-
154
174
  // src/dashboard/onboarding.ts
155
175
  function isNonEmpty(s) {
156
176
  return typeof s === "string" && s.trim().length > 0;
@@ -294,15 +314,16 @@ var SUBMISSION_STATUS_SCRIPT = `document.querySelectorAll("button.subm-status").
294
314
  });`;
295
315
 
296
316
  // src/dashboard/site-details.ts
297
- var SITE_STATUS_OPTIONS = [
298
- "in development",
299
- "launch period",
300
- "maintenance",
301
- "hosting",
302
- "probably not our problem",
303
- "deprecated"
304
- ];
317
+ var SITE_STATUS_OPTIONS = CANONICAL_STATUSES.map(toAirtableStatus);
305
318
  var FREQ_OPTIONS = ["None", "Monthly", "Quarterly", "Yearly"];
319
+ var WATCH_CONDITION_OPTIONS = [
320
+ "Performance",
321
+ "Accessibility",
322
+ "Best Practices",
323
+ "SEO",
324
+ "stale repo",
325
+ "no custom domain"
326
+ ];
306
327
 
307
328
  // src/dashboard/render.ts
308
329
  var DASH = "\u2014";
@@ -454,14 +475,27 @@ function recipientsLine(site) {
454
475
  const ccPart = cc.length > 0 ? ` \xB7 CC ${cc.map(escapeHtml).join(", ")}` : "";
455
476
  return `<span class="recipients">To ${to.map(escapeHtml).join(", ")}${ccPart}</span>`;
456
477
  }
478
+ function rerenderButton(r) {
479
+ if (r.sentAt !== null) return "";
480
+ const url = `/api/reports/${encodeURIComponent(r.id)}/rerender`;
481
+ return `<button class="rerender" data-rerender-url="${escapeHtml(url)}" title="Re-render this report from its current row (runs in Actions; takes a minute or two)">refresh preview</button>`;
482
+ }
483
+ function reportPreviewUrl(reportId) {
484
+ return `/api/reports/${encodeURIComponent(reportId)}/preview`;
485
+ }
486
+ function commentaryEditor(r) {
487
+ if (!rendersCommentary(r.reportType)) return "";
488
+ const url = `/api/reports/${encodeURIComponent(r.id)}/commentary`;
489
+ return `<div class="commentary"><label for="commentary-${escapeHtml(r.id)}">Commentary <span class="muted">(re-rendered into the email at send)</span></label><textarea id="commentary-${escapeHtml(r.id)}" data-commentary-for="${escapeHtml(r.id)}" data-commentary-url="${escapeHtml(url)}" rows="3">${escapeHtml(r.commentary ?? "")}</textarea><span class="commentary-saved" data-for="${escapeHtml(r.id)}"></span></div>`;
490
+ }
457
491
  function pendingRow(r, site, now) {
458
492
  const type = escapeHtml(r.reportType);
459
493
  const period = r.period ? escapeHtml(r.period) : "\u2014";
460
494
  const findings = approveBlockers(site, r);
461
495
  const blocked = findings.some((f) => f.level === "fail");
462
- const preview = r.renderedHtmlAttachment ? `<a href="${escapeHtml(safeUrl(r.renderedHtmlAttachment.url))}" rel="noopener noreferrer" title="rendered at draft time \u2014 Commentary/subject edits after drafting are not reflected">draft preview \u25B8</a>` : `<span class="muted">no preview yet</span>`;
496
+ const preview = r.renderedHtmlAttachment ? `<a href="${escapeHtml(reportPreviewUrl(r.id))}" rel="noopener noreferrer" title="rendered at draft time \u2014 Commentary/subject edits after drafting are not reflected">draft preview \u25B8</a>` : `<span class="muted">no preview yet</span>`;
463
497
  const sendLine = sendTimingLine(now);
464
- return `<li><div class="pending-head"><strong>${type}</strong> <span class="muted">${period}</span> ${preflightChip(findings)} ${preview} ${approveButton(r, blocked)}</div><div class="pending-info">${recipientsLine(site)} ${sendLine}</div>${checklistBlock(r)}${overrideControl(r)}</li>`;
498
+ return `<li><div class="pending-head"><strong>${type}</strong> <span class="muted">${period}</span> ${preflightChip(findings)} ${preview} ${rerenderButton(r)} ${approveButton(r, blocked)}</div><div class="pending-info">${recipientsLine(site)} ${sendLine}</div>${checklistBlock(r)}${commentaryEditor(r)}${overrideControl(r)}</li>`;
465
499
  }
466
500
  function pendingSection(reports, site, now) {
467
501
  const pending = reports.filter(isPendingApproval);
@@ -476,8 +510,8 @@ function gaUsersCell(r) {
476
510
  const current = String(r.gaUsersCurrent);
477
511
  if (r.gaUsersPrevious === null) return escapeHtml(current);
478
512
  const delta = r.gaUsersCurrent - r.gaUsersPrevious;
479
- const sign = delta > 0 ? "+" : "";
480
- return `${escapeHtml(current)} <span class="muted">(${escapeHtml(`${sign}${delta}`)})</span>`;
513
+ const sign2 = delta > 0 ? "+" : "";
514
+ return `${escapeHtml(current)} <span class="muted">(${escapeHtml(`${sign2}${delta}`)})</span>`;
481
515
  }
482
516
  function searchCell(r) {
483
517
  if (r.searchFoundPage1 && r.searchPosition !== null) {
@@ -491,12 +525,13 @@ function reportRow(r, site) {
491
525
  const id = escapeHtml(r.reportId);
492
526
  const ga = gaUsersCell(r);
493
527
  const search = searchCell(r);
494
- const link = r.renderedHtmlAttachment ? `<a href="${escapeHtml(safeUrl(r.renderedHtmlAttachment.url))}">view</a>` : `<span class="muted">no attachment</span>`;
528
+ const link = r.renderedHtmlAttachment ? `<a href="${escapeHtml(reportPreviewUrl(r.id))}">view</a>` : `<span class="muted">no attachment</span>`;
495
529
  const action = isPendingApproval(r) ? approveButton(
496
530
  r,
497
531
  approveBlockers(site, r).some((f) => f.level === "fail")
498
532
  ) : "";
499
- return `<tr><td>${date}</td><td>${type}</td><td><code>${id}</code></td><td>${ga}</td><td>${search}</td><td>${link}</td><td>${action}</td></tr>`;
533
+ const commentary = r.sentAt === null && !isPendingApproval(r) ? `<tr class="commentary-row"><td colspan="7">${commentaryEditor(r)}</td></tr>` : "";
534
+ return `<tr><td>${date}</td><td>${type}</td><td><code>${id}</code></td><td>${ga}</td><td>${search}</td><td>${link}</td><td>${action}</td></tr>${commentary}`;
500
535
  }
501
536
  var SUBMISSIONS_PER_SITE_CAP = 25;
502
537
  function submissionsSection(submissions, site) {
@@ -575,6 +610,28 @@ function selectRow(label, field, options, current, url) {
575
610
  function inputRow(label, field, value, url) {
576
611
  return `<div class="detail"><dt><label for="detail-${field}">${escapeHtml(label)}</label></dt><dd><input type="text" id="detail-${field}" data-detail-field="${field}" data-details-url="${url}" value="${escapeHtml(value ?? "")}" />${savedSpan(field)}</dd></div>`;
577
612
  }
613
+ var DETAIL_VALUE_FN = `function detailValue(el) {
614
+ if (el.type === "checkbox") return el.checked ? "true" : "false";
615
+ if (el.multiple) return Array.from(el.selectedOptions).map((o) => o.value).join(",");
616
+ return el.value;
617
+ }`;
618
+ function dateRow(label, field, value, url) {
619
+ return `<div class="detail"><dt><label for="detail-${field}">${escapeHtml(label)}</label></dt><dd><input type="date" id="detail-${field}" data-detail-field="${field}" data-details-url="${url}" value="${escapeHtml(value ?? "")}" />${savedSpan(field)}</dd></div>`;
620
+ }
621
+ function checkboxRow(label, field, checked, url) {
622
+ return `<div class="detail"><dt><label for="detail-${field}">${escapeHtml(label)}</label></dt><dd><input type="checkbox" id="detail-${field}" data-detail-field="${field}" data-details-url="${url}"${checked ? " checked" : ""} />${savedSpan(field)}</dd></div>`;
623
+ }
624
+ function multiSelectRow(label, field, options, selected, url) {
625
+ const sel = new Set(selected);
626
+ const opts = options.map(
627
+ (o) => `<option value="${escapeHtml(o)}"${sel.has(o) ? " selected" : ""}>${escapeHtml(o)}</option>`
628
+ ).join("");
629
+ return `<div class="detail wide"><dt><label for="detail-${field}">${escapeHtml(label)}</label></dt><dd><select multiple id="detail-${field}" data-detail-field="${field}" data-details-url="${url}">${opts}</select>${savedSpan(field)}</dd></div>`;
630
+ }
631
+ function secretRow(label, field, isSet, url) {
632
+ const ph = isSet ? "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022 (set \u2014 type to replace)" : "not set";
633
+ return `<div class="detail"><dt><label for="detail-${field}">${escapeHtml(label)}</label></dt><dd><input type="password" autocomplete="off" id="detail-${field}" data-detail-field="${field}" data-details-url="${url}" placeholder="${escapeHtml(ph)}" />${savedSpan(field)}</dd></div>`;
634
+ }
578
635
  function textareaRow(label, field, value, url) {
579
636
  return `<div class="detail wide"><dt><label for="detail-${field}">${escapeHtml(label)}</label></dt><dd><textarea id="detail-${field}" data-detail-field="${field}" data-details-url="${url}">${escapeHtml(value ?? "")}</textarea>${savedSpan(field)}</dd></div>`;
580
637
  }
@@ -582,7 +639,11 @@ function siteDetailsSection(site) {
582
639
  const url = `/api/sites/${escapeHtml(siteSlug(site.name))}/details`;
583
640
  const lastCommit = site.lastCommitAt ? `${relativeTimeFromNow(site.lastCommitAt)}` : null;
584
641
  const rows = [
585
- selectRow("Status", "status", SITE_STATUS_OPTIONS, site.status, url),
642
+ // `statusRaw`, not `status`: this select's options ARE the Airtable cell
643
+ // values (see SITE_STATUS_OPTIONS), so it must preselect against the raw cell.
644
+ // Comparing the canonical value would mis-preselect every site, and would show
645
+ // a "legacy" site as "deprecated" instead of the placeholder.
646
+ selectRow("Status", "status", SITE_STATUS_OPTIONS, site.statusRaw, url),
586
647
  selectRow("Maintenance cadence", "maintenanceFreq", FREQ_OPTIONS, site.maintenanceFreq, url),
587
648
  selectRow("Testing cadence", "testingFreq", FREQ_OPTIONS, site.testingFreq, url),
588
649
  inputRow("Report recipients (To)", "reportRecipientsTo", site.reportRecipientsTo, url),
@@ -591,6 +652,27 @@ function siteDetailsSection(site) {
591
652
  inputRow("GA4 property", "ga4PropertyId", site.ga4PropertyId, url),
592
653
  inputRow("Search query", "searchQuery", site.searchQuery, url),
593
654
  inputRow("Git repo", "gitRepo", site.gitRepo, url),
655
+ // #539 Phase 4 — the fields nothing rendered before. `Mailchimp API Key` is
656
+ // the one field in that group still absent, and deliberately: it is a live
657
+ // credential and every row here emits its stored value into the page.
658
+ inputRow("Netlify ID", "netlifyId", site.netlifyId, url),
659
+ inputRow("Search Console property", "searchConsoleProperty", site.searchConsoleProperty, url),
660
+ inputRow("Newsletter webhook", "newsletterWebhook", site.newsletterWebhook, url),
661
+ inputRow("Mailchimp audience ID", "mailchimpAudienceId", site.mailchimpAudienceId, url),
662
+ dateRow("Last maintenance day", "maintenanceDay", site.maintenanceDay, url),
663
+ dateRow("Last testing day", "testingDay", site.testingDay, url),
664
+ // Raw JSON, and shown as the raw cell rather than the parsed object: what the
665
+ // operator edits has to be the thing `parseNotifyRouting` will read back.
666
+ textareaRow("Notify routing (JSON)", "notifyRouting", site.notifyRoutingRaw, url),
667
+ checkboxRow("Require Turnstile", "requireTurnstile", site.requireTurnstile, url),
668
+ secretRow("Mailchimp API key", "mailchimpApiKey", site.mailchimpApiKey !== null, url),
669
+ multiSelectRow(
670
+ "Accepted watch conditions",
671
+ "acceptedWatchConditions",
672
+ WATCH_CONDITION_OPTIONS,
673
+ site.acceptedWatchConditions,
674
+ url
675
+ ),
594
676
  textareaRow("Copy \u2014 Intro", "copyIntro", site.copyIntro, url),
595
677
  textareaRow("Copy \u2014 Contact", "copyContact", site.copyContact, url),
596
678
  textareaRow("Copy \u2014 Footer", "copyFooter", site.copyFooter, url),
@@ -754,7 +836,7 @@ button.trigger-renovate:disabled { opacity: 0.6; cursor: default; }
754
836
  .chip.accepted { background: transparent; border: 1px dashed #bbb; color: #888; }
755
837
  @media (prefers-color-scheme: dark) { .chip.accepted { border-color: #444; } .chip.critical { background: #2a0f0d; color: #ff8a80; } }
756
838
  `;
757
- function renderSiteDashboardHtml(site, reports, submissions = [], spamTotals = null, now = /* @__PURE__ */ new Date(), alarm = null) {
839
+ function renderSiteDashboardHtml(site, reports, submissions = [], spamTotals = null, now = /* @__PURE__ */ new Date(), alarm = null, operatorEmail = null) {
758
840
  const name = escapeHtml(site.name);
759
841
  const urlSafe = safeUrl(site.url);
760
842
  const allScoresNull = site.pScore === null && site.rScore === null && site.bpScore === null && site.seoScore === null;
@@ -787,6 +869,7 @@ function renderSiteDashboardHtml(site, reports, submissions = [], spamTotals = n
787
869
  <style>${STYLES}${SUBMISSION_STYLES}</style>
788
870
  </head>
789
871
  <body>
872
+ ${renderAuthChrome(operatorEmail)}
790
873
  <a class="home" href="/">\u2190 Fleet home</a>
791
874
  <h1>${name}</h1>
792
875
  <div class="meta"><a href="${escapeHtml(urlSafe)}">${escapeHtml(site.url)}</a></div>
@@ -932,12 +1015,13 @@ function renderSiteDashboardHtml(site, reports, submissions = [], spamTotals = n
932
1015
  });
933
1016
  // Site-details editor: save on change (selects) / blur (inputs+textareas, only
934
1017
  // when the value actually changed). The per-field span shows \u2713 / \u2717.
1018
+ ${DETAIL_VALUE_FN}
935
1019
  function saveDetail(el) {
936
1020
  const span = document.querySelector('.detail-saved[data-for="' + el.dataset.detailField + '"]');
937
1021
  fetch(el.dataset.detailsUrl, {
938
1022
  method: "POST",
939
1023
  headers: { "content-type": "application/json" },
940
- body: JSON.stringify({ field: el.dataset.detailField, value: el.value }),
1024
+ body: JSON.stringify({ field: el.dataset.detailField, value: detailValue(el) }),
941
1025
  })
942
1026
  .then((r) => {
943
1027
  if (span) span.textContent = r.ok ? " \u2713" : " \u2717";
@@ -949,11 +1033,55 @@ function renderSiteDashboardHtml(site, reports, submissions = [], spamTotals = n
949
1033
  document.querySelectorAll("select[data-detail-field]").forEach((s) => {
950
1034
  s.addEventListener("change", () => saveDetail(s));
951
1035
  });
952
- document.querySelectorAll("input[data-detail-field], textarea[data-detail-field]").forEach((i) => {
1036
+ // Checkboxes save on CHANGE. They cannot use the blur path below: that path
1037
+ // only fires when \`value !== defaultValue\`, and for a checkbox both are the
1038
+ // "on" content attribute, so it would never save at all.
1039
+ document.querySelectorAll("input[type=checkbox][data-detail-field]").forEach((c) => {
1040
+ c.addEventListener("change", () => saveDetail(c));
1041
+ });
1042
+ document.querySelectorAll("input:not([type=checkbox])[data-detail-field], textarea[data-detail-field]").forEach((i) => {
953
1043
  i.addEventListener("blur", () => {
954
1044
  if (i.value !== i.defaultValue) saveDetail(i);
955
1045
  });
956
1046
  });
1047
+ // Refresh preview: dispatch the re-render workflow, then tell the operator to
1048
+ // reload once it lands. No polling \u2014 the run takes a minute or two and a
1049
+ // spinner that long reads as a hang.
1050
+ document.querySelectorAll("button.rerender").forEach((b) => {
1051
+ b.addEventListener("click", async () => {
1052
+ b.disabled = true;
1053
+ b.textContent = "Refreshing\u2026";
1054
+ try {
1055
+ const res = await fetch(b.dataset.rerenderUrl, { method: "POST" });
1056
+ b.textContent = res.ok ? "Queued \u2713 reload in ~2 min" : "Failed";
1057
+ if (!res.ok) b.disabled = false;
1058
+ } catch {
1059
+ b.textContent = "Failed";
1060
+ b.disabled = false;
1061
+ }
1062
+ });
1063
+ });
1064
+ // Report commentary: save on blur, only when it actually changed. Same
1065
+ // shape as the site-details editor, but keyed on the REPORT id rather than a
1066
+ // field name, so it posts { text } to the report's own endpoint.
1067
+ document.querySelectorAll("textarea[data-commentary-for]").forEach((t) => {
1068
+ t.addEventListener("blur", () => {
1069
+ if (t.value === t.defaultValue) return;
1070
+ const span = document.querySelector('.commentary-saved[data-for="' + t.dataset.commentaryFor + '"]');
1071
+ fetch(t.dataset.commentaryUrl, {
1072
+ method: "POST",
1073
+ headers: { "content-type": "application/json" },
1074
+ body: JSON.stringify({ text: t.value }),
1075
+ })
1076
+ .then((r) => {
1077
+ if (span) span.textContent = r.ok ? " \u2713" : " \u2717";
1078
+ if (r.ok) t.defaultValue = t.value;
1079
+ })
1080
+ .catch(() => {
1081
+ if (span) span.textContent = " \u2717";
1082
+ });
1083
+ });
1084
+ });
957
1085
  ${SUBMISSION_STATUS_SCRIPT}
958
1086
  </script>
959
1087
  </body>
@@ -1612,7 +1740,7 @@ var AUDIT_SCRIPT = `<script>
1612
1740
  } catch(e){}
1613
1741
  })();
1614
1742
  </script>`;
1615
- function renderCockpitHtml(model) {
1743
+ function renderCockpitHtml(model, operatorEmail = null) {
1616
1744
  const total = model.cards.length;
1617
1745
  const feed = buildNeedsYouFeed(model);
1618
1746
  return `<!doctype html>
@@ -1625,8 +1753,9 @@ function renderCockpitHtml(model) {
1625
1753
  <style>${STYLES2}</style>
1626
1754
  </head>
1627
1755
  <body>
1756
+ ${renderAuthChrome(operatorEmail)}
1628
1757
  <h1>Reddoor fleet cockpit</h1>
1629
- <div class="meta">${total} site${total === 1 ? "" : "s"} on the Reddoor stack.</div>
1758
+ <div class="meta">${total} site${total === 1 ? "" : "s"} on the Reddoor stack. <a href="/fleet">Fleet table \u2192</a></div>
1630
1759
  ${verdictBar(model, feed)}
1631
1760
  ${renderNeedsYouFeed(feed)}
1632
1761
  ${renderFleetBrowsePanel(model)}
@@ -1659,6 +1788,15 @@ function verifyBasicAuth(authHeader, expectedPassword) {
1659
1788
  if (a.length !== b.length) return false;
1660
1789
  return timingSafeEqual(a, b);
1661
1790
  }
1791
+
1792
+ // src/dashboard/auth/signing.ts
1793
+ import { createHmac, timingSafeEqual as timingSafeEqual2 } from "crypto";
1794
+
1795
+ // src/dashboard/auth/session.ts
1796
+ var SESSION_TTL_SECONDS = 30 * 24 * 60 * 60;
1797
+
1798
+ // src/dashboard/prospect-audit-trigger.ts
1799
+ var PROSPECT_AUDIT_DUPLICATE_WINDOW_MS = 10 * 60 * 1e3;
1662
1800
  export {
1663
1801
  ALL_AUDIT_NAMES,
1664
1802
  ALL_RECIPE_NAMES,
@@ -1681,6 +1819,7 @@ export {
1681
1819
  lighthouseAudit,
1682
1820
  lintAudit,
1683
1821
  loadBundledImages,
1822
+ loadHeadline,
1684
1823
  loadPlate,
1685
1824
  localPath,
1686
1825
  onboard,