@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.
- package/CHANGELOG.md +70 -0
- package/dist/{breakdown-MM5GSZKV.js → breakdown-B6QUGYI6.js} +21 -6
- package/dist/{check-GDKUHVQI.js → check-P5JJJNEX.js} +1 -1
- package/dist/{chunk-EPKNZRX6.js → chunk-BQDMAEQU.js} +51 -6
- package/dist/{chunk-37KYJWB3.js → chunk-DJVB73FL.js} +1 -1
- package/dist/{chunk-YXRFUYA6.js → chunk-NQT77IB7.js} +50 -8
- package/dist/{chunk-SX3L6NKR.js → chunk-OSRFCVBT.js} +129 -2
- package/dist/chunk-S37VFIZY.js +66 -0
- package/dist/cli.js +411 -86
- package/dist/{completions-62OW3B3Y.js → completions-6C6KG5DH.js} +1 -1
- package/dist/{configs-update-7X7657PB.js → configs-update-3ZVXGADV.js} +1 -1
- package/dist/{create-FL4QQTPN.js → create-DFH2G7RH.js} +1 -1
- package/dist/{drift-JKBHWWFU.js → drift-T74V2C3J.js} +1 -1
- package/dist/found-NXAWEIEK.js +59 -0
- package/dist/{healthcheck-EVQVPGWW.js → healthcheck-HZYEIIOR.js} +1 -1
- package/dist/{list-BLNIE4GL.js → list-23QQYAV5.js} +1 -1
- package/dist/list-EIVPGMWJ.js +82 -0
- package/dist/list-I7SBGA52.js +50 -0
- package/dist/{list-5DN6X3DP.js → list-IYJBKE2F.js} +1 -1
- package/dist/list-PBAXQSL5.js +85 -0
- package/dist/list-QUFY4IP7.js +146 -0
- package/dist/{list-JPG2ZSR4.js → list-WJQT2XLE.js} +7 -1
- package/dist/{list-ULHPOUJV.js → list-WX5G3IOF.js} +2 -2
- package/dist/list-YCT6DYDI.js +89 -0
- package/dist/{list-XDGU6SJQ.js → list-YRJPN4PI.js} +1 -1
- package/dist/{list-E5XNR2YG.js → list-ZFPML3ZR.js} +47 -3
- package/dist/{list-json-R2MIXADX.js → list-json-T2Z7NV7G.js} +1 -1
- package/dist/{organization-MJRKWC4Z.js → organization-GS5LFIWO.js} +19 -6
- package/dist/{run-EUVRC72M.js → run-BHEXWBAS.js} +2 -2
- package/dist/{run-2YZZGZYN.js → run-CJGN6TX4.js} +1 -1
- package/dist/{run-5E5EC3MP.js → run-MSO6IXEV.js} +1 -1
- package/dist/search-WPSKQGUS.js +71 -0
- package/dist/{setup-skill-HAENFIFQ.js → setup-skill-TPMTULHJ.js} +2 -2
- package/dist/{snapshot-3FUJICJJ.js → snapshot-ZWAHEG64.js} +1 -1
- package/dist/{summary-RVYQUKWV.js → summary-CV657J5V.js} +19 -6
- package/dist/{validate-UOVKEAJM.js → validate-SM5DD7I2.js} +1 -1
- package/dist/whoami-DH5HVLFN.js +69 -0
- package/package.json +1 -1
- 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-
|
|
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:
|
|
19
|
-
endDate:
|
|
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(
|
|
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}`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
installCompletions,
|
|
3
3
|
uninstallCompletions
|
|
4
|
-
} from "./chunk-
|
|
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
|
|
666
|
-
chainpatrol --json metrics
|
|
667
|
-
chainpatrol --json metrics
|
|
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
|
|
|
@@ -16,13 +16,16 @@ _chainpatrol() {
|
|
|
16
16
|
commands=(
|
|
17
17
|
'login:Authenticate with ChainPatrol'
|
|
18
18
|
'logout:Clear stored credentials'
|
|
19
|
-
'
|
|
19
|
+
'whoami:Show the current authenticated identity'
|
|
20
|
+
'asset:Check or list assets against ChainPatrol'
|
|
20
21
|
'configs:Manage detection configs'
|
|
21
|
-
'detections:Validate
|
|
22
|
+
'detections:Validate, run, list, update detection configs and results'
|
|
22
23
|
'metrics:Query organization metrics'
|
|
23
|
-
'reports:Create
|
|
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=(
|
|
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
|
-
|
|
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
|
+
};
|