@chainpatrol/cli 0.11.0 → 0.13.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/dist/{breakdown-MM5GSZKV.js → breakdown-B6QUGYI6.js} +21 -6
  3. package/dist/{check-GDKUHVQI.js → check-P5JJJNEX.js} +1 -1
  4. package/dist/{chunk-EPKNZRX6.js → chunk-BQDMAEQU.js} +51 -6
  5. package/dist/{chunk-37KYJWB3.js → chunk-DJVB73FL.js} +1 -1
  6. package/dist/{chunk-YXRFUYA6.js → chunk-NQT77IB7.js} +50 -8
  7. package/dist/{chunk-SX3L6NKR.js → chunk-OSRFCVBT.js} +129 -2
  8. package/dist/chunk-S37VFIZY.js +66 -0
  9. package/dist/cli.js +411 -86
  10. package/dist/{completions-62OW3B3Y.js → completions-6C6KG5DH.js} +1 -1
  11. package/dist/{configs-update-7X7657PB.js → configs-update-3ZVXGADV.js} +1 -1
  12. package/dist/{create-FL4QQTPN.js → create-DFH2G7RH.js} +1 -1
  13. package/dist/{drift-JKBHWWFU.js → drift-T74V2C3J.js} +1 -1
  14. package/dist/found-NXAWEIEK.js +59 -0
  15. package/dist/{healthcheck-EVQVPGWW.js → healthcheck-HZYEIIOR.js} +1 -1
  16. package/dist/{list-BLNIE4GL.js → list-23QQYAV5.js} +1 -1
  17. package/dist/list-EIVPGMWJ.js +82 -0
  18. package/dist/list-I7SBGA52.js +50 -0
  19. package/dist/{list-5DN6X3DP.js → list-IYJBKE2F.js} +1 -1
  20. package/dist/list-PBAXQSL5.js +85 -0
  21. package/dist/list-QUFY4IP7.js +146 -0
  22. package/dist/{list-JPG2ZSR4.js → list-WJQT2XLE.js} +7 -1
  23. package/dist/{list-ULHPOUJV.js → list-WX5G3IOF.js} +2 -2
  24. package/dist/list-YCT6DYDI.js +89 -0
  25. package/dist/{list-XDGU6SJQ.js → list-YRJPN4PI.js} +1 -1
  26. package/dist/{list-E5XNR2YG.js → list-ZFPML3ZR.js} +47 -3
  27. package/dist/{list-json-R2MIXADX.js → list-json-T2Z7NV7G.js} +1 -1
  28. package/dist/{organization-MJRKWC4Z.js → organization-GS5LFIWO.js} +19 -6
  29. package/dist/{run-EUVRC72M.js → run-BHEXWBAS.js} +2 -2
  30. package/dist/{run-2YZZGZYN.js → run-CJGN6TX4.js} +1 -1
  31. package/dist/{run-5E5EC3MP.js → run-MSO6IXEV.js} +1 -1
  32. package/dist/search-WPSKQGUS.js +71 -0
  33. package/dist/{setup-skill-HAENFIFQ.js → setup-skill-TPMTULHJ.js} +2 -2
  34. package/dist/{snapshot-3FUJICJJ.js → snapshot-ZWAHEG64.js} +1 -1
  35. package/dist/{summary-RVYQUKWV.js → summary-CV657J5V.js} +19 -6
  36. package/dist/{validate-UOVKEAJM.js → validate-SM5DD7I2.js} +1 -1
  37. package/dist/whoami-DH5HVLFN.js +69 -0
  38. package/package.json +1 -1
  39. package/dist/found-3WI4XQG4.js +0 -95
package/CHANGELOG.md CHANGED
@@ -1,5 +1,75 @@
1
1
  # @chainpatrol/cli
2
2
 
