@chainpatrol/cli 0.17.0 → 0.18.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/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # @chainpatrol/cli
2
2
 
3
+ ## 0.18.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 0825606: Drop `automated` from the per-service shape of `orgs list` / `orgs get`
8
+ (and the matching `/user/orgs` and `/user/orgs/{slug}` public APIs) for
9
+ every service except `takedowns`. `automated` only ever had operational
10
+ meaning for takedowns — it controls whether ChainPatrol files the
11
+ takedown on its own. The `isAutomated*Active` columns on
12
+ reporting/reviewing/protection have no runtime effect, so exposing them
13
+ in the public API only invited misleading filters and CSV columns.
14
+
15
+ Concretely:
16
+
17
+ - API response: `services.reporting`, `services.reviewing`, and
18
+ `services.protection` now return `{ "active": boolean }` only.
19
+ `services.takedowns` still returns `{ "active": boolean, "automated":
20
+ boolean }`. `detection` and `darkWebMonitoring` are unchanged.
21
+ - API services filter: same — `reporting`, `reviewing`, and
22
+ `protection` no longer accept an `automated` filter. Only
23
+ `takedowns` does.
24
+ - CLI: `--service-automated` / `--service-manual` now only accept
25
+ `takedowns`. Passing any other service name errors out with a
26
+ clearer message.
27
+ - CLI CSV output: drops the `reportingAutomated` / `reviewingAutomated`
28
+ / `protectionAutomated` columns. Only `takedownsAutomated` remains.
29
+ - Skill description and OpenAPI endpoint descriptions explain the
30
+ new shape.
31
+
32
+ Server-side work in @chainpatrol/external-trpc and @chainpatrol/validation
33
+ supports the new shape; both are private packages and don't need
34
+ version bumps.
35
+
3
36
  ## 0.17.0
4
37
 
5
38
  ### Minor Changes
