@reddoorla/maintenance 0.47.0 → 0.50.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/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as Site, a as AuditResult, A as AuditName, b as RecipeResult, R as RecipeName, I as InventoryProvider } from './types-DeKpgkG-.js';
2
- export { C as ConfigName } from './types-DeKpgkG-.js';
1
+ import { S as Site, a as AuditResult, A as AuditName, b as RecipeResult, R as RecipeName, I as InventoryProvider } from './types-QG-QhCYh.js';
2
+ export { C as ConfigName } from './types-QG-QhCYh.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';
@@ -20,9 +20,65 @@ type SpawnOptions = {
20
20
  };
21
21
  type SpawnFn = (cmd: string, args: readonly string[], opts?: SpawnOptions) => Promise<SpawnResult>;
22
22
 
23
+ /** Injected IO so the check is unit-testable without real DNS/TLS. `lookup` throws when the host
24
+ * doesn't resolve; `certValidTo` returns the cert's notAfter date, or null when there's none. */
25
+ type DomainDeps = {
26
+ lookup: (host: string) => Promise<void>;
27
+ certValidTo: (host: string) => Promise<Date | null>;
28
+ now: Date;
29
+ };
30
+
31
+ /**
32
+ * Route discovery for the deployed-URL browser audit. Pulls the site's sitemap, then samples a
33
+ * REPRESENTATIVE set of paths — bucketed by path family (first segment) and sampled round-robin —
34
+ * so every page *type* is covered, including the dynamic CMS-generated templates (Prismic
35
+ * `[uid]`/`[slug]` detail pages: blog posts, projects, portfolio items) where broken
36
+ * images / overflowing galleries / dead links hide. Taking the first N sitemap entries would skew
37
+ * to top-level static pages and miss them. Pure functions + one fetch-injected entry point.
38
+ */
39
+ type DiscoverDeps = {
40
+ /** Fetch a URL, returning its text body, or null on any non-2xx / network error. */
41
+ fetchText: (url: string) => Promise<string | null>;
42
+ };
43
+
44
+ /** One route probed across desktop engines + mobile devices, plus the internal links found on it. */
45
+ type RouteResult = {
46
+ url: string;
47
+ /** Per desktop engine (chromium/firefox/webkit): loaded with no JS error + a visible main landmark. */
48
+ desktop: Array<{
49
+ engine: string;
50
+ ok: boolean;
51
+ }>;
52
+ /** Per mobile device: loaded with no JS error and no horizontal overflow. */
53
+ mobile: Array<{
54
+ device: string;
55
+ ok: boolean;
56
+ }>;
57
+ /** Same-origin links discovered on the page (absolute URLs), for the Links check. */
58
+ links: string[];
59
+ };
60
+ type LinkResult = {
61
+ url: string;
62
+ status: number | null;
63
+ };
64
+ /** Injected browser IO. The real impl drives Playwright; tests pass a fake. */
65
+ type BrowserRunner = {
66
+ probe: (urls: string[]) => Promise<RouteResult[]>;
67
+ checkLinks: (urls: string[]) => Promise<LinkResult[]>;
68
+ close?: () => Promise<void>;
69
+ };
70
+
23
71
  type AuditContext = {
24
72
  site: Site;
25
73
  spawn?: SpawnFn;
74
+ /** Clock injection (domain + browser audits). Defaults to `new Date()`. */
75
+ now?: Date;
76
+ /** DNS/TLS injection for the domain audit (tests). Defaults to real DNS+TLS. */
77
+ domainDeps?: DomainDeps;
78
+ /** Sitemap/homepage fetch injection for the browser audit (tests). Defaults to real fetch. */
79
+ discoverDeps?: DiscoverDeps;
80
+ /** Playwright runner injection for the browser audit (tests). Defaults to real Playwright. */
81
+ browserRunner?: BrowserRunner;
26
82
  };
27
83
 
28
84
  declare function depsAudit(ctx: AuditContext): Promise<AuditResult>;
