@reddoorla/maintenance 0.76.0 → 0.79.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 (125) hide show
  1. package/README.md +34 -7
  2. package/dist/{blux-RIJBRVCF.js → blux-2P4FGCUL.js} +5 -5
  3. package/dist/{blux-RIJBRVCF.js.map → blux-2P4FGCUL.js.map} +1 -1
  4. package/dist/{bump-deps-OQR3IXLN.js → bump-deps-XB2LJTVN.js} +3 -3
  5. package/dist/{chunk-RHPDQW6D.js → chunk-2SLED3NB.js} +1 -1
  6. package/dist/{chunk-RHPDQW6D.js.map → chunk-2SLED3NB.js.map} +1 -1
  7. package/dist/{chunk-3U3IGVAQ.js → chunk-3LWKIKZ2.js} +47 -9
  8. package/dist/chunk-3LWKIKZ2.js.map +1 -0
  9. package/dist/{chunk-HIN3P4ZN.js → chunk-4SOCPK7A.js} +10 -1
  10. package/dist/chunk-4SOCPK7A.js.map +1 -0
  11. package/dist/{chunk-CASCWQQX.js → chunk-73UFRZKY.js} +34 -19
  12. package/dist/chunk-73UFRZKY.js.map +1 -0
  13. package/dist/chunk-A3WDWNN5.js +70 -0
  14. package/dist/chunk-A3WDWNN5.js.map +1 -0
  15. package/dist/{chunk-D3DQFC32.js → chunk-ATJ6ZA2V.js} +2 -2
  16. package/dist/{chunk-ZO7WNY57.js → chunk-B5ZUQZFL.js} +2 -2
  17. package/dist/{chunk-PH3AGF4Z.js → chunk-DC5H7KEQ.js} +2 -2
  18. package/dist/{chunk-DYKG53IR.js → chunk-FAQIMC26.js} +9 -9
  19. package/dist/{chunk-4VAUSRSS.js → chunk-FVVGDIGX.js} +2 -2
  20. package/dist/{chunk-7MJBTV2R.js → chunk-FX7RAMGC.js} +2 -2
  21. package/dist/{chunk-PKVZMFEB.js → chunk-K5JZ5KLO.js} +2 -2
  22. package/dist/{chunk-CZAMYVOP.js → chunk-KPQXB5CR.js} +2 -2
  23. package/dist/{chunk-BTEBRTW4.js → chunk-LS6QPANO.js} +2 -2
  24. package/dist/{chunk-2X322ZES.js → chunk-MGJ72BA4.js} +2 -2
  25. package/dist/chunk-MNDIED4M.js +137 -0
  26. package/dist/chunk-MNDIED4M.js.map +1 -0
  27. package/dist/{chunk-ZYBOT5PM.js → chunk-NT4WIP7I.js} +2 -2
  28. package/dist/{chunk-JNXCDUYB.js → chunk-Q276MZ7E.js} +3 -4
  29. package/dist/chunk-Q276MZ7E.js.map +1 -0
  30. package/dist/{chunk-GYNRZCM6.js → chunk-QG6OSL4M.js} +2 -2
  31. package/dist/{chunk-IRRZG66U.js → chunk-QMXQUL5Z.js} +34 -18
  32. package/dist/chunk-QMXQUL5Z.js.map +1 -0
  33. package/dist/{chunk-YEGHUODU.js → chunk-VSHC4HOI.js} +96 -1
  34. package/dist/chunk-VSHC4HOI.js.map +1 -0
  35. package/dist/{chunk-JTRTG5CU.js → chunk-YIQ7IWE3.js} +2 -2
  36. package/dist/{chunk-XKOZUVK2.js → chunk-ZTPPCHDB.js} +1 -1
  37. package/dist/chunk-ZTPPCHDB.js.map +1 -0
  38. package/dist/cli/bin.js +32 -21
  39. package/dist/cli/bin.js.map +1 -1
  40. package/dist/cli/commands/audit.d.ts +1 -1
  41. package/dist/cli/commands/audit.js +7 -5
  42. package/dist/cli/commands/audit.js.map +1 -1
  43. package/dist/client-X5WUJWDE.js +11 -0
  44. package/dist/configs/eslint.js +10 -0
  45. package/dist/configs/eslint.js.map +1 -1
  46. package/dist/{convert-to-pnpm-OVMASATZ.js → convert-to-pnpm-FZHSLUQB.js} +3 -3
  47. package/dist/{db-3QW2XEXA.js → db-JSIZYT23.js} +3 -3
  48. package/dist/{digest-75FWSC74.js → digest-NQAQI34P.js} +11 -11
  49. package/dist/forms/index.js +6 -62
  50. package/dist/forms/index.js.map +1 -1
  51. package/dist/{github-signals-TF3VSNIN.js → github-signals-4LWQGD5V.js} +5 -5
  52. package/dist/{health-endpoint-JZGYCMTV.js → health-endpoint-LFVE26QS.js} +3 -3
  53. package/dist/index.d.ts +11 -3
  54. package/dist/index.js +32 -24
  55. package/dist/index.js.map +1 -1
  56. package/dist/{init-2KOISBCZ.js → init-Y5O33BUL.js} +14 -12
  57. package/dist/{init-2KOISBCZ.js.map → init-Y5O33BUL.js.map} +1 -1
  58. package/dist/{launch-K4EHKTXC.js → launch-3SYLX263.js} +8 -5
  59. package/dist/launch-3SYLX263.js.map +1 -0
  60. package/dist/migrate-LJUFGXQZ.js +7 -0
  61. package/dist/{onboard-PX36YDZA.js → onboard-RDGHVCNG.js} +3 -3
  62. package/dist/{orchestrate-CPR6KVS2.js → orchestrate-QOQXOJLI.js} +5 -5
  63. package/dist/{preflight-QRRMPI7K.js → preflight-2PWVVIRR.js} +6 -6
  64. package/dist/protection-audit-X3BHT2MB.js +140 -0
  65. package/dist/protection-audit-X3BHT2MB.js.map +1 -0
  66. package/dist/recipes/sync-configs.d.ts +1 -1
  67. package/dist/recipes/sync-configs.js +3 -3
  68. package/dist/{renovate-dispatch-6II2JVOX.js → renovate-dispatch-2VYCEH42.js} +2 -2
  69. package/dist/renovate-dispatch-2VYCEH42.js.map +1 -0
  70. package/dist/{report-SLGBDJ6O.js → report-IU4CLJS5.js} +3 -3
  71. package/dist/{self-updating-2YSVNMPP.js → self-updating-ALMUWJNX.js} +5 -4
  72. package/dist/{self-updating-2YSVNMPP.js.map → self-updating-ALMUWJNX.js.map} +1 -1
  73. package/dist/{selftest-RVASRO3Z.js → selftest-PJFABZDM.js} +5 -5
  74. package/dist/{smoke-suite-CSP23NZM.js → smoke-suite-SUEJFBYP.js} +3 -3
  75. package/dist/{submissions-MDKWJYMM.js → submissions-3I3GAQAX.js} +13 -5
  76. package/dist/submissions-3I3GAQAX.js.map +1 -0
  77. package/dist/{submissions-BNRGY3JQ.js → submissions-SURN7BV5.js} +3 -3
  78. package/dist/{svelte-codemods-V54KOBWU.js → svelte-codemods-IWO7X3F3.js} +3 -3
  79. package/dist/{sync-configs-UBCJRASZ.js → sync-configs-7XGHFC6P.js} +4 -4
  80. package/dist/{types-0jreMCF5.d.ts → types-DnEL3NRn.d.ts} +1 -1
  81. package/dist/{upgrade-WR6ICPAG.js → upgrade-AM4S7JF3.js} +3 -3
  82. package/package.json +1 -1
  83. package/dist/chunk-3U3IGVAQ.js.map +0 -1
  84. package/dist/chunk-CASCWQQX.js.map +0 -1
  85. package/dist/chunk-HIN3P4ZN.js.map +0 -1
  86. package/dist/chunk-IRRZG66U.js.map +0 -1
  87. package/dist/chunk-JNXCDUYB.js.map +0 -1
  88. package/dist/chunk-XKOZUVK2.js.map +0 -1
  89. package/dist/chunk-YEGHUODU.js.map +0 -1
  90. package/dist/client-NVVQK3HH.js +0 -11
  91. package/dist/launch-K4EHKTXC.js.map +0 -1
  92. package/dist/migrate-35DNNF3H.js +0 -7
  93. package/dist/renovate-dispatch-6II2JVOX.js.map +0 -1
  94. package/dist/submissions-MDKWJYMM.js.map +0 -1
  95. /package/dist/{bump-deps-OQR3IXLN.js.map → bump-deps-XB2LJTVN.js.map} +0 -0
  96. /package/dist/{chunk-D3DQFC32.js.map → chunk-ATJ6ZA2V.js.map} +0 -0
  97. /package/dist/{chunk-ZO7WNY57.js.map → chunk-B5ZUQZFL.js.map} +0 -0
  98. /package/dist/{chunk-PH3AGF4Z.js.map → chunk-DC5H7KEQ.js.map} +0 -0
  99. /package/dist/{chunk-DYKG53IR.js.map → chunk-FAQIMC26.js.map} +0 -0
  100. /package/dist/{chunk-4VAUSRSS.js.map → chunk-FVVGDIGX.js.map} +0 -0
  101. /package/dist/{chunk-7MJBTV2R.js.map → chunk-FX7RAMGC.js.map} +0 -0
  102. /package/dist/{chunk-PKVZMFEB.js.map → chunk-K5JZ5KLO.js.map} +0 -0
  103. /package/dist/{chunk-CZAMYVOP.js.map → chunk-KPQXB5CR.js.map} +0 -0
  104. /package/dist/{chunk-BTEBRTW4.js.map → chunk-LS6QPANO.js.map} +0 -0
  105. /package/dist/{chunk-2X322ZES.js.map → chunk-MGJ72BA4.js.map} +0 -0
  106. /package/dist/{chunk-ZYBOT5PM.js.map → chunk-NT4WIP7I.js.map} +0 -0
  107. /package/dist/{chunk-GYNRZCM6.js.map → chunk-QG6OSL4M.js.map} +0 -0
  108. /package/dist/{chunk-JTRTG5CU.js.map → chunk-YIQ7IWE3.js.map} +0 -0
  109. /package/dist/{client-NVVQK3HH.js.map → client-X5WUJWDE.js.map} +0 -0
  110. /package/dist/{convert-to-pnpm-OVMASATZ.js.map → convert-to-pnpm-FZHSLUQB.js.map} +0 -0
  111. /package/dist/{db-3QW2XEXA.js.map → db-JSIZYT23.js.map} +0 -0
  112. /package/dist/{digest-75FWSC74.js.map → digest-NQAQI34P.js.map} +0 -0
  113. /package/dist/{github-signals-TF3VSNIN.js.map → github-signals-4LWQGD5V.js.map} +0 -0
  114. /package/dist/{health-endpoint-JZGYCMTV.js.map → health-endpoint-LFVE26QS.js.map} +0 -0
  115. /package/dist/{migrate-35DNNF3H.js.map → migrate-LJUFGXQZ.js.map} +0 -0
  116. /package/dist/{onboard-PX36YDZA.js.map → onboard-RDGHVCNG.js.map} +0 -0
  117. /package/dist/{orchestrate-CPR6KVS2.js.map → orchestrate-QOQXOJLI.js.map} +0 -0
  118. /package/dist/{preflight-QRRMPI7K.js.map → preflight-2PWVVIRR.js.map} +0 -0
  119. /package/dist/{report-SLGBDJ6O.js.map → report-IU4CLJS5.js.map} +0 -0
  120. /package/dist/{selftest-RVASRO3Z.js.map → selftest-PJFABZDM.js.map} +0 -0
  121. /package/dist/{smoke-suite-CSP23NZM.js.map → smoke-suite-SUEJFBYP.js.map} +0 -0
  122. /package/dist/{submissions-BNRGY3JQ.js.map → submissions-SURN7BV5.js.map} +0 -0
  123. /package/dist/{svelte-codemods-V54KOBWU.js.map → svelte-codemods-IWO7X3F3.js.map} +0 -0
  124. /package/dist/{sync-configs-UBCJRASZ.js.map → sync-configs-7XGHFC6P.js.map} +0 -0
  125. /package/dist/{upgrade-WR6ICPAG.js.map → upgrade-AM4S7JF3.js.map} +0 -0
