@reddoorla/maintenance 0.68.0 → 0.71.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.
- package/dist/airtable-2PJ4NSAV.js +9 -0
- package/dist/{announce-72R3LRNT.js → announce-3JE5FKW7.js} +6 -6
- package/dist/blux-FKZYMKLF.js +2205 -0
- package/dist/blux-FKZYMKLF.js.map +1 -0
- package/dist/{bump-deps-QNM3H4GI.js → bump-deps-K3JMLMBB.js} +3 -2
- package/dist/bump-deps-K3JMLMBB.js.map +1 -0
- package/dist/{chunk-RINXPU3H.js → chunk-2PWQ6MPG.js} +2 -2
- package/dist/{chunk-H6YZBXBQ.js → chunk-52TDNN7K.js} +37 -15
- package/dist/chunk-52TDNN7K.js.map +1 -0
- package/dist/{chunk-XWPZ46IN.js → chunk-5QC5KJHR.js} +2 -2
- package/dist/{chunk-O6G4HHMF.js → chunk-6J25IIAI.js} +162 -42
- package/dist/chunk-6J25IIAI.js.map +1 -0
- package/dist/chunk-7MJBTV2R.js +145 -0
- package/dist/chunk-7MJBTV2R.js.map +1 -0
- package/dist/{chunk-6JFOAPW4.js → chunk-AYM2EFSK.js} +38 -6
- package/dist/chunk-AYM2EFSK.js.map +1 -0
- package/dist/{chunk-GKSXZIMX.js → chunk-CMQMNFFJ.js} +77 -3
- package/dist/chunk-CMQMNFFJ.js.map +1 -0
- package/dist/{chunk-6MT5W6UF.js → chunk-F6OE6MGQ.js} +6 -3
- package/dist/chunk-F6OE6MGQ.js.map +1 -0
- package/dist/{chunk-OTBA7DON.js → chunk-J2SHWT2O.js} +1 -1
- package/dist/chunk-J2SHWT2O.js.map +1 -0
- package/dist/{chunk-XVR7UM6Z.js → chunk-JNXCDUYB.js} +4 -4
- package/dist/{chunk-2E2X5BCG.js → chunk-KOAGMTRI.js} +3 -3
- package/dist/chunk-KRDLHAKK.js +17 -0
- package/dist/chunk-KRDLHAKK.js.map +1 -0
- package/dist/{chunk-LYCKN7ZR.js → chunk-LPMQXS2N.js} +8 -4
- package/dist/chunk-LPMQXS2N.js.map +1 -0
- package/dist/{chunk-WCN54744.js → chunk-M7HOQ4W7.js} +388 -8
- package/dist/chunk-M7HOQ4W7.js.map +1 -0
- package/dist/{chunk-LCKKIJ22.js → chunk-MPRLMGJU.js} +11 -3
- package/dist/chunk-MPRLMGJU.js.map +1 -0
- package/dist/chunk-PKVZMFEB.js +315 -0
- package/dist/chunk-PKVZMFEB.js.map +1 -0
- package/dist/{chunk-A5KYRGQA.js → chunk-PSJQE6T6.js} +4 -4
- package/dist/chunk-SL24DCGC.js +41 -0
- package/dist/chunk-SL24DCGC.js.map +1 -0
- package/dist/{chunk-MAYHLXCS.js → chunk-VR246V3G.js} +25 -5
- package/dist/chunk-VR246V3G.js.map +1 -0
- package/dist/{chunk-45AUGDFR.js → chunk-WN4NEHE7.js} +2 -7
- package/dist/chunk-WN4NEHE7.js.map +1 -0
- package/dist/{chunk-YQMYQAJX.js → chunk-Y7LZHPDF.js} +2 -2
- package/dist/{chunk-C3PDS623.js → chunk-YWRQEDB3.js} +53 -3
- package/dist/chunk-YWRQEDB3.js.map +1 -0
- package/dist/cli/bin.js +63 -19
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/commands/audit.d.ts +1 -1
- package/dist/cli/commands/audit.js +13 -11
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/client/index.d.ts +84 -0
- package/dist/client/index.js +47 -0
- package/dist/client/index.js.map +1 -0
- package/dist/configs/playwright-a11y.js +1 -1
- package/dist/{convert-to-pnpm-XH7NYRVK.js → convert-to-pnpm-6F4RAFEJ.js} +3 -2
- package/dist/convert-to-pnpm-6F4RAFEJ.js.map +1 -0
- package/dist/{digest-J7TDG62Q.js → digest-GZCZYJKC.js} +11 -11
- package/dist/{ensure-site-2PF522VL.js → ensure-site-H5VMBPLF.js} +2 -2
- package/dist/forms/index.d.ts +2 -0
- package/dist/forms/index.js +7 -1
- package/dist/forms/index.js.map +1 -1
- package/dist/{github-signals-PP7GWYIY.js → github-signals-SQECQNST.js} +8 -8
- package/dist/health-endpoint-QXWM6GW2.js +54 -0
- package/dist/health-endpoint-QXWM6GW2.js.map +1 -0
- package/dist/index.d.ts +132 -17
- package/dist/index.js +213 -70
- package/dist/index.js.map +1 -1
- package/dist/{init-WLR35YGN.js → init-KQOIPLVT.js} +12 -8
- package/dist/init-KQOIPLVT.js.map +1 -0
- package/dist/{launch-2HPQXWII.js → launch-RX4VI7F2.js} +13 -13
- package/dist/{lighthouse-airtable-UBSXKHAQ.js → lighthouse-airtable-TTXULEGU.js} +3 -3
- package/dist/{onboard-X6KJ5Z2V.js → onboard-TFBL62J3.js} +2 -2
- package/dist/{orchestrate-PVCGBH4K.js → orchestrate-DYA4XAQJ.js} +6 -6
- package/dist/{preflight-KWVYJ2DU.js → preflight-S3GYME3Q.js} +8 -8
- package/dist/probe-DJAMLVTT.js +46 -0
- package/dist/probe-DJAMLVTT.js.map +1 -0
- package/dist/recipes/sync-configs.d.ts +1 -1
- package/dist/recipes/sync-configs.js +2 -2
- package/dist/{renovate-dispatch-LG4RJGDY.js → renovate-dispatch-MZPAWVBL.js} +2 -2
- package/dist/{report-ZBFMTT76.js → report-BLZ67QAQ.js} +12 -12
- package/dist/run-migration-LJNNZWIV.js +205 -0
- package/dist/run-migration-LJNNZWIV.js.map +1 -0
- package/dist/{self-updating-JTTFOJ7Q.js → self-updating-GSH427XP.js} +2 -2
- package/dist/{selftest-LFZPZRJP.js → selftest-KPTL6KC4.js} +11 -11
- package/dist/smoke-suite-GP3W57JP.js +54 -0
- package/dist/smoke-suite-GP3W57JP.js.map +1 -0
- package/dist/{svelte-codemods-KJLNH6FQ.js → svelte-codemods-GYZZX742.js} +3 -2
- package/dist/svelte-codemods-GYZZX742.js.map +1 -0
- package/dist/{sync-configs-6GBZLGRQ.js → sync-configs-CQNOTJ2B.js} +5 -4
- package/dist/sync-configs-CQNOTJ2B.js.map +1 -0
- package/dist/{types-Dg4mHvyf.d.ts → types-0jreMCF5.d.ts} +2 -2
- package/dist/{upgrade-TPTE26FG.js → upgrade-RTAJZD56.js} +3 -2
- package/dist/upgrade-RTAJZD56.js.map +1 -0
- package/dist/{websites-6YTT5ZTO.js → websites-SVI4KYSH.js} +8 -2
- package/dist/{write-audits-to-airtable-IWOO4FFH.js → write-audits-to-airtable-3XFNWMUE.js} +4 -4
- package/package.json +8 -1
- package/dist/airtable-WGQQ3KAD.js +0 -9
- package/dist/bump-deps-QNM3H4GI.js.map +0 -1
- package/dist/chunk-45AUGDFR.js.map +0 -1
- package/dist/chunk-6JFOAPW4.js.map +0 -1
- package/dist/chunk-6MT5W6UF.js.map +0 -1
- package/dist/chunk-C3PDS623.js.map +0 -1
- package/dist/chunk-GKSXZIMX.js.map +0 -1
- package/dist/chunk-H6YZBXBQ.js.map +0 -1
- package/dist/chunk-LCKKIJ22.js.map +0 -1
- package/dist/chunk-LYCKN7ZR.js.map +0 -1
- package/dist/chunk-MAYHLXCS.js.map +0 -1
- package/dist/chunk-O6G4HHMF.js.map +0 -1
- package/dist/chunk-OTBA7DON.js.map +0 -1
- package/dist/chunk-WCN54744.js.map +0 -1
- package/dist/convert-to-pnpm-XH7NYRVK.js.map +0 -1
- package/dist/init-WLR35YGN.js.map +0 -1
- package/dist/svelte-codemods-KJLNH6FQ.js.map +0 -1
- package/dist/sync-configs-6GBZLGRQ.js.map +0 -1
- package/dist/upgrade-TPTE26FG.js.map +0 -1
- /package/dist/{airtable-WGQQ3KAD.js.map → airtable-2PJ4NSAV.js.map} +0 -0
- /package/dist/{announce-72R3LRNT.js.map → announce-3JE5FKW7.js.map} +0 -0
- /package/dist/{chunk-RINXPU3H.js.map → chunk-2PWQ6MPG.js.map} +0 -0
- /package/dist/{chunk-XWPZ46IN.js.map → chunk-5QC5KJHR.js.map} +0 -0
- /package/dist/{chunk-XVR7UM6Z.js.map → chunk-JNXCDUYB.js.map} +0 -0
- /package/dist/{chunk-2E2X5BCG.js.map → chunk-KOAGMTRI.js.map} +0 -0
- /package/dist/{chunk-A5KYRGQA.js.map → chunk-PSJQE6T6.js.map} +0 -0
- /package/dist/{chunk-YQMYQAJX.js.map → chunk-Y7LZHPDF.js.map} +0 -0
- /package/dist/{digest-J7TDG62Q.js.map → digest-GZCZYJKC.js.map} +0 -0
- /package/dist/{ensure-site-2PF522VL.js.map → ensure-site-H5VMBPLF.js.map} +0 -0
- /package/dist/{github-signals-PP7GWYIY.js.map → github-signals-SQECQNST.js.map} +0 -0
- /package/dist/{launch-2HPQXWII.js.map → launch-RX4VI7F2.js.map} +0 -0
- /package/dist/{lighthouse-airtable-UBSXKHAQ.js.map → lighthouse-airtable-TTXULEGU.js.map} +0 -0
- /package/dist/{onboard-X6KJ5Z2V.js.map → onboard-TFBL62J3.js.map} +0 -0
- /package/dist/{orchestrate-PVCGBH4K.js.map → orchestrate-DYA4XAQJ.js.map} +0 -0
- /package/dist/{preflight-KWVYJ2DU.js.map → preflight-S3GYME3Q.js.map} +0 -0
- /package/dist/{renovate-dispatch-LG4RJGDY.js.map → renovate-dispatch-MZPAWVBL.js.map} +0 -0
- /package/dist/{report-ZBFMTT76.js.map → report-BLZ67QAQ.js.map} +0 -0
- /package/dist/{self-updating-JTTFOJ7Q.js.map → self-updating-GSH427XP.js.map} +0 -0
- /package/dist/{selftest-LFZPZRJP.js.map → selftest-KPTL6KC4.js.map} +0 -0
- /package/dist/{websites-6YTT5ZTO.js.map → websites-SVI4KYSH.js.map} +0 -0
- /package/dist/{write-audits-to-airtable-IWOO4FFH.js.map → write-audits-to-airtable-3XFNWMUE.js.map} +0 -0
|
@@ -3,26 +3,26 @@ import {
|
|
|
3
3
|
} from "./chunk-PZQ3WED2.js";
|
|
4
4
|
import {
|
|
5
5
|
formatFleetWriteSummary
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-CMQMNFFJ.js";
|
|
7
|
+
import "./chunk-5QC5KJHR.js";
|
|
8
8
|
import {
|
|
9
9
|
detectSignalEvents,
|
|
10
10
|
fleetSweptEvent
|
|
11
11
|
} from "./chunk-5L3FPQIJ.js";
|
|
12
|
+
import {
|
|
13
|
+
makeGitHub
|
|
14
|
+
} from "./chunk-YEGHUODU.js";
|
|
12
15
|
import {
|
|
13
16
|
recordFleetEventsBestEffort
|
|
14
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-J2SHWT2O.js";
|
|
15
18
|
import "./chunk-PH3AGF4Z.js";
|
|
16
19
|
import "./chunk-HIN3P4ZN.js";
|
|
17
|
-
import {
|
|
18
|
-
makeGitHub
|
|
19
|
-
} from "./chunk-YEGHUODU.js";
|
|
20
20
|
import "./chunk-HVOOCK6L.js";
|
|
21
21
|
import {
|
|
22
22
|
listWebsites,
|
|
23
23
|
siteSlug,
|
|
24
24
|
updateGitHubSignals
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-YWRQEDB3.js";
|
|
26
26
|
import {
|
|
27
27
|
openBase,
|
|
28
28
|
readAirtableConfig
|
|
@@ -134,4 +134,4 @@ export {
|
|
|
134
134
|
githubSignalsExitCode,
|
|
135
135
|
runGitHubSignalsCommand
|
|
136
136
|
};
|
|
137
|
-
//# sourceMappingURL=github-signals-
|
|
137
|
+
//# sourceMappingURL=github-signals-SQECQNST.js.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {
|
|
2
|
+
runRecipeOverSites
|
|
3
|
+
} from "./chunk-VPJ7N6P7.js";
|
|
4
|
+
import {
|
|
5
|
+
appendSkipNotice,
|
|
6
|
+
fleetWorkdir,
|
|
7
|
+
prepareFleetSites
|
|
8
|
+
} from "./chunk-4NAOR44V.js";
|
|
9
|
+
import {
|
|
10
|
+
resolveSites
|
|
11
|
+
} from "./chunk-Y7LZHPDF.js";
|
|
12
|
+
import {
|
|
13
|
+
healthEndpoint
|
|
14
|
+
} from "./chunk-7MJBTV2R.js";
|
|
15
|
+
import "./chunk-KRDLHAKK.js";
|
|
16
|
+
import "./chunk-XKOZUVK2.js";
|
|
17
|
+
import "./chunk-FDIFTIXC.js";
|
|
18
|
+
import "./chunk-HVOOCK6L.js";
|
|
19
|
+
import "./chunk-XXTZBPUY.js";
|
|
20
|
+
import "./chunk-XTK5VIQB.js";
|
|
21
|
+
import "./chunk-U5SZ4FOP.js";
|
|
22
|
+
|
|
23
|
+
// src/cli/commands/health-endpoint.ts
|
|
24
|
+
import { resolve } from "path";
|
|
25
|
+
function formatResult(r) {
|
|
26
|
+
if (r.status === "noop") return `[${r.site}] noop: ${r.notes ?? ""}`;
|
|
27
|
+
if (r.status === "failed") return `[${r.site}] failed: ${r.notes ?? ""}`;
|
|
28
|
+
return `[${r.site}] applied: ${r.commits.length} commit(s)
|
|
29
|
+
${r.notes ?? ""}`;
|
|
30
|
+
}
|
|
31
|
+
async function runHealthEndpointCommand(site, opts) {
|
|
32
|
+
const cwd = opts.cwd ? resolve(opts.cwd) : process.cwd();
|
|
33
|
+
let sites = await resolveSites({
|
|
34
|
+
...site !== void 0 ? { site } : {},
|
|
35
|
+
...opts.fleet !== void 0 ? { fleet: opts.fleet } : {},
|
|
36
|
+
...opts.workdir !== void 0 ? { workdir: opts.workdir } : {},
|
|
37
|
+
cwd
|
|
38
|
+
});
|
|
39
|
+
let skipped = [];
|
|
40
|
+
if (opts.fleet) {
|
|
41
|
+
const workdir = opts.workdir ?? fleetWorkdir();
|
|
42
|
+
const prep = await prepareFleetSites(sites, { workdir });
|
|
43
|
+
sites = prep.prepared;
|
|
44
|
+
skipped = prep.skipped;
|
|
45
|
+
}
|
|
46
|
+
const results = await runRecipeOverSites("health-endpoint", sites, (s) => healthEndpoint(s));
|
|
47
|
+
const output = results.map(formatResult).join("\n");
|
|
48
|
+
const code = results.some((r) => r.status === "failed") ? 1 : 0;
|
|
49
|
+
return { output: appendSkipNotice(output, skipped), code };
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
runHealthEndpointCommand
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=health-endpoint-QXWM6GW2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/commands/health-endpoint.ts"],"sourcesContent":["import { resolve } from \"node:path\";\nimport { healthEndpoint } from \"../../recipes/health-endpoint/index.js\";\nimport type { RecipeResult } from \"../../types.js\";\nimport { resolveSites } from \"../fleet/resolve-sites.js\";\nimport { prepareFleetSites, appendSkipNotice, type SkippedSite } from \"../fleet/prepare-sites.js\";\nimport { runRecipeOverSites } from \"../fleet/run-recipe-over-sites.js\";\nimport { fleetWorkdir } from \"../../util/fleet-workdir.js\";\n\nexport type HealthEndpointCommandOptions = {\n fleet?: string;\n workdir?: string;\n cwd?: string;\n};\n\nfunction formatResult(r: RecipeResult): string {\n if (r.status === \"noop\") return `[${r.site}] noop: ${r.notes ?? \"\"}`;\n if (r.status === \"failed\") return `[${r.site}] failed: ${r.notes ?? \"\"}`;\n return `[${r.site}] applied: ${r.commits.length} commit(s)\\n${r.notes ?? \"\"}`;\n}\n\nexport async function runHealthEndpointCommand(\n site: string | undefined,\n opts: HealthEndpointCommandOptions,\n): Promise<{ output: string; code: number }> {\n const cwd = opts.cwd ? resolve(opts.cwd) : process.cwd();\n\n let sites = await resolveSites({\n ...(site !== undefined ? { site } : {}),\n ...(opts.fleet !== undefined ? { fleet: opts.fleet } : {}),\n ...(opts.workdir !== undefined ? { workdir: opts.workdir } : {}),\n cwd,\n });\n\n let skipped: SkippedSite[] = [];\n if (opts.fleet) {\n const workdir = opts.workdir ?? fleetWorkdir();\n const prep = await prepareFleetSites(sites, { workdir });\n sites = prep.prepared;\n skipped = prep.skipped;\n }\n\n const results = await runRecipeOverSites(\"health-endpoint\", sites, (s) => healthEndpoint(s));\n\n const output = results.map(formatResult).join(\"\\n\");\n const code = results.some((r) => r.status === \"failed\") ? 1 : 0;\n return { output: appendSkipNotice(output, skipped), code };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,eAAe;AAcxB,SAAS,aAAa,GAAyB;AAC7C,MAAI,EAAE,WAAW,OAAQ,QAAO,IAAI,EAAE,IAAI,WAAW,EAAE,SAAS,EAAE;AAClE,MAAI,EAAE,WAAW,SAAU,QAAO,IAAI,EAAE,IAAI,aAAa,EAAE,SAAS,EAAE;AACtE,SAAO,IAAI,EAAE,IAAI,cAAc,EAAE,QAAQ,MAAM;AAAA,EAAe,EAAE,SAAS,EAAE;AAC7E;AAEA,eAAsB,yBACpB,MACA,MAC2C;AAC3C,QAAM,MAAM,KAAK,MAAM,QAAQ,KAAK,GAAG,IAAI,QAAQ,IAAI;AAEvD,MAAI,QAAQ,MAAM,aAAa;AAAA,IAC7B,GAAI,SAAS,SAAY,EAAE,KAAK,IAAI,CAAC;AAAA,IACrC,GAAI,KAAK,UAAU,SAAY,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,IACxD,GAAI,KAAK,YAAY,SAAY,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,IAC9D;AAAA,EACF,CAAC;AAED,MAAI,UAAyB,CAAC;AAC9B,MAAI,KAAK,OAAO;AACd,UAAM,UAAU,KAAK,WAAW,aAAa;AAC7C,UAAM,OAAO,MAAM,kBAAkB,OAAO,EAAE,QAAQ,CAAC;AACvD,YAAQ,KAAK;AACb,cAAU,KAAK;AAAA,EACjB;AAEA,QAAM,UAAU,MAAM,mBAAmB,mBAAmB,OAAO,CAAC,MAAM,eAAe,CAAC,CAAC;AAE3F,QAAM,SAAS,QAAQ,IAAI,YAAY,EAAE,KAAK,IAAI;AAClD,QAAM,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,WAAW,QAAQ,IAAI,IAAI;AAC9D,SAAO,EAAE,QAAQ,iBAAiB,QAAQ,OAAO,GAAG,KAAK;AAC3D;","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as AuditResult, S as Site, A as AuditName, b as RecipeResult, R as RecipeName, I as InventoryProvider } from './types-
|
|
2
|
-
export { C as ConfigName } from './types-
|
|
1
|
+
import { a as AuditResult, S as Site, A as AuditName, b as RecipeResult, R as RecipeName, I as InventoryProvider } from './types-0jreMCF5.js';
|
|
2
|
+
export { C as ConfigName } from './types-0jreMCF5.js';
|
|
3
3
|
import * as airtable_lib_airtable_base_js from 'airtable/lib/airtable_base.js';
|
|
4
4
|
import { F as FormType } from './types-RXY-vY-5.js';
|
|
5
5
|
export { SyncConfigsOptions, syncConfigs } from './recipes/sync-configs.js';
|
|
@@ -41,7 +41,9 @@ type DiscoverDeps = {
|
|
|
41
41
|
fetchText: (url: string) => Promise<string | null>;
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
-
/** One route probed across desktop engines + mobile devices, plus the internal links found on it
|
|
44
|
+
/** One route probed across desktop engines + mobile devices, plus the internal links found on it,
|
|
45
|
+
* plus the chromium-derived reachability + SEO signals (captured on the page chromium already
|
|
46
|
+
* opened — no extra navigation). */
|
|
45
47
|
type RouteResult = {
|
|
46
48
|
url: string;
|
|
47
49
|
/** Per desktop engine (chromium/firefox/webkit): loaded with no JS error + a visible main landmark. */
|
|
@@ -56,6 +58,12 @@ type RouteResult = {
|
|
|
56
58
|
}>;
|
|
57
59
|
/** Same-origin links discovered on the page (absolute URLs), for the Links check. */
|
|
58
60
|
links: string[];
|
|
61
|
+
/** HTTP status of the chromium navigation (2xx/3xx = reachable). null = the nav failed/threw. */
|
|
62
|
+
status: number | null;
|
|
63
|
+
/** The chromium `<title>` (trimmed by the reducer), or null when not captured. */
|
|
64
|
+
title: string | null;
|
|
65
|
+
/** The chromium `meta[name="description"]` content, or null when absent/not captured. */
|
|
66
|
+
metaDescription: string | null;
|
|
59
67
|
};
|
|
60
68
|
type LinkResult = {
|
|
61
69
|
url: string;
|
|
@@ -68,6 +76,29 @@ type BrowserRunner = {
|
|
|
68
76
|
close?: () => Promise<void>;
|
|
69
77
|
};
|
|
70
78
|
|
|
79
|
+
/** Outcome of driving one site's contact form. `formPresent:false` ⇒ n/a
|
|
80
|
+
* (persisted). `testModeUndeclared` ⇒ the site's /health does not declare
|
|
81
|
+
* `forms.testMode`, so the probe refused to submit — a plain skip, prior
|
|
82
|
+
* verdict preserved. */
|
|
83
|
+
type FormSubmitOutcome = {
|
|
84
|
+
formPresent: false;
|
|
85
|
+
} | {
|
|
86
|
+
formPresent: true;
|
|
87
|
+
success: boolean;
|
|
88
|
+
detail?: string;
|
|
89
|
+
} | {
|
|
90
|
+
testModeUndeclared: true;
|
|
91
|
+
};
|
|
92
|
+
/** Injected browser IO. The real impl drives Playwright; tests pass a fake. */
|
|
93
|
+
type FormRunner = {
|
|
94
|
+
submit: (opts: {
|
|
95
|
+
baseUrl: string;
|
|
96
|
+
testMode: boolean;
|
|
97
|
+
testSitekey: string;
|
|
98
|
+
}) => Promise<FormSubmitOutcome>;
|
|
99
|
+
close?: () => Promise<void>;
|
|
100
|
+
};
|
|
101
|
+
|
|
71
102
|
/** Result of probing a site's latest PRODUCTION Netlify deploy. Every field is
|
|
72
103
|
* nullable: a site with no production deploy yet degrades to all-nulls (a real
|
|
73
104
|
* "none" verdict). A read FAILURE is NOT represented here — it surfaces as
|
|
@@ -109,6 +140,38 @@ type NetlifyDeployDeps = {
|
|
|
109
140
|
now: Date;
|
|
110
141
|
};
|
|
111
142
|
|
|
143
|
+
/** The parts of the deployed `/health` body this audit reads. `ok` is the endpoint's self-rollup
|
|
144
|
+
* (`functionRan && prismic !== "error"`); `prismic` is the server-side CMS probe status; `forms`
|
|
145
|
+
* are booleans recorded for the dashboard only. A public endpoint can return anything, so every
|
|
146
|
+
* field is validated/coerced by `parseHealthBody`. */
|
|
147
|
+
type HealthBody = {
|
|
148
|
+
ok: boolean;
|
|
149
|
+
prismic: "ok" | "error" | "skipped" | null;
|
|
150
|
+
forms: {
|
|
151
|
+
ingestUrl: boolean;
|
|
152
|
+
ingestToken: boolean;
|
|
153
|
+
turnstile: boolean;
|
|
154
|
+
} | null;
|
|
155
|
+
};
|
|
156
|
+
/** Outcome of fetching `{deployedUrl}/health`, distinguishing "no usable report" (`present:false`
|
|
157
|
+
* → self-skip, the writer preserves the prior verdict) from "read a body" (`present:true`
|
|
158
|
+
* → a real pass/fail). `present:true` with a real `HealthBody` is a 200 JSON response (`ok`
|
|
159
|
+
* drives pass/fail); the fetch layer also synthesizes an all-`ok:false` body for "deployed but
|
|
160
|
+
* erroring" responses (a non-404 non-2xx, or a 200 that isn't valid JSON) so those fail loudly
|
|
161
|
+
* instead of silently skipping. Mirrors `netlify-deploy`'s `NetlifyDeployFetch` read/no-read split. */
|
|
162
|
+
type HealthFetch = {
|
|
163
|
+
present: false;
|
|
164
|
+
} | {
|
|
165
|
+
present: true;
|
|
166
|
+
body: HealthBody;
|
|
167
|
+
};
|
|
168
|
+
/** Injected IO so the audit is unit-testable without a network. `fetchHealth` returns a
|
|
169
|
+
* `HealthFetch`; `now` is the clock for the checked-at stamp. */
|
|
170
|
+
type FunctionHealthDeps = {
|
|
171
|
+
fetchHealth: (deployedUrl: string) => Promise<HealthFetch>;
|
|
172
|
+
now: Date;
|
|
173
|
+
};
|
|
174
|
+
|
|
112
175
|
/** One GitHub Dependabot alert, mapped to the fields the security audit needs. */
|
|
113
176
|
type DependabotAlert = {
|
|
114
177
|
/** The vulnerable package name (`dependency.package.name`). */
|
|
@@ -147,8 +210,12 @@ type AuditContext = {
|
|
|
147
210
|
discoverDeps?: DiscoverDeps;
|
|
148
211
|
/** Playwright runner injection for the browser audit (tests). Defaults to real Playwright. */
|
|
149
212
|
browserRunner?: BrowserRunner;
|
|
213
|
+
/** Playwright runner injection for the form-e2e audit (tests). Defaults to real Playwright. */
|
|
214
|
+
formRunner?: FormRunner;
|
|
150
215
|
/** Netlify API injection for the netlify-deploy audit (tests). Defaults to a real API call. */
|
|
151
216
|
netlifyDeployDeps?: NetlifyDeployDeps;
|
|
217
|
+
/** `/health` fetch injection for the function-health audit (tests). Defaults to a real GET. */
|
|
218
|
+
functionHealthDeps?: FunctionHealthDeps;
|
|
152
219
|
/** GitHub Dependabot fetch injection for the security audit (tests). Defaults to a real client
|
|
153
220
|
* from GITHUB_TOKEN; absent token or no site.gitRepo → the pnpm/npm audit fallback. */
|
|
154
221
|
dependabotDeps?: DependabotDeps;
|
|
@@ -250,10 +317,11 @@ type InitOptions = {
|
|
|
250
317
|
steps?: InitStep[];
|
|
251
318
|
};
|
|
252
319
|
/** convert-to-pnpm → onboard → sync-configs → svelte-codemods →
|
|
253
|
-
* a11y-fixtures-page → audit. Order is
|
|
254
|
-
* the prior one's output (pnpm before
|
|
255
|
-
* before sync-configs writes lighthouserc,
|
|
256
|
-
* actually has a route to hit
|
|
320
|
+
* a11y-fixtures-page → health-endpoint → smoke-suite → audit. Order is
|
|
321
|
+
* deliberate — every step depends on the prior one's output (pnpm before
|
|
322
|
+
* onboard's installs, onboard's deps before sync-configs writes lighthouserc,
|
|
323
|
+
* fixtures page before audit actually has a route to hit; smoke-suite's
|
|
324
|
+
* `pnpm install` lands before the closing audit). */
|
|
257
325
|
declare const DEFAULT_INIT_STEPS: InitStep[];
|
|
258
326
|
/**
|
|
259
327
|
* One-shot guided onboarding. Runs the default step sequence against a
|
|
@@ -296,11 +364,15 @@ type AirtableInventoryOptions = {
|
|
|
296
364
|
/**
|
|
297
365
|
* Read sites from the Airtable Websites table as an InventoryProvider.
|
|
298
366
|
* Each row becomes one Site; `path` is computed as `{workdir}/{slug}`.
|
|
299
|
-
* Only `maintenance`
|
|
300
|
-
* (
|
|
301
|
-
*
|
|
302
|
-
*
|
|
303
|
-
*
|
|
367
|
+
* Only LIVE `maintenance` sites that have a `url` are included — pre-launch
|
|
368
|
+
* stages ("launch period" / "in development", via isPreLaunch) are excluded so a
|
|
369
|
+
* not-yet-live site is never audited as production (its deploy/domain/uptime/CMS
|
|
370
|
+
* audits would fail against nothing and red its Airtable row) nor swept by other
|
|
371
|
+
* `--fleet airtable` ops; it re-enters the fleet when a Launch report flips its
|
|
372
|
+
* Status to "maintenance". The production URL is exposed as `Site.deployedUrl` so
|
|
373
|
+
* the lighthouse audit can run against it with no checkout. `repoUrl` is
|
|
374
|
+
* intentionally NOT set from `url` — a clone source must come from `gitRepo`
|
|
375
|
+
* (`owner/repo`), never the production URL.
|
|
304
376
|
*/
|
|
305
377
|
declare function fromAirtableBase(base: AirtableBase, opts?: AirtableInventoryOptions): InventoryProvider;
|
|
306
378
|
|
|
@@ -418,6 +490,22 @@ type WebsiteRow = {
|
|
|
418
490
|
deployStatus: string | null;
|
|
419
491
|
lastDeployAt: string | null;
|
|
420
492
|
deployLogUrl: string | null;
|
|
493
|
+
/** When the `netlify-deploy` audit last RAN (freshness stamp for `deployStatus`). The audit
|
|
494
|
+
* already writes "Deploy checked at"; this read-back is the Plan-2 fix so `deployEvidence`
|
|
495
|
+
* (Plan 4) can gate on check time — NOT on `lastDeployAt`, which is deploy time, not check time. */
|
|
496
|
+
deployCheckedAt: string | null;
|
|
497
|
+
/** Function-health verdict (the `function-health` audit): the deployed `/health` function
|
|
498
|
+
* answered `ok:true` (pass) or `ok:false` (fail). Single-select `pass`/`fail`; null = never ran
|
|
499
|
+
* / unreachable (→ Plan 4 maps to unknown/amber). Kept SEPARATE from `deployStatus` so
|
|
500
|
+
* `isFailedDeployStatus` keeps meaning "the build failed". */
|
|
501
|
+
functionHealth: "pass" | "fail" | null;
|
|
502
|
+
/** CMS reachability (server-side), derived from the same `/health` body's `details.prismic ===
|
|
503
|
+
* "ok"`. Single-select `pass`/`fail`; null = never ran. No per-site Prismic token or identity
|
|
504
|
+
* column is ever built — this rides `/health`. */
|
|
505
|
+
cmsReachable: "pass" | "fail" | null;
|
|
506
|
+
/** When the `function-health` audit last ran — the freshness gate for BOTH `functionHealth` and
|
|
507
|
+
* `cmsReachable`. Null = never ran. */
|
|
508
|
+
functionHealthCheckedAt: string | null;
|
|
421
509
|
/** Deployed-URL browser probe (the `browser` audit): cross-engine render OK, mobile render OK,
|
|
422
510
|
* internal-links OK + broken count, and when it last ran (one timestamp gates all three). */
|
|
423
511
|
crossbrowserOk: boolean | null;
|
|
@@ -425,6 +513,13 @@ type WebsiteRow = {
|
|
|
425
513
|
linksOk: boolean | null;
|
|
426
514
|
brokenLinks: number | null;
|
|
427
515
|
browserCheckedAt: string | null;
|
|
516
|
+
/** Uptime-reachable verdict (browser audit): every sampled route returned 2xx/3xx. Single-select
|
|
517
|
+
* `pass`/`fail`; null = never ran. Point-in-time. Freshness-gated by `browserCheckedAt`. */
|
|
518
|
+
reachableOk: "pass" | "fail" | null;
|
|
519
|
+
/** Titles & meta verdict (browser audit, chromium): every sampled route has a non-empty `<title>`
|
|
520
|
+
* ≤ 70 chars + a non-empty meta description, and no duplicate titles across the sample.
|
|
521
|
+
* Single-select `pass`/`fail`; null = never ran. Freshness-gated by `browserCheckedAt`. */
|
|
522
|
+
titleMetaOk: "pass" | "fail" | null;
|
|
428
523
|
/** Per-site copy overrides (M6a). Blank → null → the DEFAULT_COPY value. */
|
|
429
524
|
copyIntro: string | null;
|
|
430
525
|
copyContact: string | null;
|
|
@@ -447,6 +542,16 @@ type WebsiteRow = {
|
|
|
447
542
|
defaultBranchCi: string | null;
|
|
448
543
|
lastCommitAt: string | null;
|
|
449
544
|
githubSignalsAt: string | null;
|
|
545
|
+
/** Per-site smoke-suite verdict (the `smoke` audit runs `pnpm test:smoke`).
|
|
546
|
+
* Single-select pass/fail; null = never ran. `lastSmokeAt` gates freshness. */
|
|
547
|
+
smokeOk: "pass" | "fail" | null;
|
|
548
|
+
lastSmokeAt: string | null;
|
|
549
|
+
/** Synthetic form end-to-end verdict (the `form-e2e` audit submits the real prod
|
|
550
|
+
* contact form in test-mode). Single-select pass/fail; null = never ran OR (with
|
|
551
|
+
* a fresh `formE2eCheckedAt`) no contact form → n/a. `formE2eCheckedAt` gates
|
|
552
|
+
* freshness AND encodes the n/a-vs-never-ran distinction. */
|
|
553
|
+
formE2eOk: "pass" | "fail" | null;
|
|
554
|
+
formE2eCheckedAt: string | null;
|
|
450
555
|
notifyRouting: NotifyRouting | null;
|
|
451
556
|
};
|
|
452
557
|
type Severity = "low" | "moderate" | "high" | "critical";
|
|
@@ -559,7 +664,7 @@ type ReportData = {
|
|
|
559
664
|
};
|
|
560
665
|
|
|
561
666
|
/** A single auto-check outcome. `pass` + fresh ⇒ the caller ticks the box. */
|
|
562
|
-
type EvidenceResult = "pass" | "fail" | "unknown";
|
|
667
|
+
type EvidenceResult = "pass" | "fail" | "unknown" | "n/a";
|
|
563
668
|
type EvidenceRecord = {
|
|
564
669
|
result: EvidenceResult;
|
|
565
670
|
checkedAt: string | null;
|
|
@@ -602,9 +707,17 @@ type ReportRow = {
|
|
|
602
707
|
* subset (see src/reports/checklist.ts). */
|
|
603
708
|
checklist: Record<string, boolean>;
|
|
604
709
|
/** Snapshot of the auto-tick evidence at draft time, keyed by checklist field → evidence
|
|
605
|
-
* record. Null when the report predates auto-tick or carried no auto-checked items.
|
|
606
|
-
*
|
|
710
|
+
* record. Null when the report predates auto-tick or carried no auto-checked items. This is the
|
|
711
|
+
* health gate's source of truth: `isHealthGateClear`/`gatingHealth` (src/reports/checklist.ts)
|
|
712
|
+
* read these evidence records, NOT the checklist booleans — and also drive the dashboard badges. */
|
|
607
713
|
autoEvidence: Record<string, EvidenceRecord> | null;
|
|
714
|
+
/** Logged send-anyway override (Phase 10). When `sendOverride` is true AND `overrideReason` is
|
|
715
|
+
* non-empty, the health gate is bypassed for THIS report; `overrideBy`/`overrideAt` are the
|
|
716
|
+
* audit trail (parallel to approvedBy/approvedAt). Missing cells read false/null. */
|
|
717
|
+
sendOverride: boolean;
|
|
718
|
+
overrideReason: string | null;
|
|
719
|
+
overrideBy: string | null;
|
|
720
|
+
overrideAt: string | null;
|
|
608
721
|
};
|
|
609
722
|
|
|
610
723
|
type DraftOptions = {
|
|
@@ -833,9 +946,9 @@ type AttentionItem = {
|
|
|
833
946
|
autoFixExhausted?: boolean;
|
|
834
947
|
};
|
|
835
948
|
|
|
836
|
-
type FleetEventType = "pr_automerged" | "vuln_cleared" | "ci_recovered" | "site_launched" | "fleet_swept" | "cert_renewed";
|
|
949
|
+
type FleetEventType = "pr_automerged" | "vuln_cleared" | "ci_recovered" | "site_launched" | "fleet_swept" | "cert_renewed" | "report_sent_with_override";
|
|
837
950
|
|
|
838
|
-
type Tier = "attention" | "watch" | "healthy";
|
|
951
|
+
type Tier = "attention" | "watch" | "healthy" | "pre-launch";
|
|
839
952
|
type SiteCard = {
|
|
840
953
|
site: WebsiteRow;
|
|
841
954
|
tier: Tier;
|
|
@@ -871,6 +984,8 @@ type CockpitSummary = {
|
|
|
871
984
|
attention: number;
|
|
872
985
|
watch: number;
|
|
873
986
|
healthy: number;
|
|
987
|
+
/** Count of pre-live "launch period" sites — muted, never counted as broken. */
|
|
988
|
+
preLaunch: number;
|
|
874
989
|
criticalHighVulns: number;
|
|
875
990
|
lighthouseBelowFloor: number;
|
|
876
991
|
deliveryFailures: number;
|