@@ -626,10 +626,10 @@ Use \`--all\` to snapshot every org you have access to instead of a single slug.
626
626
 
627
627
  Returns every organization the caller can see, with each org's
628
628
  subscription status (\`PROSPECT\`, \`TRIAL\`, \`ACTIVE\`, \`INTEGRATION\`) and
629
- which services are active and automated. Use it to answer questions like
630
- "which customers have takedowns enabled but automation off?" or "which
631
- prospects don't have detection turned on yet?" \u2014 filters compose with AND
632
- and are applied server-side, so one call returns the final list.
629
+ which services are active. Use it to answer questions like "which
630
+ customers have takedowns enabled but automation off?" or "which prospects
631
+ don't have detection turned on yet?" \u2014 filters compose with AND and are
632
+ applied server-side, so one call returns the final list.
633
633
 
634
634
  \`\`\`bash
635
635
  chainpatrol --json orgs list \\
@@ -638,6 +638,40 @@ chainpatrol --json orgs list \\
638
638
  --service-manual takedowns
639
639
  \`\`\`
640
640
 
641
+ #### Per-service response shape \u2014 \`automated\` is takedowns-only
642
+
643
+ Every service exposes an \`active\` boolean. **Only \`takedowns\`
644
+ additionally exposes \`automated\`** \u2014 that is the one service where the
645
+ manual-vs-automated distinction changes real platform behavior (whether
646
+ ChainPatrol files the takedown on its own, or queues it for a human to
647
+ file). \`reporting\`, \`reviewing\`, and \`protection\` have backing
648
+ \`isAutomated*Active\` columns in the database, but those flags have no
649
+ operational effect today, so the API deliberately omits them from both
650
+ the response and the \`services\` filter \u2014 surfacing them would invite
651
+ misleading filters like "reporting.automated=true" that don't mean
652
+ anything. \`detection\` and \`darkWebMonitoring\` have always been
653
+ single-flag services.
654
+
655
+ So per-org JSON looks like:
656
+
657
+ \`\`\`json
658
+ {
659
+ "services": {
660
+ "reporting": { "active": true },
661
+ "reviewing": { "active": true },
662
+ "protection": { "active": false },
663
+ "takedowns": { "active": true, "automated": false },
664
+ "detection": { "active": true },
665
+ "darkWebMonitoring": { "active": false }
666
+ }
667
+ }
668
+ \`\`\`
669
+
670
+ When a user asks about "automated reporting / reviewing / protection",
671
+ explain that the flag exists in the DB but has no operational effect and
672
+ isn't exposed by the public API \u2014 only \`takedowns.automated\` carries a
673
+ real meaning.
674
+
641
675
  Filter flags (all optional, all comma-separated lists):
642
676
 
643
677
  - \`--query <text>\` partial name match (substring, case-insensitive)
@@ -646,11 +680,11 @@ Filter flags (all optional, all comma-separated lists):
646
680
  through this filter \u2014 \`orgs list\` only ever returns live customers.
647
681
  - \`--service-active <list>\` services that must be active
648
682
  - \`--service-inactive <list>\` services that must be inactive
649
- - \`--service-automated <list>\` services whose automation must be ON
650
- (\`reporting\`, \`reviewing\`, \`protection\`, \`takedowns\` \u2014 the four
651
- with an automation toggle)
652
- - \`--service-manual <list>\` services whose automation must be OFF
653
- (same four)
683
+ - \`--service-automated <list>\` services whose automation must be ON.
684
+ **Only \`takedowns\` is accepted** \u2014 the other services don't have a
685
+ meaningful automation toggle. Passing any other service name errors out.
686
+ - \`--service-manual <list>\` services whose automation must be OFF.
687
+ Same restriction \u2014 only \`takedowns\`.
654
688
 
655
689
  Service names: \`reporting\`, \`reviewing\`, \`protection\`, \`takedowns\`,
656
690
  \`detection\`, \`darkWebMonitoring\`.
@@ -662,11 +696,13 @@ enforced server-side.
662
696
  ### \`orgs get\` \u2014 Get a single organization by slug
663
697
 
664
698
  Look up one organization the caller has access to. Returns the same per-org
665
- shape as a single row from \`orgs list\` (subscription status + per-service
666
- active/automated flags), so anything you could read from \`orgs list\` you
667
- can also read here without paging or filtering. Use it when the user names
668
- a specific customer ("show me acme's setup", "is takedowns automation on
669
- for morpho?") and you don't need the rest of the catalogue.
699
+ shape as a single row from \`orgs list\` \u2014 \`active\` for every service,
700
+ plus \`automated\` on \`takedowns\` only (see the note above on why other
701
+ services don't expose an automation flag). Anything you could read from
702
+ \`orgs list\` you can also read here without paging or filtering. Use it
703
+ when the user names a specific customer ("show me acme's setup", "is
704
+ takedowns automation on for morpho?") and you don't need the rest of the
705
+ catalogue.
670
706
 
671
707
  \`\`\`bash
672
708
  chainpatrol orgs get <slug>
package/dist/cli.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  getCliVersion,
14
14
  isSkillInstalled,
15
15
  readInstalledSkillVersion
16
- } from "./chunk-75H4KTIQ.js";
16
+ } from "./chunk-MDDC4F6Q.js";
17
17
  import "./chunk-NQT77IB7.js";
18
18
  import {
19
19
  DateTime
@@ -513,15 +513,15 @@ var HELP = {
513
513
  examples: ["chainpatrol orgs asset-groups list --output csv"]
514
514
  },
515
515
  "orgs list": {
516
- description: "List organizations with their subscription status and per-service active/automated flags. All filters compose with AND.",
516
+ description: "List organizations with their subscription status and per-service active flag (plus `automated` for takedowns only \u2014 that's the one service where manual-vs-automated changes real platform behavior). All filters compose with AND.",
517
517
  usage: "chainpatrol orgs list [filters]",
518
518
  options: [
519
519
  "--query <text> Partial name match (substring, case-insensitive)",
520
520
  "--subscription-status <l> Comma-separated list (PROSPECT,TRIAL,ACTIVE,INTEGRATION)",
521
521
  "--service-active <l> Comma-separated services that must be active",
522
522
  "--service-inactive <l> Comma-separated services that must be inactive",
523
- "--service-automated <l> Services whose automation must be ON (reporting,reviewing,protection,takedowns)",
524
- "--service-manual <l> Services whose automation must be OFF (reporting,reviewing,protection,takedowns)"
523
+ "--service-automated <l> Services whose automation must be ON (only `takedowns` is accepted \u2014 the other services have no meaningful automation toggle)",
524
+ "--service-manual <l> Services whose automation must be OFF (only `takedowns` is accepted)"
525
525
  ],
526
526
  examples: [
527
527
  "chainpatrol orgs list --subscription-status ACTIVE",
@@ -530,7 +530,7 @@ var HELP = {
530
530
  ]
531
531
  },
532
532
  "orgs get": {
533
- description: "Get a single organization by slug. Returns the same shape as one row of `orgs list` (subscription status + per-service active/automated flags). Caller must have access: org-scoped API keys must match the slug, user sessions/keys need an active membership unless the user is staff.",
533
+ description: "Get a single organization by slug. Returns the same shape as one row of `orgs list` (subscription status + per-service active flag, with `automated` exposed only for takedowns \u2014 the one service where manual-vs-automated changes real platform behavior). Caller must have access: org-scoped API keys must match the slug, user sessions/keys need an active membership unless the user is staff.",
534
534
  usage: "chainpatrol orgs get <slug>",
535
535
  options: [
536
536
  "--org <slug> Use the saved default org instead of a positional argument."
@@ -1538,7 +1538,7 @@ async function main() {
1538
1538
  }
1539
1539
  case "orgs": {
1540
1540
  if (subcommand === "list") {
1541
- const { runOrgsList } = await import("./list-OEJV4UNQ.js");
1541
+ const { runOrgsList } = await import("./list-XUYCZG7S.js");
1542
1542
  await runOrgsList({
1543
1543
  query: cli.flags.query,
1544
1544
  subscriptionStatus: cli.flags.subscriptionStatus,
@@ -1554,7 +1554,7 @@ async function main() {
1554
1554
  if (subcommand === "get") {
1555
1555
  const positionalSlug = action;
1556
1556
  const slug = positionalSlug ?? await tryResolveOrg();
1557
- const { runOrgsGet } = await import("./get-BPTWCJ6H.js");
1557
+ const { runOrgsGet } = await import("./get-YFYSJFBC.js");
1558
1558
  await runOrgsGet({
1559
1559
  slug,
1560
1560
  json: jsonMode,
@@ -1664,12 +1664,12 @@ async function main() {
1664
1664
  case "setup":
1665
1665
  case "install":
1666
1666
  case "i": {
1667
- const { setupSkill } = await import("./setup-skill-RPVW2CCQ.js");
1667
+ const { setupSkill } = await import("./setup-skill-Z6SBI6GC.js");
1668
1668
  setupSkill({ json: jsonMode, cloud: cli.flags.cloud });
1669
1669
  break;
1670
1670
  }
1671
1671
  case "uninstall": {
1672
- const { uninstallSkill } = await import("./setup-skill-RPVW2CCQ.js");
1672
+ const { uninstallSkill } = await import("./setup-skill-Z6SBI6GC.js");
1673
1673
  uninstallSkill({ json: jsonMode });
1674
1674
  break;
1675
1675
  }
@@ -16,11 +16,12 @@ import "./chunk-U73SABXK.js";
16
16
  // src/commands/orgs/get.ts
17
17
  function summarizeServices(org) {
18
18
  const parts = [];
19
- for (const service of ["reporting", "reviewing", "protection", "takedowns"]) {
20
- const entry = org.services[service];
21
- if (!entry.active) continue;
22
- parts.push(`${service}=${entry.automated ? "auto" : "manual"}`);
19
+ if (org.services.takedowns.active) {
20
+ parts.push(`takedowns=${org.services.takedowns.automated ? "auto" : "manual"}`);
23
21
  }
22
+ if (org.services.reporting.active) parts.push("reporting");
23
+ if (org.services.reviewing.active) parts.push("reviewing");
24
+ if (org.services.protection.active) parts.push("protection");
24
25
  if (org.services.detection.active) parts.push("detection");
25
26
  if (org.services.darkWebMonitoring.active) parts.push("darkWebMonitoring");
26
27
  return parts.length > 0 ? parts.join(" ") : "(no services enabled)";
@@ -52,12 +53,10 @@ async function runOrgsGet(options) {
52
53
  name: organization.name,
53
54
  subscriptionStatus: organization.subscriptionStatus,
54
55
  reportingActive: organization.services.reporting.active,
55
- reportingAutomated: organization.services.reporting.automated,
56
56
  reviewingActive: organization.services.reviewing.active,
57
- reviewingAutomated: organization.services.reviewing.automated,
58
57
  protectionActive: organization.services.protection.active,
59
- protectionAutomated: organization.services.protection.automated,
60
58
  takedownsActive: organization.services.takedowns.active,
59
+ // `takedowns` is the only service with a meaningful automation flag.
61
60
  takedownsAutomated: organization.services.takedowns.automated,
62
61
  detectionActive: organization.services.detection.active,
63
62
  darkWebMonitoringActive: organization.services.darkWebMonitoring.active
@@ -20,8 +20,14 @@ var VALID_SUBSCRIPTION_STATUSES = /* @__PURE__ */ new Set([
20
20
  "ACTIVE",
21
21
  "INTEGRATION"
22
22
  ]);
23
- var DUAL_SERVICES = ["reporting", "reviewing", "protection", "takedowns"];
24
- var SINGLE_SERVICES = ["detection", "darkWebMonitoring"];
23
+ var DUAL_SERVICES = ["takedowns"];
24
+ var SINGLE_SERVICES = [
25
+ "reporting",
26
+ "reviewing",
27
+ "protection",
28
+ "detection",
29
+ "darkWebMonitoring"
30
+ ];
25
31
  var ALL_SERVICES = [...DUAL_SERVICES, ...SINGLE_SERVICES];
26
32
  function splitCsv(value) {
27
33
  if (!value) return [];
@@ -60,7 +66,7 @@ function parseServiceList(raw, flagName) {
60
66
  function requireDualService(service, flagName) {
61
67
  if (!DUAL_SERVICES.includes(service)) {
62
68
  throw new CliExitError(
63
- `Service '${service}' does not have an automation toggle and can't be used with --${flagName}. Use --service-active / --service-inactive instead.`,
69
+ `Service '${service}' does not have a meaningful automation toggle and can't be used with --${flagName}. Only 'takedowns' supports --service-automated / --service-manual; use --service-active / --service-inactive for the others.`,
64
70
  ExitCode.USAGE