@@ -11,8 +11,8 @@ import {
11
11
  } from "./chunk-4BHNP6Y2.js";
12
12
  import {
13
13
  bumpDeps
14
- } from "./chunk-D3DQFC32.js";
15
- import "./chunk-XKOZUVK2.js";
14
+ } from "./chunk-ATJ6ZA2V.js";
15
+ import "./chunk-ZTPPCHDB.js";
16
16
  import "./chunk-FDIFTIXC.js";
17
17
  import "./chunk-HVOOCK6L.js";
18
18
  import "./chunk-XXTZBPUY.js";
@@ -57,4 +57,4 @@ async function runBumpDepsCommand(site, opts) {
57
57
  export {
58
58
  runBumpDepsCommand
59
59
  };
60
- //# sourceMappingURL=bump-deps-OQR3IXLN.js.map
60
+ //# sourceMappingURL=bump-deps-XB2LJTVN.js.map
@@ -26,4 +26,4 @@ export {
26
26
  toStatus,
27
27
  toNotifyStatus
28
28
  };
29
- //# sourceMappingURL=chunk-RHPDQW6D.js.map
29
+ //# sourceMappingURL=chunk-2SLED3NB.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/reports/submission-row.ts"],"sourcesContent":["import { SUBMISSION_FORM_TYPES, type FormType } from \"../forms/types.js\";\n\nexport { SUBMISSION_FORM_TYPES };\nexport type { FormType };\n\nexport const SUBMISSION_STATUSES = [\"new\", \"read\", \"archived\", \"spam\", \"spam_auto\"] as const;\nexport type SubmissionStatus = (typeof SUBMISSION_STATUSES)[number];\n\n// \"bounced\" (2026-07-16): Resend ACCEPTED the notification (\"sent\") but later\n// reported a bounce/complaint via webhook — the lead never reached the client\n// (the Espada failure mode: 4 of 8 notifications bounced with nothing alarming).\n// The resend-webhook maps the event back onto the submission by resend_message_id.\nexport const NOTIFY_STATUSES = [\"sent\", \"failed\", \"skipped\", \"bounced\"] as const;\nexport type NotifyStatus = (typeof NOTIFY_STATUSES)[number];\n\nexport function toFormType(raw: string | undefined): FormType {\n if (raw && (SUBMISSION_FORM_TYPES as readonly string[]).includes(raw)) return raw as FormType;\n if (raw)\n console.warn(`[submissions] unknown Form type ${JSON.stringify(raw)} — treating as contact`);\n return \"contact\";\n}\n\nexport function toStatus(raw: string | undefined): SubmissionStatus {\n if (raw && (SUBMISSION_STATUSES as readonly string[]).includes(raw))\n return raw as SubmissionStatus;\n return \"new\";\n}\n\nexport function toNotifyStatus(raw: string | undefined): NotifyStatus {\n if (raw && (NOTIFY_STATUSES as readonly string[]).includes(raw)) return raw as NotifyStatus;\n return \"skipped\";\n}\n\nexport type SubmissionRow = {\n id: string;\n submissionId: number | null;\n siteId: string;\n formType: FormType;\n name: string;\n email: string;\n phone: string | null;\n message: string | null;\n /** Raw JSON string of any site-specific fields the typed columns didn't claim. */\n extraFields: string | null;\n sourceUrl: string | null;\n utm: string | null;\n submittedAt: string | null;\n status: SubmissionStatus;\n notifyStatus: NotifyStatus;\n resendMessageId: string | null;\n /** Heuristic spam score at ingest time; null for pre-classifier / un-scored rows. */\n spamScore?: number | null;\n /** Comma-joined classifier reason codes (e.g. \"links:3,disposable-email\"); null when unscored. */\n spamReason?: string | null;\n};\n\nexport type SubmissionInput = {\n siteId: string;\n formType: FormType;\n name: string;\n email: string;\n phone?: string;\n message?: string;\n extraFields?: Record<string, unknown>;\n sourceUrl?: string;\n utm?: string;\n submittedAt: Date;\n status?: SubmissionStatus;\n spamScore?: number | null;\n spamReason?: string | null;\n};\n"],"mappings":";;;;;AAKO,IAAM,sBAAsB,CAAC,OAAO,QAAQ,YAAY,QAAQ,WAAW;AAO3E,IAAM,kBAAkB,CAAC,QAAQ,UAAU,WAAW,SAAS;AAG/D,SAAS,WAAW,KAAmC;AAC5D,MAAI,OAAQ,sBAA4C,SAAS,GAAG,EAAG,QAAO;AAC9E,MAAI;AACF,YAAQ,KAAK,mCAAmC,KAAK,UAAU,GAAG,CAAC,6BAAwB;AAC7F,SAAO;AACT;AAEO,SAAS,SAAS,KAA2C;AAClE,MAAI,OAAQ,oBAA0C,SAAS,GAAG;AAChE,WAAO;AACT,SAAO;AACT;AAEO,SAAS,eAAe,KAAuC;AACpE,MAAI,OAAQ,gBAAsC,SAAS,GAAG,EAAG,QAAO;AACxE,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/reports/submission-row.ts"],"sourcesContent":["import { SUBMISSION_FORM_TYPES, type FormType } from \"../forms/types.js\";\n\nexport { SUBMISSION_FORM_TYPES };\nexport type { FormType };\n\nexport const SUBMISSION_STATUSES = [\"new\", \"read\", \"archived\", \"spam\", \"spam_auto\"] as const;\nexport type SubmissionStatus = (typeof SUBMISSION_STATUSES)[number];\n\n// \"bounced\" (2026-07-16): Resend ACCEPTED the notification (\"sent\") but later\n// reported a bounce/complaint via webhook — the lead never reached the client\n// (the Espada failure mode: 4 of 8 notifications bounced with nothing alarming).\n// The resend-webhook maps the event back onto the submission by resend_message_id.\nexport const NOTIFY_STATUSES = [\"sent\", \"failed\", \"skipped\", \"bounced\"] as const;\nexport type NotifyStatus = (typeof NOTIFY_STATUSES)[number];\n\nexport function toFormType(raw: string | undefined): FormType {\n if (raw && (SUBMISSION_FORM_TYPES as readonly string[]).includes(raw)) return raw as FormType;\n if (raw)\n console.warn(`[submissions] unknown Form type ${JSON.stringify(raw)} — treating as contact`);\n return \"contact\";\n}\n\nexport function toStatus(raw: string | undefined): SubmissionStatus {\n if (raw && (SUBMISSION_STATUSES as readonly string[]).includes(raw))\n return raw as SubmissionStatus;\n return \"new\";\n}\n\nexport function toNotifyStatus(raw: string | undefined): NotifyStatus {\n if (raw && (NOTIFY_STATUSES as readonly string[]).includes(raw)) return raw as NotifyStatus;\n return \"skipped\";\n}\n\nexport type SubmissionRow = {\n id: string;\n submissionId: number | null;\n siteId: string;\n formType: FormType;\n name: string;\n email: string;\n phone: string | null;\n message: string | null;\n /** Raw JSON string of any site-specific fields the typed columns didn't claim. */\n extraFields: string | null;\n sourceUrl: string | null;\n utm: string | null;\n submittedAt: string | null;\n status: SubmissionStatus;\n notifyStatus: NotifyStatus;\n resendMessageId: string | null;\n /** Heuristic spam score at ingest time; null for pre-classifier / un-scored rows. */\n spamScore?: number | null;\n /** Comma-joined classifier reason codes (e.g. \"links:3,disposable-email\"); null when unscored. */\n spamReason?: string | null;\n /** Comma-joined newsletter fan-out outcome per destination — `webhook:ok`,\n * `mailchimp:401`, `mailchimp:threw`, `mailchimp-tags:failed`. Null means nothing\n * was attempted: a non-newsletter form, a spam row, a site with no destination\n * configured, or a row written before 0005. See ingest.ts for the token grammar. */\n fanoutStatus?: string | null;\n};\n\nexport type SubmissionInput = {\n siteId: string;\n formType: FormType;\n name: string;\n email: string;\n phone?: string;\n message?: string;\n extraFields?: Record<string, unknown>;\n sourceUrl?: string;\n utm?: string;\n submittedAt: Date;\n status?: SubmissionStatus;\n spamScore?: number | null;\n spamReason?: string | null;\n};\n"],"mappings":";;;;;AAKO,IAAM,sBAAsB,CAAC,OAAO,QAAQ,YAAY,QAAQ,WAAW;AAO3E,IAAM,kBAAkB,CAAC,QAAQ,UAAU,WAAW,SAAS;AAG/D,SAAS,WAAW,KAAmC;AAC5D,MAAI,OAAQ,sBAA4C,SAAS,GAAG,EAAG,QAAO;AAC9E,MAAI;AACF,YAAQ,KAAK,mCAAmC,KAAK,UAAU,GAAG,CAAC,6BAAwB;AAC7F,SAAO;AACT;AAEO,SAAS,SAAS,KAA2C;AAClE,MAAI,OAAQ,oBAA0C,SAAS,GAAG;AAChE,WAAO;AACT,SAAO;AACT;AAEO,SAAS,eAAe,KAAuC;AACpE,MAAI,OAAQ,gBAAsC,SAAS,GAAG,EAAG,QAAO;AACxE,SAAO;AACT;","names":[]}
@@ -3,13 +3,16 @@ import {
3
3
  } from "./chunk-GASBX52O.js";
4
4
  import {
5
5
  assertUrlSegment
6
- } from "./chunk-YEGHUODU.js";
6
+ } from "./chunk-VSHC4HOI.js";
7
7
  import {
8
8
  baselineVersions
9
9
  } from "./chunk-LKGVSM2O.js";