3
+ ## 0.13.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 7cc2783: Default every `chainpatrol metrics …` subcommand
8
+ (`summary` / `found` / `breakdown` / `organization`) to a trailing
9
+ **3-month** window when no `--from`/`--to`/`--this-week` flag is
10
+ supplied, and echo the resolved range in every output format
11
+ (human, markdown, csv, json) so consumers can see exactly what
12
+ window the numbers describe.
13
+
14
+ Previously, omitting the date flags sent `undefined` for `startDate`
15
+ / `endDate`, which caused the metrics handler to fan out ~15 parallel
16
+ unbounded Prisma aggregates per call. On large orgs that routinely
17
+ exceeded the platform's 30s function cap and surfaced to agents as
18
+ flaky `503` responses. The new default keeps the queries bounded
19
+ and produces a stable, labelled result.
20
+
21
+ `--this-week` is now also wired through to `metrics summary`,
22
+ `metrics breakdown`, and `metrics organization` (it was already
23
+ supported on `metrics found`).
24
+
25
+ JSON output now includes a `range: { startDate, endDate, label }`
26
+ field on every metrics subcommand. The label is one of
27
+ `"last 3 months"` (default), `"this week"`, or
28
+ `"custom range (<startIso> → <endIso>)"`.
29
+
30
+ ## 0.12.0
31
+
32
+ ### Minor Changes
33
+
34
+ - 28cdda8: Two-part change to the external API surface and the CLI:
35
+
36
+ **Part 1: eight new read-only commands** so operators and agents can pull
37
+ asset, threat, detection, report-search, and identity data without leaving the
38
+ terminal:
39
+
40
+ - `chainpatrol asset list` — `POST /asset/list`
41
+ - `chainpatrol threats list` — `POST /threats/list`
42
+ - `chainpatrol detections list` — `POST /detection/list`
43
+ - `chainpatrol reports search` — `POST /reports/search`
44
+ - `chainpatrol orgs assets list` — `GET /organization/assets`
45
+ - `chainpatrol orgs asset-groups list` — `GET /organization/asset-groups`
46
+ - `chainpatrol whoami` — `GET /validate` (with an API key) or `POST /user/me`
47
+ (with a session token)
48
+
49
+ All support the standard `--json` / `--output {human,json,markdown,csv}` shapes
50
+ and integrate with the existing API-key and session auth modes.
51
+
52
+ **Part 2: filter parity** between the external API + CLI and the app's
53
+ detections / takedowns / reports views.
54
+
55
+ - **Detections** — new filter properties on `POST /detection/list`: liveness,
56
+ watchlist, reported, deleted (opt-in), countryCode. CLI flags:
57
+ `--liveness`, `--watchlist`, `--reported`, `--country-code`,
58
+ `--include-deleted`, plus brand filtering via `--brand`.
59
+ - **Takedowns** — new fields on `POST /takedowns/list`: brandIds, assigneeIds,
60
+ startedAtStartDate / startedAtEndDate (computed from the earliest
61
+ IN_PROGRESS TakedownEvent), hideAutomatedTakedowns,
62
+ hideAutomatedLivenessChecks; plus new sort keys `assigneeId`, `brandId`.
63
+ CLI flags: `--brand`, `--assignee`, `--started-from`, `--started-to`,
64
+ `--hide-automated-takedowns`, `--hide-automated-liveness-checks`.
65
+ - **Reports** — the external `/public/getOrganizationReports` endpoint
66
+ already accepted every app filter via its shared schema; the CLI now
67
+ surfaces them. New flags on `chainpatrol reports list`: `--reporter-query`,
68
+ `--exclude-automation`, `--only-rejected`, `--review-status`,
69
+ `--asset-type`, `--brand`, `--country-code`, `--reviewed-by-user-id`,
70
+ `--updated-from`, `--updated-to`, and the existing `--from`/`--to` are now
71
+ wired through.
72
+
3
73
  ## 0.11.0
4
74
 
5
75
  ### Minor Changes
@@ -1,31 +1,40 @@
1
+ import {
2
+ resolveDateRange
3
+ } from "./chunk-S37VFIZY.js";
1
4
  import {
2
5
  printOutput,
3
6
  toCsvRows
4
7
  } from "./chunk-VFT3TD3E.js";
5
8
  import {
6
9
  createApiClient
7
- } from "./chunk-SX3L6NKR.js";
10
+ } from "./chunk-OSRFCVBT.js";
8
11
  import "./chunk-EGWK6SRQ.js";