65
71
  );
66
72
  }
@@ -114,10 +120,8 @@ function buildServicesFilter(options) {
114
120
  }
115
121
  function summarizeServices(org) {
116
122
  const parts = [];
117
- for (const service of DUAL_SERVICES) {
118
- const entry = org.services[service];
119
- if (!entry.active) continue;
120
- parts.push(`${service}=${entry.automated ? "auto" : "manual"}`);
123
+ if (org.services.takedowns.active) {
124
+ parts.push(`takedowns=${org.services.takedowns.automated ? "auto" : "manual"}`);
121
125
  }
122
126
  for (const service of SINGLE_SERVICES) {
123
127
  if (org.services[service].active) parts.push(service);
@@ -150,12 +154,10 @@ async function runOrgsList(options) {
150
154
  name: org.name,
151
155
  subscriptionStatus: org.subscriptionStatus,
152
156
  reportingActive: org.services.reporting.active,
153
- reportingAutomated: org.services.reporting.automated,
154
157
  reviewingActive: org.services.reviewing.active,
155
- reviewingAutomated: org.services.reviewing.automated,
156
158
  protectionActive: org.services.protection.active,
157
- protectionAutomated: org.services.protection.automated,
158
159
  takedownsActive: org.services.takedowns.active,
160
+ // `takedowns` is the only service with a meaningful automation flag.
159
161
  takedownsAutomated: org.services.takedowns.automated,
160
162
  detectionActive: org.services.detection.active,
161
163
  darkWebMonitoringActive: org.services.darkWebMonitoring.active
@@ -6,7 +6,7 @@ import {
6
6
  readInstalledSkillVersion,
7
7
  setupSkill,
8
8
  uninstallSkill
9
- } from "./chunk-75H4KTIQ.js";
9
+ } from "./chunk-MDDC4F6Q.js";
10
10
  import "./chunk-NQT77IB7.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.17.0",
5
+ "version": "0.18.0",
6
6
  "license": "UNLICENSED",
7
7
  "homepage": "https://chainpatrol.com/docs/cli",
8
8
  "keywords": [