10
10
  import {
11
11
  defaultSpawn
12
12
  } from "./chunk-HVOOCK6L.js";
13
+ import {
14
+ INGEST_TIMEOUT_MS
15
+ } from "./chunk-A3WDWNN5.js";
13
16
  import {
14
17
  siteLabel
15
18
  } from "./chunk-XXTZBPUY.js";
@@ -604,6 +607,11 @@ async function readSiteConfig(sitePath) {
604
607
  if (typeof url === "string" && url.length > 0) {
605
608
  out.lighthouseUrl = url;
606
609
  }
610
+ const routes = cfg.a11yRoutes;
611
+ if (Array.isArray(routes)) {
612
+ const clean = routes.filter((r) => typeof r === "string").map((r) => r.trim()).filter((r) => r.length > 0);
613
+ if (clean.length > 0) out.a11yRoutes = clean;
614
+ }
607
615
  return out;
608
616
  }
609
617
 
@@ -863,13 +871,13 @@ export default defineConfig({
863
871
  });
864
872
  `;
865
873
  }
866
- function buildSpec() {
874
+ function buildSpec(axePages) {
867
875
  return `import { test, expect } from "@playwright/test";
868
876
  import AxeBuilder from "@axe-core/playwright";
869
877
  import { mkdir, writeFile } from "node:fs/promises";