9
12
  import "./chunk-TFCNKBRC.js";
10
13
  import "./chunk-U73SABXK.js";
11
14
 
12
15
  // src/commands/metrics/breakdown.ts
13
16
  async function runMetricsBreakdown(options) {
17
+ const range = resolveDateRange({
18
+ from: options.from,
19
+ to: options.to,
20
+ thisWeek: options.thisWeek
21
+ });
14
22
  const client = options.apiClient ?? createApiClient();
15
23
  const result = await client.getMetricsBreakdown({
16
24
  slug: options.org,
17
25
  by: options.by,
18
- startDate: options.from,
19
- endDate: options.to,
26
+ startDate: range.startDate,
27
+ endDate: range.endDate,
20
28
  brandIds: options.brandIds
21
29
  });
22
30
  const outputFormat = options.outputFormat ?? (options.json ? "json" : "human");
23
31
  printOutput({
24
32
  outputFormat,
25
- json: result,
33
+ json: { ...result, range },
26
34
  markdown: [
27
- `# Metrics Breakdown (${options.org})`,
35
+ `# Metrics Breakdown (${options.org}) \u2014 ${range.label}`,
28
36
  "",
37
+ `- Range: ${range.startDate} \u2192 ${range.endDate}`,
29
38
  `- Grouped by: ${result.by}`,
30
39
  "",
31
40
  ...result.points.map((point) => {
@@ -40,6 +49,9 @@ async function runMetricsBreakdown(options) {
40
49
  ].join("\n"),
41
50
  csv: toCsvRows(
42
51
  result.points.map((point) => ({
52
+ rangeLabel: range.label,
53
+ startDate: range.startDate,
54
+ endDate: range.endDate,
43
55
  key: point.key,
44
56
  count: point.count,
45
57
  date: point.date ?? null,
@@ -50,7 +62,10 @@ async function runMetricsBreakdown(options) {
50
62
  }))
51
63
  ),
52
64
  human: () => {
53
- console.log(`Metrics breakdown for ${options.org} by ${result.by}`);
65
+ console.log(
66
+ `Metrics breakdown for ${options.org} by ${result.by} \u2014 ${range.label}`
67
+ );
68
+ console.log(`Range: ${range.startDate} \u2192 ${range.endDate}`);
54
69
  for (const point of result.points) {
55
70
  if (result.by === "day") {
56
71
  console.log(`${point.date ?? point.key}: ${point.count}`);
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-SX3L6NKR.js";
11
+ } from "./chunk-OSRFCVBT.js";
12
12
  import "./chunk-EGWK6SRQ.js";
13
13
  import "./chunk-TFCNKBRC.js";
14
14
  import "./chunk-U73SABXK.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  installCompletions,
3
3
  uninstallCompletions
4
- } from "./chunk-YXRFUYA6.js";
4
+ } from "./chunk-NQT77IB7.js";
5
5
 
6
6
  // src/commands/setup-skill.ts
7
7
  import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, readFileSync as readFileSync3, rmSync } from "fs";
@@ -659,20 +659,65 @@ takedowns?", reach for \`orgs list\` \u2014 it's the only command that exposes
659
659
  service flags across multiple orgs in one call. Run it in \`--json\` mode
660
660
  and summarize patterns by service or by subscription tier.
661
661
 
662
- ### \`metrics summary | found | breakdown\` \u2014 Org metrics for spike/drop analysis
662
+ ### \`metrics summary | found | breakdown | organization\` \u2014 Org metrics for spike/drop analysis
663
663
 
664
664
  \`\`\`bash
665
- chainpatrol --json metrics summary --org <slug> --this-week
666
- chainpatrol --json metrics breakdown --org <slug> --by day --this-week
667
- chainpatrol --json metrics found --org <slug> --from <YYYY-MM-DD> --to <YYYY-MM-DD>
665
+ chainpatrol --json metrics summary --org <slug> # defaults to last 3 months
666
+ chainpatrol --json metrics summary --org <slug> --this-week
667
+ chainpatrol --json metrics breakdown --org <slug> --by day --this-week
668
+ chainpatrol --json metrics found --org <slug> --from <YYYY-MM-DD> --to <YYYY-MM-DD>
669
+ chainpatrol --json metrics organization --org <slug> # defaults to last 3 months
668
670
  \`\`\`
669
671
 
672
+ **Always operate on a bounded window.** When no \`--from\`/\`--to\`/\`--this-week\`
673
+ is passed, every metrics subcommand defaults to the trailing **last 3 months**
674
+ ending now. The default exists because unbounded org-wide aggregates over
675
+ multi-year history routinely time out at the platform layer (Vercel's
676
+ 30s function cap), which surfaces to clients as a 503. Stick to the default,
677
+ or pass an explicit narrower window \u2014 don't try to bypass the default by
678
+ guessing wide \`--from\` values.
679
+
680
+ The resolved range is echoed back in every output format so the user can
681
+ see exactly what they got:
682
+
683
+ - JSON: \`{ "range": { "startDate": "...", "endDate": "...", "label": "last 3 months" } }\`
684
+ - Markdown / human: the header line includes the label, e.g.
685
+ \`Organization metrics for acme \u2014 last 3 months\`, followed by
686
+ \`Range: <startDate> \u2192 <endDate>\`.
687
+
688
+ When reporting numbers to the user (especially averages and rates),
689
+ **state the window explicitly** \u2014 say "averaged over the last 3 months"
690
+ rather than just quoting a number, since the same prompt phrased
691
+ differently can pick a different window.
692
+
670
693
  \`breakdown\` is the one you usually want for healthchecks: it returns a
671
694
  time series (by day or week) of reports, new threats, watchlisted threats,
672
695
  and takedowns filed/completed. Compare the latest period against a prior
673
696
  window to spot the **spike** or **drop** signals described in the manual
674
697
  HealthCheck Guide. \`summary\` returns a single window total; \`found\` is
675
- oriented around when threats were first discovered.
698
+ oriented around when threats were first discovered; \`organization\` is
699
+ the full customer-facing dashboard slice (reports, new threats,
700
+ watchlisted, takedowns filed/completed, plus per-type and per-day
701
+ breakdowns).
702
+
703
+ #### "Across all orgs" via an API key \u2014 what's actually possible
704
+
705
+ A ChainPatrol API key is scoped to a single organization. The
706
+ \`/organization/metrics\` endpoint derives the org from the key, so
707
+ **there is no way to fetch metrics for multiple orgs with one API key**.
708
+ If the user asks for "averages across all orgs":
709
+
710
+ 1. If they're authenticated with a user session, list accessible orgs
711
+ first (\`chainpatrol --json orgs list\`) and then call
712
+ \`metrics organization\` once per org **serially** (concurrent
713
+ fan-out across many orgs is what triggers 503/throttling on the
714
+ metrics endpoint).
715
+ 2. If they're using a single API key, explain that the key only
716
+ covers one org \u2014 they need either session auth or one key per
717
+ org, not a loop with the same key.
718
+ 3. Whatever window you choose, **make it explicit** in your reply
719
+ ("last 3 months", "last 7 days", etc) \u2014 never report an average
720
+ without naming the window it was computed over.
676
721
 
677
722
  ### \`presets list | run\` \u2014 Packaged workflows for common jobs
678
723
 
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-VFT3TD3E.js";
9
9
  import {
10
10
  createApiClient
11
- } from "./chunk-SX3L6NKR.js";
11
+ } from "./chunk-OSRFCVBT.js";
12
12
  import {
13
13
  DateTime
14
14
  } from "./chunk-TFCNKBRC.js";
@@ -16,13 +16,16 @@ _chainpatrol() {
16
16
  commands=(
17
17
  'login:Authenticate with ChainPatrol'
18
18
  'logout:Clear stored credentials'
19
- 'asset:Check asset status against ChainPatrol'
19
+ 'whoami:Show the current authenticated identity'
20
+ 'asset:Check or list assets against ChainPatrol'
20
21
  'configs:Manage detection configs'
21
- 'detections:Validate and run detection configs'
22
+ 'detections:Validate, run, list, update detection configs and results'
22
23
  'metrics:Query organization metrics'
23
- 'reports:Create and list reports from terminal'
24
+ 'reports:Create, list, search reports from terminal'
24
25
  'queues:Snapshot operations queues'
25
26
  'takedowns:List individual takedown records'
27
+ 'threats:List confirmed threats blocked by ChainPatrol'
28
+ 'orgs:List organizations, org assets, and asset groups'
26
29
  'presets:Run saved workflows'
27
30
  'setup:Install Claude Code skill and shell completions'
28
31
  'uninstall:Remove Claude Code skill and shell completions'
@@ -60,7 +63,10 @@ _chainpatrol() {
60
63
  case "\${words[2]}" in
61
64
  asset)
62
65
  local -a asset_subcommands
63
- asset_subcommands=('check:Check asset status against ChainPatrol')
66
+ asset_subcommands=(
67
+ 'check:Check asset status against ChainPatrol'
68
+ 'list:List assets in the global ChainPatrol blocklist'
69
+ )
64
70
  _describe 'subcommand' asset_subcommands
65
71
  ;;
66
72
  configs)
@@ -75,6 +81,7 @@ _chainpatrol() {
75
81
  'validate:Validate detection configs'
76
82
  'drift:Show detection drift signals'
77
83
  'run:Run detection configs'
84
+ 'list:List threat detection results'
78
85
  'configs:Manage detection configs'
79
86
  )
80
87
  _describe 'subcommand' detections_subcommands
@@ -94,6 +101,7 @@ _chainpatrol() {
94
101
  reports_subcommands=(
95
102
  'create:Create a new report'
96
103
  'list:List organization reports'
104
+ 'search:Search reports by asset contents'
97
105
  )
98
106
  _describe 'subcommand' reports_subcommands
99
107
  ;;
@@ -107,6 +115,20 @@ _chainpatrol() {
107
115
  takedowns_subcommands=('list:List individual takedown records')
108
116
  _describe 'subcommand' takedowns_subcommands
109
117
  ;;
118
+ threats)
119
+ local -a threats_subcommands
120
+ threats_subcommands=('list:List confirmed threats')
121
+ _describe 'subcommand' threats_subcommands
122
+ ;;
123
+ orgs)
124
+ local -a orgs_subcommands
125
+ orgs_subcommands=(
126
+ 'list:List organizations'
127
+ 'assets:Manage organization assets'
128
+ 'asset-groups:Manage organization asset groups'
129
+ )
130
+ _describe 'subcommand' orgs_subcommands
131
+ ;;
110
132
  presets)
111
133
  local -a presets_subcommands
112
134
  presets_subcommands=(
@@ -131,7 +153,7 @@ var BASH_COMPLETION = `_chainpatrol() {
131
153
  COMPREPLY=()
132
154
  cur="\${COMP_WORDS[COMP_CWORD]}"
133
155
  prev="\${COMP_WORDS[COMP_CWORD-1]}"
134
- commands="login logout asset configs detections metrics reports queues takedowns presets setup uninstall completions help"
156
+ commands="login logout whoami asset configs detections metrics reports queues takedowns threats orgs presets setup uninstall completions help"
135
157
 
136
158
  case "\${prev}" in
137
159
  chainpatrol)
@@ -139,7 +161,7 @@ var BASH_COMPLETION = `_chainpatrol() {
139
161
  return 0
140
162
  ;;
141
163
  asset)
142
- COMPREPLY=( $(compgen -W "check" -- "\${cur}") )
164
+ COMPREPLY=( $(compgen -W "check list" -- "\${cur}") )
143
165
  return 0
144
166
  ;;
145
167
  configs)
@@ -147,7 +169,7 @@ var BASH_COMPLETION = `_chainpatrol() {
147
169
  return 0
148
170
  ;;
149
171
  detections)
150
- COMPREPLY=( $(compgen -W "healthcheck validate drift run configs" -- "\${cur}") )
172
+ COMPREPLY=( $(compgen -W "healthcheck validate drift run list configs" -- "\${cur}") )
151
173
  return 0
152
174
  ;;
153
175
  metrics)
@@ -155,7 +177,7 @@ var BASH_COMPLETION = `_chainpatrol() {
155
177
  return 0
156
178
  ;;
157
179
  reports)
158
- COMPREPLY=( $(compgen -W "create list" -- "\${cur}") )
180
+ COMPREPLY=( $(compgen -W "create list search" -- "\${cur}") )
159
181
  return 0
160
182
  ;;
161
183
  queues)
@@ -166,6 +188,26 @@ var BASH_COMPLETION = `_chainpatrol() {
166
188
  COMPREPLY=( $(compgen -W "list" -- "\${cur}") )
167
189
  return 0
168
190
  ;;
191
+ threats)
192
+ COMPREPLY=( $(compgen -W "list" -- "\${cur}") )
193
+ return 0
194
+ ;;
195
+ orgs)
196
+ COMPREPLY=( $(compgen -W "list assets asset-groups" -- "\${cur}") )
197
+ return 0
198
+ ;;
199
+ assets)
200
+ if [[ "\${COMP_WORDS[COMP_CWORD-2]}" == "orgs" ]]; then
201
+ COMPREPLY=( $(compgen -W "list" -- "\${cur}") )
202
+ return 0
203
+ fi
204
+ ;;
205
+ asset-groups)
206
+ if [[ "\${COMP_WORDS[COMP_CWORD-2]}" == "orgs" ]]; then
207
+ COMPREPLY=( $(compgen -W "list" -- "\${cur}") )
208
+ return 0
209
+ fi
210
+ ;;
169
211
  presets)
170
212
  COMPREPLY=( $(compgen -W "list run" -- "\${cur}") )
171
213
  return 0
@@ -20,6 +20,12 @@ function parseIsoDate(value) {
20
20
  function parseIsoDateString(value) {
21
21
  return parseIsoDate(value)?.toISOString();
22
22
  }
23
+ var REPORT_REVIEW_DECISIONS = ["APPROVE", "REJECT", "SKIP", "ESCALATE"];
24
+ var REPORT_STATUSES = ["TODO", "IN_PROGRESS", "CLOSED"];
25
+ var DETECTION_CONFIDENCE_LEVELS = ["none", "low", "medium", "high"];
26
+ var DETECTION_REPORTED_FILTERS = ["reported", "not_reported"];
27
+ var LIVENESS_FILTER_VALUES = ["ALIVE", "DEAD", "UNKNOWN"];
28
+ var WATCHLIST_FILTER_VALUES = ["ENABLED", "DISABLED"];
23
29
  var TAKEDOWN_STATUSES = [
24
30
  "TODO",
25
31
  "IN_PROGRESS",
@@ -35,7 +41,9 @@ var TAKEDOWN_SORT_KEYS = [
35
41
  "updatedAt",
36
42
  "createdAt",
37
43
  "takedownStatus",
38
- "takedownUpdatedAt"
44
+ "takedownUpdatedAt",
45
+ "assigneeId",
46
+ "brandId"
39
47
  ];
40
48
  var REQUEST_TIMEOUT_MS = 3e4;
41
49
  function defaultGetCredential() {
@@ -210,7 +218,19 @@ function createApiClient(options) {
210
218
  cursor: input.cursor,
211
219
  status: input.status,
212
220
  searchQuery: input.searchQuery,
213
- reportedByCustomer: input.reportedByCustomer
221
+ reporterQuery: input.reporterQuery,
222
+ reportedByCustomer: input.reportedByCustomer,
223
+ excludeAutomation: input.excludeAutomation,
224
+ onlyRejected: input.onlyRejected,
225
+ reviewStatuses: input.reviewStatuses?.length ? input.reviewStatuses : void 0,
226
+ assetTypes: input.assetTypes?.length ? input.assetTypes : void 0,
227
+ brandIds: input.brandIds?.length ? input.brandIds : void 0,
228
+ countryCodes: input.countryCodes?.length ? input.countryCodes : void 0,
229
+ reviewedByUserId: input.reviewedByUserId,
230
+ startDate: parseIsoDateString(input.startDate),
231
+ endDate: parseIsoDateString(input.endDate),
232
+ updatedAtStartDate: parseIsoDateString(input.updatedAtStartDate),
233
+ updatedAtEndDate: parseIsoDateString(input.updatedAtEndDate)
214
234
  });
215
235
  },
216
236
  listTakedowns(input) {
@@ -222,6 +242,12 @@ function createApiClient(options) {
222
242
  assetType: input.assetType,
223
243
  takedownStatus: input.takedownStatus,
224
244
  livenessStatus: input.livenessStatus,
245
+ brandIds: input.brandIds?.length ? input.brandIds : void 0,
246
+ assigneeIds: input.assigneeIds?.length ? input.assigneeIds : void 0,
247
+ startedAtStartDate: parseIsoDateString(input.startedAtStartDate),
248
+ startedAtEndDate: parseIsoDateString(input.startedAtEndDate),
249
+ hideAutomatedTakedowns: input.hideAutomatedTakedowns,
250
+ hideAutomatedLivenessChecks: input.hideAutomatedLivenessChecks,
225
251
  sorting: input.sorting,
226
252
  per_page: input.perPage,
227
253
  next_page: input.nextPage
@@ -243,11 +269,112 @@ function createApiClient(options) {
243
269
  },
244
270
  getUserOrgs(input) {
245
271
  return request("/user/orgs", input);
272
+ },
273
+ listAssets(input) {
274
+ return request("/asset/list", {
275
+ type: input.type,
276
+ status: input.status,
277
+ startDate: parseIsoDateString(input.startDate),
278
+ endDate: parseIsoDateString(input.endDate),
279
+ per_page: input.perPage,
280
+ next_page: input.nextPage
281
+ });
282
+ },
283
+ listThreats(input) {
284
+ return request("/threats/list", {
285
+ query: input.query,
286
+ startDate: parseIsoDateString(input.startDate),
287
+ endDate: parseIsoDateString(input.endDate),
288
+ assetType: input.assetType,
289
+ sorting: input.sorting,
290
+ per_page: input.perPage,
291
+ next_page: input.nextPage
292
+ });
293
+ },
294
+ listDetections(input) {
295
+ const filters = [];
296
+ if (input.sources?.length) {
297
+ filters.push({ property: "source", operator: "in", value: input.sources });
298
+ }
299
+ if (input.confidence?.length) {
300
+ filters.push({ property: "confidence", operator: "in", value: input.confidence });
301
+ }
302
+ if (input.assetStatus?.length) {
303
+ filters.push({
304
+ property: "assetStatus",
305
+ operator: "in",
306
+ value: input.assetStatus
307
+ });
308
+ }
309
+ if (input.assetType?.length) {
310
+ filters.push({ property: "assetType", operator: "in", value: input.assetType });
311
+ }
312
+ if (input.brandIds?.length) {
313
+ filters.push({ property: "brand", operator: "in", value: input.brandIds });
314
+ }
315
+ if (input.liveness?.length) {
316
+ filters.push({ property: "liveness", operator: "in", value: input.liveness });
317
+ }
318
+ if (input.watchlist?.length) {
319
+ filters.push({ property: "watchlist", operator: "in", value: input.watchlist });
320
+ }
321
+ if (input.reported?.length) {
322
+ filters.push({ property: "reported", operator: "in", value: input.reported });
323
+ }
324
+ if (input.countryCodes?.length) {
325
+ filters.push({
326
+ property: "countryCode",
327
+ operator: "in",
328
+ value: input.countryCodes
329
+ });
330
+ }
331
+ if (input.onlyDeleted) {
332
+ filters.push({ property: "deleted", operator: "in", value: ["deleted"] });
333
+ }
334
+ return request("/detection/list", {
335
+ slug: input.slug,
336
+ cursor: input.cursor,
337
+ limit: input.limit,
338
+ query: input.query,
339
+ startDate: parseIsoDate(input.startDate),
340
+ endDate: parseIsoDate(input.endDate),
341
+ filters: filters.length > 0 ? filters : void 0
342
+ });
343
+ },
344
+ searchReports(input) {
345
+ return request("/reports/search", input);
346
+ },
347
+ listOrganizationAssets(input) {
348
+ return requestGet("/organization/assets", {
349
+ type: input.type,
350
+ groupId: input.groupId !== void 0 ? String(input.groupId) : void 0,
351
+ query: input.query,
352
+ per_page: input.perPage !== void 0 ? String(input.perPage) : void 0,
353
+ next_page: input.nextPage
354
+ });
355
+ },
356
+ listOrganizationAssetGroups() {
357
+ return requestGet(
358
+ "/organization/asset-groups",
359
+ {}
360
+ );
361
+ },
362
+ getCurrentUser() {
363
+ return request("/user/me", {});
364
+ },
365
+ validateApiKey() {
366
+ return requestGet("/validate", {});
246
367
  }
247
368
  };
248
369
  }
249
370
 
250
371
  export {
372
+ REPORT_REVIEW_DECISIONS,
373
+ REPORT_STATUSES,
374
+ DETECTION_CONFIDENCE_LEVELS,
375
+ DETECTION_REPORTED_FILTERS,
376
+ LIVENESS_FILTER_VALUES,
377
+ WATCHLIST_FILTER_VALUES,
251
378
  TAKEDOWN_STATUSES,
252
379
  LIVENESS_STATUSES,
253
380
  TAKEDOWN_SORT_KEYS,
@@ -0,0 +1,66 @@
1
+ import {
2
+ DateTime
3
+ } from "./chunk-TFCNKBRC.js";
4
+
5
+ // src/lib/date-range.ts
6
+ var DEFAULT_RANGE_MONTHS = 3;
7
+ var DEFAULT_RANGE_LABEL = `last ${DEFAULT_RANGE_MONTHS} months`;
8
+ function customLabel(start, end) {
9
+ const startIso = start.toUTC().toISODate();
10
+ const endIso = end.toUTC().toISODate();
11
+ return `custom range (${startIso} \u2192 ${endIso})`;
12
+ }
13
+ function resolveDateRange({
14
+ from,
15
+ to,
16
+ thisWeek
17
+ }) {
18
+ if (from && to) {
19
+ const start2 = DateTime.fromISO(from).toUTC();
20
+ const end = DateTime.fromISO(to).toUTC();
21
+ return {
22
+ startDate: start2.toISO() ?? from,
23
+ endDate: end.toISO() ?? to,
24
+ label: customLabel(start2, end)
25
+ };
26
+ }
27
+ if (from && !to) {
28
+ const now2 = DateTime.now().toUTC();
29
+ const start2 = DateTime.fromISO(from).toUTC();
30
+ return {
31
+ startDate: start2.toISO() ?? from,
32
+ endDate: now2.toISO() ?? "",
33
+ label: customLabel(start2, now2)
34
+ };
35
+ }
36
+ if (!from && to) {
37
+ const end = DateTime.fromISO(to).toUTC();
38
+ const start2 = end.minus({ days: 7 });
39
+ return {
40
+ startDate: start2.toISO() ?? "",
41
+ endDate: end.toISO() ?? to,
42
+ label: customLabel(start2, end)
43
+ };
44
+ }
45
+ if (thisWeek) {
46
+ const now2 = DateTime.now().toUTC();
47
+ const start2 = now2.startOf("week");
48
+ const end = now2.endOf("week");
49
+ return {
50
+ startDate: start2.toISO() ?? now2.minus({ days: 7 }).toISO() ?? "",
51
+ endDate: end.toISO() ?? now2.toISO() ?? "",
52
+ label: "this week"
53
+ };
54
+ }
55
+ const now = DateTime.now().toUTC();
56
+ const start = now.minus({ months: DEFAULT_RANGE_MONTHS });
57
+ return {
58
+ startDate: start.toISO() ?? "",
59
+ endDate: now.toISO() ?? "",
60
+ label: DEFAULT_RANGE_LABEL
61
+ };
62
+ }
63
+
64
+ export {
65
+ resolveDateRange
66
+ };