@reddoorla/maintenance 0.62.1 → 0.64.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.js CHANGED
@@ -1,3 +1,4 @@
1
+ import "./chunk-BMDBOPN3.js";
1
2
  import {
2
3
  findDueReports
3
4
  } from "./chunk-WVRPOXKH.js";
@@ -25,17 +26,17 @@ import {
25
26
  draftReportForSite
26
27
  } from "./chunk-NPJFHBAX.js";
27
28
  import "./chunk-6LIWDIXU.js";
28
- import "./chunk-BMDBOPN3.js";
29
29
  import {
30
30
  sendApprovedReports
31
- } from "./chunk-DXRKWALS.js";
31
+ } from "./chunk-J37CZORZ.js";
32
+ import "./chunk-OGGRFBL4.js";
33
+ import "./chunk-GECESMVS.js";
32
34
  import {
33
35
  BLURRED_CID,
34
36
  CHECK_CID,
35
37
  loadBundledImages,
36
38
  renderReportHtml
37
39
  } from "./chunk-U3MF6RCS.js";
38
- import "./chunk-OGGRFBL4.js";
39
40
  import {
40
41
  checklistFor,
41
42
  escapeHtml,
@@ -650,7 +651,7 @@ function isReadyDeployStatus(status) {
650
651
  function isFailedDeployStatus(status) {
651
652
  return status !== null && FAILED_DEPLOY_STATES.has(status.toLowerCase());
652
653
  }
653
- var NEEDS_YOU_GROUP_RANK = { broken: 0, approval: 1, slipping: 2 };
654
+ var NEEDS_YOU_GROUP_RANK = { broken: 0, watch: 1, approval: 2 };
654
655
  function buildNeedsYouFeed(model) {
655
656
  const bySlug = /* @__PURE__ */ new Map();
656
657
  const get = (siteName) => {
@@ -663,8 +664,8 @@ function buildNeedsYouFeed(model) {
663
664
  reasons: [],
664
665
  hasCritical: false,
665
666
  broken: false,
666
- approval: false,
667
- slipping: false
667
+ watch: false,
668
+ approval: false
668
669
  };
669
670
  bySlug.set(slug, a);
670
671
  }
@@ -672,17 +673,25 @@ function buildNeedsYouFeed(model) {
672
673
  };
673
674
  for (const card2 of model.cards) {
674
675
  if (card2.tier === "attention") {
675
- for (const item of card2.items) {
676
- if (item.kind === "vuln" && item.autoFixExhausted !== true) continue;
676
+ const isSelfPatchingVuln = (it) => it.kind === "vuln" && it.autoFixExhausted !== true;
677
+ const hardBroken = card2.items.filter((it) => !isSelfPatchingVuln(it));
678
+ const selfPatchingVulns = card2.items.filter(isSelfPatchingVuln);
679
+ if (hardBroken.length > 0) {
677
680
  const a = get(card2.site.name);
678
- a.reasons.push(item.title);
681
+ for (const it of hardBroken) {
682
+ a.reasons.push(it.title);
683
+ if (it.severity === "critical") a.hasCritical = true;
684
+ }
679
685
  a.broken = true;
680
- if (item.severity === "critical") a.hasCritical = true;
686
+ } else if (selfPatchingVulns.length > 0) {
687
+ const a = get(card2.site.name);
688
+ for (const it of selfPatchingVulns) a.reasons.push(it.title);
689
+ a.watch = true;
681
690
  }
682
691
  } else if (card2.tier === "watch" && card2.watchReasons.length > 0) {
683
692
  const a = get(card2.site.name);
684
693
  for (const r of card2.watchReasons) a.reasons.push(r);
685
- a.slipping = true;
694
+ a.watch = true;
686
695
  }
687
696
  }
688
697
  for (const p of model.pending) {
@@ -693,7 +702,7 @@ function buildNeedsYouFeed(model) {
693
702
  const items = [];
694
703
  for (const a of bySlug.values()) {
695
704
  if (a.reasons.length === 0) continue;
696
- const group = a.broken ? "broken" : a.approval ? "approval" : "slipping";
705
+ const group = a.broken ? "broken" : a.watch ? "watch" : "approval";
697
706
  items.push({
698
707
  group,
699
708
  hasCritical: a.hasCritical,
@@ -962,7 +971,11 @@ details.fleet-browse > summary, details.inbox > summary { cursor:pointer; font-w
962
971
  .verdict.ok .verdict-meta { color:#2e7d32; }
963
972
  .verdict.warn { background:#fdecea; color:#b00; }
964
973
  .verdict.warn .verdict-meta { color:#b00; opacity:0.85; }
965
- @media (prefers-color-scheme: dark) { .verdict.ok { background:#10240f; color:#7fce85; } .verdict.warn { background:#2a0f0d; color:#ff8a80; } }
974
+ .verdict.watch { background:#fff4e5; color:#a65a00; }
975
+ .verdict.watch .verdict-meta { color:#a65a00; opacity:0.85; }
976
+ .verdict.soft { background:#e7f1ff; color:#1c5d99; }
977
+ .verdict.soft .verdict-meta { color:#1c5d99; opacity:0.85; }
978
+ @media (prefers-color-scheme: dark) { .verdict.ok { background:#10240f; color:#7fce85; } .verdict.warn { background:#2a0f0d; color:#ff8a80; } .verdict.watch { background:#2a2410; color:#ffd454; } .verdict.soft { background:#0f1d2a; color:#7fb6e8; } }
966
979
  .verdict .fleet-actions { margin:0.6rem 0 0; }
967
980
  .needs-you { border:1px solid #e5e5e5; border-radius:8px; padding:0.75rem 1rem; margin-bottom:1.25rem; }
968
981
  @media (prefers-color-scheme: dark) { .needs-you { border-color:#2a2a2a; background:#181818; } }
@@ -976,39 +989,66 @@ details.fleet-browse > summary, details.inbox > summary { cursor:pointer; font-w
976
989
  .dot { width:0.55rem; height:0.55rem; border-radius:50%; display:inline-block; flex:0 0 auto; }
977
990
  .dot.broken { background:#dc2626; }
978
991
  .dot.approval { background:#2563eb; }
979
- .dot.slipping { background:#f59e0b; }
992
+ .dot.watch { background:#f59e0b; }
980
993
  `;
981
- function verdictBar(model, feedCount) {
994
+ function needsYouCounts(feed) {
995
+ let broken = 0;
996
+ let watch = 0;
997
+ let approval = 0;
998
+ for (const i of feed) {
999
+ if (i.group === "broken") broken++;
1000
+ else if (i.group === "watch") watch++;
1001
+ else approval++;
1002
+ }
1003
+ return { broken, watch, approval };
1004
+ }
1005
+ function verdictBar(model, feed) {
982
1006
  const auditedIso = fleetLastAuditedAt(model.cards);
983
- const audited = auditedIso ? ` \xB7 fleet last audited ${escapeHtml(relativeTimeFromNow(auditedIso))}` : "";
984
- const sites = model.cards.length;
985
- const sitesWord = `${sites} site${sites === 1 ? "" : "s"}`;
1007
+ const auditedTerm = auditedIso ? `fleet last audited ${escapeHtml(relativeTimeFromNow(auditedIso))}` : null;
1008
+ const total = model.cards.length;
1009
+ const { broken, watch, approval } = needsYouCounts(feed);
1010
+ const healthy = Math.max(0, total - (broken + watch + approval));
986
1011
  const actions = `<div class="fleet-actions">
987
1012
  <button type="button" class="refresh-fleet" data-refresh-url="/api/fleet/refresh">\u21BB Audit fleet</button>
988
1013
  <div id="rf-status" class="rf-status" aria-live="polite"></div>
989
1014
  </div>`;
990
- if (feedCount === 0) {
991
- return `<div class="verdict ok">
992
- <div class="verdict-line">\u2713 All clear</div>
993
- <div class="verdict-meta">${sitesWord} healthy${audited}</div>
994
- ${actions}
995
- </div>`;
996
- }
997
- const noun = feedCount === 1 ? "site needs" : "sites need";
998
- return `<div class="verdict warn">
999
- <div class="verdict-line">\u26A0 ${feedCount} ${noun} you</div>
1000
- <div class="verdict-meta">${sitesWord}${audited}</div>
1015
+ const render = (cls, line, terms) => `<div class="verdict ${cls}">
1016
+ <div class="verdict-line">${line}</div>
1017
+ <div class="verdict-meta">${terms.filter(Boolean).join(" \xB7 ")}</div>
1001
1018
  ${actions}
1002
1019
  </div>`;
1020
+ if (broken === 0 && watch === 0 && approval === 0) {
1021
+ const sitesWord = `${total} site${total === 1 ? "" : "s"}`;
1022
+ return render("ok", "\u2713 All clear", [`${sitesWord} healthy`, auditedTerm]);
1023
+ }
1024
+ const watchTerm = watch > 0 ? `${watch} watching` : null;
1025
+ const approvalTerm = approval > 0 ? `${approval} waiting on you` : null;
1026
+ const healthyTerm = healthy > 0 ? `${healthy} healthy` : null;
1027
+ if (broken > 0) {
1028
+ return render("warn", `\u26A0 ${broken} site${broken === 1 ? "" : "s"} broken`, [
1029
+ watchTerm,
1030
+ approvalTerm,
1031
+ healthyTerm,
1032
+ auditedTerm
1033
+ ]);
1034
+ }
1035
+ if (watch > 0) {
1036
+ return render("watch", `${watch} site${watch === 1 ? "" : "s"} to watch`, [
1037
+ approvalTerm,
1038
+ healthyTerm,
1039
+ auditedTerm
1040
+ ]);
1041
+ }
1042
+ return render("soft", `${approval} waiting on you`, [healthyTerm, auditedTerm]);
1003
1043
  }
1004
1044
  var NEEDS_YOU_GROUP_LABEL = {
1005
1045
  broken: "Broken",
1006
- approval: "Waiting on your yes",
1007
- slipping: "Slipping"
1046
+ watch: "Watch",
1047
+ approval: "Waiting on your yes"
1008
1048
  };
1009
1049
  function renderNeedsYouFeed(feed) {
1010
1050
  if (feed.length === 0) return "";
1011
- const groups = ["broken", "approval", "slipping"];
1051
+ const groups = ["broken", "watch", "approval"];
1012
1052
  const blocks = groups.map((g) => {
1013
1053
  const rows = feed.filter((i) => i.group === g);
1014
1054
  if (rows.length === 0) return "";
@@ -1212,7 +1252,7 @@ function renderCockpitHtml(model) {
1212
1252
  <body>
1213
1253
  <h1>Reddoor fleet cockpit</h1>
1214
1254
  <div class="meta">${total} site${total === 1 ? "" : "s"} on the Reddoor stack.</div>
1215
- ${verdictBar(model, feed.length)}
1255
+ ${verdictBar(model, feed)}
1216
1256
  ${renderNeedsYouFeed(feed)}
1217
1257
  ${renderFleetBrowsePanel(model)}
1218
1258
  ${renderRecentlyLane(model)}