@@ -248,6 +304,20 @@ type WebsiteRow = {
248
304
  securityVulnsHigh: number | null;
249
305
  securityVulnsModerate: number | null;
250
306
  securityVulnsLow: number | null;
307
+ /** ISO timestamp the security audit last ran — gates freshness of the Security Updates auto-tick
308
+ * (clean counts only auto-tick when recent). */
309
+ lastSecurityAuditAt: string | null;
310
+ /** Domain/DNS/SSL probe (the `domain` audit). `certDaysRemaining` is days until the TLS cert
311
+ * expires (null = unresolved or no usable cert); `domainCheckedAt` is when it last ran. */
312
+ certDaysRemaining: number | null;
313
+ domainCheckedAt: string | null;
314
+ /** Deployed-URL browser probe (the `browser` audit): cross-engine render OK, mobile render OK,
315
+ * internal-links OK + broken count, and when it last ran (one timestamp gates all three). */
316
+ crossbrowserOk: boolean | null;
317
+ mobileOk: boolean | null;
318
+ linksOk: boolean | null;
319
+ brokenLinks: number | null;
320
+ browserCheckedAt: string | null;
251
321
  /** Per-site copy overrides (M6a). Blank → null → the DEFAULT_COPY value. */
252
322
  copyIntro: string | null;
253
323
  copyContact: string | null;
@@ -284,11 +354,6 @@ type ResolvedCopy = {
284
354
  launchSetupItems: string[];
285
355
  announceHeading: string;
286
356
  announceBody: string;
287
- announceCadenceHeading: string;
288
- announceTestingLabel: string;
289
- announceMaintenanceLabel: string;
290
- announcePreviewLabel: string;
291
- announceScoreNote: string;
292
357
  announceImprovementResend: string;
293
358
  announceImprovementSvelte5: string;
294
359
  announceCadence: string;
@@ -342,8 +407,8 @@ type ReportData = {
342
407
  resendForms?: boolean;
343
408
  svelte5?: boolean;
344
409
  };
345
- /** Announcement-only: the client's go-forward pace, rendered as the "WHAT TO EXPECT"
346
- * section. A "None" pace is omitted; undefined → the whole section is absent. */
410
+ /** Announcement-only: the client's go-forward pace, baked into each section's intro copy
411
+ * ("We do this every month."). A "None" pace omits that check section; undefined → neither. */
347
412
  cadence?: ReportCadence;
348
413
  /** Resolved per-site copy (M6a). Omitted → the template falls back to DEFAULT_COPY. */
349
414
  copy?: ResolvedCopy;
@@ -361,6 +426,14 @@ type ReportData = {
361
426
  headerBgColor?: string;
362
427
  };
363
428
 
429
+ /** A single auto-check outcome. `pass` + fresh ⇒ the caller ticks the box. */
430
+ type EvidenceResult = "pass" | "fail" | "unknown";
431
+ type EvidenceRecord = {
432
+ result: EvidenceResult;
433
+ checkedAt: string | null;
434
+ note: string;
435
+ };
436
+
364
437
  type DeliveryStatus = "pending" | "delivered" | "bounced" | "complained";
365
438
  type ReportRow = {
366
439
  id: string;
@@ -396,6 +469,10 @@ type ReportRow = {
396
469
  * missing/false cells read false. Maintenance/Testing reports gate approve+send on the relevant
397
470
  * subset (see src/reports/checklist.ts). */
398
471
  checklist: Record<string, boolean>;
472
+ /** Snapshot of the auto-tick evidence at draft time, keyed by checklist field → evidence
473
+ * record. Null when the report predates auto-tick or carried no auto-checked items. Drives the
474
+ * dashboard's green/amber badges; the gate still reads the booleans, not this. */
475
+ autoEvidence: Record<string, EvidenceRecord> | null;
399
476
  };
400
477
 
401
478
  type DraftOptions = {
@@ -429,6 +506,11 @@ type DraftResult = {
429
506
  html: string;
430
507
  /** Enrichment fetches that errored for this site (empty on success or skip). */
431
508
  softFailures: SoftFailure[];
509
+ /** Whether the draft was placed in the approve queue. False when a higher-or-equal-tier
510
+ * report is already queued for the site (single-queue rule); null on the previewOnly path. */
511
+ queued: boolean | null;
512
+ /** Ids of lower-tier queued reports this draft superseded (un-queued). */
513
+ supersededIds: string[];
432
514
  };
433
515
  /**
434
516
  * Render and create an Airtable draft for one site.