870
878
  import { dirname } from "node:path";
871
879
 
872
- const pages = ${JSON.stringify(a11yRoutes)};
880
+ const pages = ${JSON.stringify(axePages)};
873
881
  const smokePages = ${JSON.stringify(smokeRoutes)};
874
882
  const OUTPUT = process.env.REDDOOR_A11Y_OUTPUT;
875
883
 
@@ -955,8 +963,13 @@ async function a11yAudit(ctx) {
955
963
  const label = siteLabel(site);
956
964
  const specDir = await mkdtemp2(join6(site.path, ".reddoor-a11y-spec-"));
957
965
  try {
966
+ const { a11yRoutes: siteRoutes } = await readSiteConfig(site.path);
967
+ const axePages = [
968
+ ...a11yRoutes,
969
+ ...(siteRoutes ?? []).map((path) => ({ path, name: path }))
970
+ ];
958
971
  const specPath = join6(specDir, "a11y.spec.ts");
959
- await writeFile2(specPath, buildSpec(), "utf-8");
972
+ await writeFile2(specPath, buildSpec(axePages), "utf-8");
960
973
  const port = await findFreePort();
961
974
  const configPath = join6(specDir, "playwright.config.ts");
962
975
  await writeFile2(configPath, buildPlaywrightConfig(port, site.path), "utf-8");
@@ -2014,6 +2027,18 @@ async function smokeAudit(ctx) {
2014
2027
  // src/audits/form-e2e.ts
2015
2028
  var CF_TEST_SITEKEY = "1x00000000000000000000AA";
2016
2029
  var CONTACT_PATHS = ["/contact", "/"];
2030
+ var TESTMODE_SKIPPED_WORK_MS = 1e3;
2031
+ var BUDGET_WARN_RATIO = 0.5;
2032
+ function projectRealSubmissionMs(probeElapsedMs) {
2033
+ return probeElapsedMs + TESTMODE_SKIPPED_WORK_MS;
2034
+ }
2035
+ function isIngestBudgetThin(probeElapsedMs, budgetMs = INGEST_TIMEOUT_MS) {
2036
+ return projectRealSubmissionMs(probeElapsedMs) > budgetMs * BUDGET_WARN_RATIO;
2037
+ }
2038
+ function budgetThinSummary(probeElapsedMs) {
2039
+ const s = (ms) => `${(ms / 1e3).toFixed(1)}s`;
2040
+ return `BUDGET_THIN: probe ${s(probeElapsedMs)} + ~${s(TESTMODE_SKIPPED_WORK_MS)} of sink work the probe skips \u2248 ${s(projectRealSubmissionMs(probeElapsedMs))} projected against a ${s(INGEST_TIMEOUT_MS)} abort budget \u2014 a real submission may be reported to the visitor as failed while central still captures the lead`;
2041
+ }
2017
2042
  var LIVE_ENV_VAR = "REDDOOR_FORM_E2E_LIVE";
2018
2043
  function liveRunnerEnabled(env = process.env) {
2019
2044
  return env[LIVE_ENV_VAR] === "1" || env[LIVE_ENV_VAR] === "true";
@@ -2059,12 +2084,23 @@ async function formE2eAudit(ctx) {
2059
2084
  };
2060
2085
  }
2061
2086
  const ok = outcome.success ? "pass" : "fail";
2087
+ const details = { ok, formPresent: true, checkedAt };
2088
+ if (!outcome.success) {
2089
+ return {
2090
+ audit: "form-e2e",
2091
+ site: label,
2092
+ status: "warn",
2093
+ summary: `form-e2e: synthetic submission failed${outcome.detail ? ` \u2014 ${outcome.detail}` : ""}`,
2094
+ details
2095
+ };
2096
+ }
2097
+ const thin = typeof outcome.elapsedMs === "number" && isIngestBudgetThin(outcome.elapsedMs) ? budgetThinSummary(outcome.elapsedMs) : null;
2062
2098
  return {
2063
2099
  audit: "form-e2e",
2064
2100
  site: label,
2065
- status: outcome.success ? "pass" : "warn",
2066
- summary: outcome.success ? "form-e2e: synthetic submission succeeded" : `form-e2e: synthetic submission failed${outcome.detail ? ` \u2014 ${outcome.detail}` : ""}`,
2067
- details: { ok, formPresent: true, checkedAt }
2101
+ status: thin ? "warn" : "pass",
2102
+ summary: thin ? `form-e2e: synthetic submission succeeded \u2014 ${thin}` : "form-e2e: synthetic submission succeeded",
2103
+ details
2068
2104
  };
2069
2105
  } finally {
2070
2106
  await runner.close?.();
@@ -2144,9 +2180,11 @@ async function defaultFormRunner() {
2144
2180
  const postResponse = page.waitForResponse((r) => r.request().method() === "POST", {
2145
2181
  timeout: PAGE_TIMEOUT_MS2
2146
2182
  }).catch(() => null);
2183
+ const startedAt = Date.now();
2147
2184
  await page.locator('button[type="submit"], input[type="submit"]').first().click({ timeout: PAGE_TIMEOUT_MS2 });
2148
2185
  const ok = await page.locator('[role="status"]').first().waitFor({ state: "visible", timeout: PAGE_TIMEOUT_MS2 }).then(() => true).catch(() => false);
2149
- if (ok) return { formPresent: true, success: true };
2186
+ const elapsedMs = Date.now() - startedAt;
2187
+ if (ok) return { formPresent: true, success: true, elapsedMs };
2150
2188
  const actionResp = await postResponse;
2151
2189
  const alertText = await page.locator('[role="alert"]').first().textContent({ timeout: 1e3 }).catch(() => null);
2152
2190
  const respBit = actionResp ? `POST ${actionResp.status()}${actionResp.status() >= 400 ? ` ${(await actionResp.text().catch(() => "")).slice(0, 80)}` : ""}` : "no POST observed";
@@ -2222,4 +2260,4 @@ export {
2222
2260
  runAudits,
2223
2261
  runAuditsAcross
2224
2262
  };
2225
- //# sourceMappingURL=chunk-3U3IGVAQ.js.map
2263
+ //# sourceMappingURL=chunk-3LWKIKZ2.js.map