@chainpatrol/cli 0.4.0 → 0.4.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @chainpatrol/cli
2
2
 
3
+ ## 0.4.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 9126b45: Split the `reviewing.backlog` healthcheck into reviewable vs. total pending so the count matches the reviewing page in the app. The endpoint now reports `pendingProposals` (total), `reviewableProposals` (the subset the UI shows by default — assets not watchlisted, or reports from a customer), and `watchlistedHiddenProposals` (delta). Severity grades on the reviewable count; a non-zero watchlisted bucket surfaces as a warn-level finding. The bundled CLI skill is updated to document the new shape.
8
+ - fb0b846: Split the reviewing healthchecks along the operational divide between "Needs Review" (high-priority queue reviewers act on) and "Watchlisted" (intentionally deferred bucket):
9
+
10
+ - `reviewing.backlog` and `reviewing.old-proposals` now grade the Needs-Review bucket only — assets not on a watchlist, or reports submitted by a customer. Their counts now match what the reviewing page in the app shows by default.
11
+ - Two new checks cover the Watchlisted bucket as separate first-class signals: `reviewing.watchlist-backlog` (pile-up of watchlisted pending proposals) and `reviewing.watchlist-old` (watchlisted proposals deferred too long). Severity for both is **capped at warn** — watchlist cleanup matters but should never block on the same SLA as Needs Review.
12
+
13
+ The CLI skill is updated to spell out the distinction so a healthcheck report groups findings under the right bucket.
14
+
3
15
  ## 0.4.0
4
16
 
5
17
  ### Minor Changes
@@ -323,16 +323,41 @@ chainpatrol --json healthchecks run --all --org <slug>
323
323
 
324
324
  Each implemented check has a stable id of the form \`category.name\`, e.g.
325
325
  \`detections.silent-configs\`, \`reviewing.backlog\`,
326
- \`reviewing.old-proposals\`, \`takedowns.stale-in-progress\`.
326
+ \`reviewing.old-proposals\`, \`reviewing.watchlist-backlog\`,
327
+ \`reviewing.watchlist-old\`, \`takedowns.stale-in-progress\`.
328
+
329
+ ### Pending proposals: "Needs Review" vs "Watchlisted"
330
+
331
+ PENDING proposals split into two operationally distinct buckets, and we
332
+ grade them with separate checks:
333
+
334
+ - **Needs Review** \u2014 pending proposals the reviewing UI shows by default
335
+ (\`excludeWatchlisted=true\`): assets that are NOT on a watchlist, OR
336
+ reports submitted by a customer (those stay visible even when the asset
337
+ is watchlisted). This is the actionable queue reviewers work from, so
338
+ pile-ups and old items here are high-priority signals (\`fail\` severity
339
+ is reachable).
340
+ - **Watchlisted** \u2014 pending proposals on watchlisted assets (excluding
341
+ customer-reported reports). The reviewing UI hides these by default
342
+ because watchlisting is the act of intentionally deferring an asset.
343
+ Pile-ups and aged items here are worth surfacing as cleanup work, but
344
+ severity is **capped at warn** so they never block on the same SLA as
345
+ Needs Review. When reporting findings, treat these as lower-priority.
327
346
 
328
347
  Implemented checks today:
329
348
 
330
349
  - **detections.silent-configs** \u2014 equivalent to \`detections healthcheck\`,
331
350
  exposed under the uniform shape.
332
- - **reviewing.backlog** \u2014 counts proposals in PENDING review state and grades
351
+ - **reviewing.backlog** \u2014 counts Needs Review pending proposals and grades
333
352
  severity against per-org thresholds (default warn=50, fail=100).
334
- - **reviewing.old-proposals** \u2014 counts proposals older than the warn / fail
335
- age thresholds (default 7 / 14 days) and lists the oldest offenders.
353
+ - **reviewing.old-proposals** \u2014 counts Needs Review proposals older than
354
+ the warn / fail age thresholds (default 7 / 14 days) and lists the
355
+ oldest offenders.
356
+ - **reviewing.watchlist-backlog** \u2014 counts watchlisted pending proposals
357
+ (default warn=200). Severity capped at warn.
358
+ - **reviewing.watchlist-old** \u2014 counts watchlisted pending proposals older
359
+ than the warn-age threshold (default 30 days) and lists the oldest.
360
+ Severity capped at warn.
336
361
  - **takedowns.stale-in-progress** \u2014 counts takedowns sitting in IN_PROGRESS
337
362
  past the staleness threshold (default 7 days) and lists the oldest.
338
363
 
@@ -644,7 +669,23 @@ executed. For soft drops (still producing results but below baseline),
644
669
 
645
670
  ### Reviewing
646
671
 
647
- #### Pile Up / Backlog of Unreviewed Proposals
672
+ PENDING proposals split into two operationally distinct buckets:
673
+
674
+ - **Needs Review** \u2014 assets not on a watchlist, or reports submitted by a
675
+ customer. This is the reviewing UI's default view (\`excludeWatchlisted=true\`)
676
+ and the actionable queue reviewers work from. Pile-ups and aged items
677
+ here are high priority \u2014 \`fail\` severity is reachable.
678
+ - **Watchlisted** \u2014 pending proposals on watchlisted assets (excluding
679
+ customer-reported reports). The UI hides these by default because
680
+ watchlisting is the act of intentionally deferring the asset. Pile-ups
681
+ and aged items here are worth surfacing as cleanup work but **severity
682
+ is capped at warn** \u2014 they should never block on the same SLA as Needs
683
+ Review.
684
+
685
+ Each bucket has its own pile-up and age check, so you can grade them
686
+ independently and tune thresholds without one drowning the other.
687
+
688
+ #### Pile Up / Backlog of Needs-Review Proposals
648
689
 
649
690
  Too many proposals waiting in review. For most organizations this is over 100
650
691
  reports, but really the threshold is relative to the average number of
@@ -652,30 +693,50 @@ confirmed threats per week. Example: if an org only adds 5 blocked threats per
652
693
  week, then a 7-day backlog of even 10 proposals is a really big deal.
653
694
 
654
695
  **Run via CLI:** **Implemented as \`healthchecks run reviewing.backlog\`.**
655
- The endpoint counts proposals in PENDING review state and grades severity
696
+ The endpoint counts the **Needs Review** subset only (assets not
697
+ watchlisted, or reports marked \`reportedByCustomer\`) and grades severity
656
698
  against per-org thresholds (default warn=50, fail=100; override with
657
- \`--warn-threshold\` / \`--fail-threshold\` via the run payload). For raw
658
- counts plus SLA / age breakdowns, \`chainpatrol --json queues snapshot --org <slug>\`
659
- remains useful and exposes \`reviewQueue.totalPendingProposals\` and
660
- \`reviewQueue.distinctReports\`. Compare against the org's typical weekly
661
- throughput (use \`metrics summary --this-week\` for that baseline) \u2014 a
662
- backlog that exceeds a week of typical confirmed-threat volume is a finding
663
- regardless of the absolute number.
664
-
665
- #### Really Old Proposals
666
-
667
- Any proposal waiting for review longer than 14 days is a sign something has
668
- gone wrong. Even complex investigations rarely take longer than this. Except
669
- for rare cases, these should be rejected or approved to prevent a backlog
670
- from building.
699
+ \`--warn-threshold\` / \`--fail-threshold\` via the run payload). This is
700
+ the number the reviewing page in the app shows by default, so the
701
+ healthcheck output matches what reviewers see.
702
+
703
+ For raw counts plus SLA / age breakdowns,
704
+ \`chainpatrol --json queues snapshot --org <slug>\` remains useful and
705
+ exposes \`reviewQueue.totalPendingProposals\` and
706
+ \`reviewQueue.distinctReports\` (note: \`queues snapshot\` does NOT apply
707
+ the watchlist filter, so its number is the sum of Needs Review +
708
+ Watchlisted). Compare against the org's typical weekly throughput
709
+ (use \`metrics summary --this-week\` for that baseline) \u2014 a backlog that
710
+ exceeds a week of typical confirmed-threat volume is a finding regardless
711
+ of the absolute number.
712
+
713
+ #### Really Old Needs-Review Proposals
714
+
715
+ Any Needs-Review proposal waiting longer than 14 days is a sign something
716
+ has gone wrong. Even complex investigations rarely take longer than this.
717
+ Except for rare cases, these should be rejected or approved to prevent a
718
+ backlog from building.
671
719
 
672
720
  **Run via CLI:** **Implemented as \`healthchecks run reviewing.old-proposals\`.**
673
- The endpoint counts pending proposals older than the warn / fail age
721
+ The endpoint counts Needs-Review proposals older than the warn / fail age
674
722
  thresholds (default 7 / 14 days) and lists the oldest offenders in
675
723
  \`findings\`. \`queues snapshot\` (\`reviewQueue.ageBuckets.gte168h\`) still
676
724
  works as a raw view, and \`reviewQueue.slaBuckets.breached\` captures the
677
725
  strictest SLA breaches separately \u2014 any non-zero value is worth raising.
678
726
 
727
+ #### Watchlist Pile-Up / Old Watchlisted Proposals
728
+
729
+ Watchlisted-pending proposals are deferred on purpose, but they shouldn't
730
+ grow unbounded \u2014 a huge pile or very-old items signal that the watchlist
731
+ needs a cleanup pass. These don't block on the same SLA as Needs Review.
732
+
733
+ **Run via CLI:** **Implemented as \`healthchecks run reviewing.watchlist-backlog\`**
734
+ (pile-up count, default warn=200) and
735
+ **\`healthchecks run reviewing.watchlist-old\`** (default warn-age 30
736
+ days). Both cap severity at warn. When reporting findings during an org
737
+ healthcheck, group them under "watchlist cleanup" rather than mixing with
738
+ Needs-Review findings \u2014 they're operationally different concerns.
739
+
679
740
  #### Spike in Auto Approved Reports
680
741
 
681
742
  If suddenly a lot of proposals in an org are being approved by automation,
package/dist/cli.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  getCliVersion,
14
14
  isSkillInstalled,
15
15
  readInstalledSkillVersion
16
- } from "./chunk-S65NM7FF.js";
16
+ } from "./chunk-F4GU6AII.js";
17
17
  import "./chunk-IUZB3DQW.js";
18
18
  import {
19
19
  DateTime
@@ -1095,12 +1095,12 @@ async function main() {
1095
1095
  case "setup":
1096
1096
  case "install":
1097
1097
  case "i": {
1098
- const { setupSkill } = await import("./setup-skill-Z5RVCWCU.js");
1098
+ const { setupSkill } = await import("./setup-skill-2SEVH3M6.js");
1099
1099
  setupSkill({ json: jsonMode });
1100
1100
  break;
1101
1101
  }
1102
1102
  case "uninstall": {
1103
- const { uninstallSkill } = await import("./setup-skill-Z5RVCWCU.js");
1103
+ const { uninstallSkill } = await import("./setup-skill-2SEVH3M6.js");
1104
1104
  uninstallSkill({ json: jsonMode });
1105
1105
  break;
1106
1106
  }
@@ -6,7 +6,7 @@ import {
6
6
  readInstalledSkillVersion,
7
7
  setupSkill,
8
8
  uninstallSkill
9
- } from "./chunk-S65NM7FF.js";
9
+ } from "./chunk-F4GU6AII.js";
10
10
  import "./chunk-IUZB3DQW.js";
11
11
  export {
12
12
  getBundledSkillContent,
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@chainpatrol/cli",
3
3
  "description": "The official ChainPatrol CLI — terminal interface for threat detection",
4
4
  "author": "Umar Ahmed <umar@chainpatrol.io>",
5
- "version": "0.4.0",
5
+ "version": "0.4.1",
6
6
  "license": "UNLICENSED",
7
7
  "homepage": "https://chainpatrol.com/docs/cli",
8
8
  "keywords": [