@vigilbase/cli 0.2.0 → 0.2.2

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 (235) hide show
  1. package/CLOUDFLARE.md +9 -12
  2. package/COMMANDS.md +192 -111
  3. package/LOCAL.md +77 -84
  4. package/ONE.md +5 -6
  5. package/README.md +349 -173
  6. package/SECURITY.md +6 -4
  7. package/dist/auth/device-auth.d.ts +0 -1
  8. package/dist/auth/device-auth.js +6 -5
  9. package/dist/auth/index.d.ts +1 -2
  10. package/dist/auth/index.js +1 -2
  11. package/dist/auth/provider.d.ts +1 -1
  12. package/dist/auth/provider.js +16 -7
  13. package/dist/auth/refresh.d.ts +23 -4
  14. package/dist/auth/refresh.js +78 -22
  15. package/dist/auth/store.d.ts +78 -4
  16. package/dist/auth/store.js +385 -74
  17. package/dist/auth/token-metadata.d.ts +0 -1
  18. package/dist/auth/token-metadata.js +0 -1
  19. package/dist/auth/types.d.ts +0 -1
  20. package/dist/auth/types.js +0 -1
  21. package/dist/bin.d.ts +0 -1
  22. package/dist/bin.js +0 -1
  23. package/dist/cli.d.ts +4 -2
  24. package/dist/cli.js +13 -11
  25. package/dist/commands/account.d.ts +0 -1
  26. package/dist/commands/account.js +1 -2
  27. package/dist/commands/auth.d.ts +0 -1
  28. package/dist/commands/auth.js +71 -22
  29. package/dist/commands/billing.d.ts +0 -1
  30. package/dist/commands/billing.js +0 -1
  31. package/dist/commands/cloudflare.d.ts +1 -2
  32. package/dist/commands/cloudflare.js +14 -9
  33. package/dist/commands/helpers.d.ts +0 -1
  34. package/dist/commands/helpers.js +0 -1
  35. package/dist/commands/index.d.ts +0 -1
  36. package/dist/commands/index.js +0 -1
  37. package/dist/commands/legacy-validation.d.ts +7 -2
  38. package/dist/commands/legacy-validation.js +15 -3
  39. package/dist/commands/local.d.ts +6 -1
  40. package/dist/commands/local.js +36 -12
  41. package/dist/commands/one.d.ts +0 -1
  42. package/dist/commands/one.js +39 -13
  43. package/dist/commands/public-tools.d.ts +0 -1
  44. package/dist/commands/public-tools.js +63 -29
  45. package/dist/commands/runs.d.ts +0 -1
  46. package/dist/commands/runs.js +1 -2
  47. package/dist/commands/security.d.ts +1 -2
  48. package/dist/commands/security.js +34 -23
  49. package/dist/commands/watchdog.d.ts +0 -1
  50. package/dist/commands/watchdog.js +0 -1
  51. package/dist/index.d.ts +2 -3
  52. package/dist/index.js +1 -2
  53. package/dist/lib/banner.d.ts +0 -1
  54. package/dist/lib/banner.js +0 -1
  55. package/dist/lib/client.d.ts +9 -2
  56. package/dist/lib/client.js +49 -20
  57. package/dist/lib/cloudflare-client.d.ts +0 -1
  58. package/dist/lib/cloudflare-client.js +1 -2
  59. package/dist/lib/config.d.ts +16 -3
  60. package/dist/lib/config.js +41 -14
  61. package/dist/lib/format.d.ts +2 -1
  62. package/dist/lib/format.js +19 -8
  63. package/dist/lib/help.d.ts +4 -2
  64. package/dist/lib/help.js +72 -23
  65. package/dist/lib/network.d.ts +10 -1
  66. package/dist/lib/network.js +31 -4
  67. package/dist/lib/one-client.d.ts +4 -1
  68. package/dist/lib/one-client.js +9 -3
  69. package/dist/lib/one-error-hints.d.ts +19 -0
  70. package/dist/lib/one-error-hints.js +47 -0
  71. package/dist/lib/one-operations.d.ts +0 -1
  72. package/dist/lib/one-operations.js +0 -1
  73. package/dist/lib/open-url.d.ts +0 -1
  74. package/dist/lib/open-url.js +0 -1
  75. package/dist/lib/platform.d.ts +2 -0
  76. package/dist/lib/platform.js +4 -0
  77. package/dist/lib/progress.d.ts +0 -1
  78. package/dist/lib/progress.js +0 -1
  79. package/dist/lib/security-client.d.ts +0 -1
  80. package/dist/lib/security-client.js +0 -1
  81. package/dist/lib/skill-fetch.d.ts +0 -1
  82. package/dist/lib/skill-fetch.js +0 -1
  83. package/dist/lib/system-trust.d.ts +0 -1
  84. package/dist/lib/system-trust.js +0 -1
  85. package/dist/lib/tui.d.ts +0 -1
  86. package/dist/lib/tui.js +0 -1
  87. package/dist/local/cloudflare-checkup/cf/allowlist.d.ts +0 -1
  88. package/dist/local/cloudflare-checkup/cf/allowlist.js +0 -1
  89. package/dist/local/cloudflare-checkup/cf/auth-lifecycle.d.ts +0 -1
  90. package/dist/local/cloudflare-checkup/cf/auth-lifecycle.js +0 -1
  91. package/dist/local/cloudflare-checkup/cf/child-env.d.ts +0 -1
  92. package/dist/local/cloudflare-checkup/cf/child-env.js +0 -1
  93. package/dist/local/cloudflare-checkup/cf/install.d.ts +0 -1
  94. package/dist/local/cloudflare-checkup/cf/install.js +0 -1
  95. package/dist/local/cloudflare-checkup/cf/locate.d.ts +0 -1
  96. package/dist/local/cloudflare-checkup/cf/locate.js +0 -1
  97. package/dist/local/cloudflare-checkup/cf/run-cf.d.ts +0 -1
  98. package/dist/local/cloudflare-checkup/cf/run-cf.js +0 -1
  99. package/dist/local/cloudflare-checkup/collector.d.ts +0 -1
  100. package/dist/local/cloudflare-checkup/collector.js +0 -1
  101. package/dist/local/cloudflare-checkup/contract.d.ts +14 -3
  102. package/dist/local/cloudflare-checkup/contract.js +9 -3
  103. package/dist/local/cloudflare-checkup/email-verification.d.ts +0 -1
  104. package/dist/local/cloudflare-checkup/email-verification.js +0 -1
  105. package/dist/local/cloudflare-checkup/errors.d.ts +4 -1
  106. package/dist/local/cloudflare-checkup/errors.js +8 -2
  107. package/dist/local/cloudflare-checkup/output.d.ts +0 -1
  108. package/dist/local/cloudflare-checkup/output.js +0 -1
  109. package/dist/local/cloudflare-checkup/prompts.d.ts +0 -1
  110. package/dist/local/cloudflare-checkup/prompts.js +0 -1
  111. package/dist/local/cloudflare-checkup/rate-budget.d.ts +0 -1
  112. package/dist/local/cloudflare-checkup/rate-budget.js +0 -1
  113. package/dist/local/cloudflare-checkup/snapshot-file.d.ts +0 -1
  114. package/dist/local/cloudflare-checkup/snapshot-file.js +5 -4
  115. package/dist/local/cloudflare-checkup/submit-client.d.ts +19 -5
  116. package/dist/local/cloudflare-checkup/submit-client.js +63 -17
  117. package/dist/local/cloudflare-checkup/terminal-ui.d.ts +0 -1
  118. package/dist/local/cloudflare-checkup/terminal-ui.js +0 -1
  119. package/dist/types.d.ts +25 -3
  120. package/dist/types.js +16 -1
  121. package/dist/version.d.ts +0 -1
  122. package/dist/version.js +0 -1
  123. package/package.json +5 -9
  124. package/dist/auth/device-auth.d.ts.map +0 -1
  125. package/dist/auth/device-auth.js.map +0 -1
  126. package/dist/auth/index.d.ts.map +0 -1
  127. package/dist/auth/index.js.map +0 -1
  128. package/dist/auth/provider.d.ts.map +0 -1
  129. package/dist/auth/provider.js.map +0 -1
  130. package/dist/auth/refresh.d.ts.map +0 -1
  131. package/dist/auth/refresh.js.map +0 -1
  132. package/dist/auth/store.d.ts.map +0 -1
  133. package/dist/auth/store.js.map +0 -1
  134. package/dist/auth/token-metadata.d.ts.map +0 -1
  135. package/dist/auth/token-metadata.js.map +0 -1
  136. package/dist/auth/types.d.ts.map +0 -1
  137. package/dist/auth/types.js.map +0 -1
  138. package/dist/bin.d.ts.map +0 -1
  139. package/dist/bin.js.map +0 -1
  140. package/dist/cli.d.ts.map +0 -1
  141. package/dist/cli.js.map +0 -1
  142. package/dist/commands/account.d.ts.map +0 -1
  143. package/dist/commands/account.js.map +0 -1
  144. package/dist/commands/auth.d.ts.map +0 -1
  145. package/dist/commands/auth.js.map +0 -1
  146. package/dist/commands/billing.d.ts.map +0 -1
  147. package/dist/commands/billing.js.map +0 -1
  148. package/dist/commands/cloudflare.d.ts.map +0 -1
  149. package/dist/commands/cloudflare.js.map +0 -1
  150. package/dist/commands/helpers.d.ts.map +0 -1
  151. package/dist/commands/helpers.js.map +0 -1
  152. package/dist/commands/index.d.ts.map +0 -1
  153. package/dist/commands/index.js.map +0 -1
  154. package/dist/commands/legacy-validation.d.ts.map +0 -1
  155. package/dist/commands/legacy-validation.js.map +0 -1
  156. package/dist/commands/local.d.ts.map +0 -1
  157. package/dist/commands/local.js.map +0 -1
  158. package/dist/commands/one.d.ts.map +0 -1
  159. package/dist/commands/one.js.map +0 -1
  160. package/dist/commands/public-tools.d.ts.map +0 -1
  161. package/dist/commands/public-tools.js.map +0 -1
  162. package/dist/commands/runs.d.ts.map +0 -1
  163. package/dist/commands/runs.js.map +0 -1
  164. package/dist/commands/security.d.ts.map +0 -1
  165. package/dist/commands/security.js.map +0 -1
  166. package/dist/commands/watchdog.d.ts.map +0 -1
  167. package/dist/commands/watchdog.js.map +0 -1
  168. package/dist/index.d.ts.map +0 -1
  169. package/dist/index.js.map +0 -1
  170. package/dist/lib/banner.d.ts.map +0 -1
  171. package/dist/lib/banner.js.map +0 -1
  172. package/dist/lib/client.d.ts.map +0 -1
  173. package/dist/lib/client.js.map +0 -1
  174. package/dist/lib/cloudflare-client.d.ts.map +0 -1
  175. package/dist/lib/cloudflare-client.js.map +0 -1
  176. package/dist/lib/config.d.ts.map +0 -1
  177. package/dist/lib/config.js.map +0 -1
  178. package/dist/lib/format.d.ts.map +0 -1
  179. package/dist/lib/format.js.map +0 -1
  180. package/dist/lib/help.d.ts.map +0 -1
  181. package/dist/lib/help.js.map +0 -1
  182. package/dist/lib/network.d.ts.map +0 -1
  183. package/dist/lib/network.js.map +0 -1
  184. package/dist/lib/one-client.d.ts.map +0 -1
  185. package/dist/lib/one-client.js.map +0 -1
  186. package/dist/lib/one-operations.d.ts.map +0 -1
  187. package/dist/lib/one-operations.js.map +0 -1
  188. package/dist/lib/open-url.d.ts.map +0 -1
  189. package/dist/lib/open-url.js.map +0 -1
  190. package/dist/lib/progress.d.ts.map +0 -1
  191. package/dist/lib/progress.js.map +0 -1
  192. package/dist/lib/security-client.d.ts.map +0 -1
  193. package/dist/lib/security-client.js.map +0 -1
  194. package/dist/lib/skill-fetch.d.ts.map +0 -1
  195. package/dist/lib/skill-fetch.js.map +0 -1
  196. package/dist/lib/system-trust.d.ts.map +0 -1
  197. package/dist/lib/system-trust.js.map +0 -1
  198. package/dist/lib/tui.d.ts.map +0 -1
  199. package/dist/lib/tui.js.map +0 -1
  200. package/dist/local/cloudflare-checkup/cf/allowlist.d.ts.map +0 -1
  201. package/dist/local/cloudflare-checkup/cf/allowlist.js.map +0 -1
  202. package/dist/local/cloudflare-checkup/cf/auth-lifecycle.d.ts.map +0 -1
  203. package/dist/local/cloudflare-checkup/cf/auth-lifecycle.js.map +0 -1
  204. package/dist/local/cloudflare-checkup/cf/child-env.d.ts.map +0 -1
  205. package/dist/local/cloudflare-checkup/cf/child-env.js.map +0 -1
  206. package/dist/local/cloudflare-checkup/cf/install.d.ts.map +0 -1
  207. package/dist/local/cloudflare-checkup/cf/install.js.map +0 -1
  208. package/dist/local/cloudflare-checkup/cf/locate.d.ts.map +0 -1
  209. package/dist/local/cloudflare-checkup/cf/locate.js.map +0 -1
  210. package/dist/local/cloudflare-checkup/cf/run-cf.d.ts.map +0 -1
  211. package/dist/local/cloudflare-checkup/cf/run-cf.js.map +0 -1
  212. package/dist/local/cloudflare-checkup/collector.d.ts.map +0 -1
  213. package/dist/local/cloudflare-checkup/collector.js.map +0 -1
  214. package/dist/local/cloudflare-checkup/contract.d.ts.map +0 -1
  215. package/dist/local/cloudflare-checkup/contract.js.map +0 -1
  216. package/dist/local/cloudflare-checkup/email-verification.d.ts.map +0 -1
  217. package/dist/local/cloudflare-checkup/email-verification.js.map +0 -1
  218. package/dist/local/cloudflare-checkup/errors.d.ts.map +0 -1
  219. package/dist/local/cloudflare-checkup/errors.js.map +0 -1
  220. package/dist/local/cloudflare-checkup/output.d.ts.map +0 -1
  221. package/dist/local/cloudflare-checkup/output.js.map +0 -1
  222. package/dist/local/cloudflare-checkup/prompts.d.ts.map +0 -1
  223. package/dist/local/cloudflare-checkup/prompts.js.map +0 -1
  224. package/dist/local/cloudflare-checkup/rate-budget.d.ts.map +0 -1
  225. package/dist/local/cloudflare-checkup/rate-budget.js.map +0 -1
  226. package/dist/local/cloudflare-checkup/snapshot-file.d.ts.map +0 -1
  227. package/dist/local/cloudflare-checkup/snapshot-file.js.map +0 -1
  228. package/dist/local/cloudflare-checkup/submit-client.d.ts.map +0 -1
  229. package/dist/local/cloudflare-checkup/submit-client.js.map +0 -1
  230. package/dist/local/cloudflare-checkup/terminal-ui.d.ts.map +0 -1
  231. package/dist/local/cloudflare-checkup/terminal-ui.js.map +0 -1
  232. package/dist/types.d.ts.map +0 -1
  233. package/dist/types.js.map +0 -1
  234. package/dist/version.d.ts.map +0 -1
  235. package/dist/version.js.map +0 -1
@@ -1,6 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { executeOneOperation, formatOnePayload } from '../lib/one-operations.js';
3
3
  import { assertCommandFlags, ok, outputJson, requireOneClient, withSpinner } from './helpers.js';
4
+ import { missingArguments } from './legacy-validation.js';
4
5
  const regions = ['ams', 'nyc', 'lon', 'sgp', 'iad', 'sfo', 'fra', 'dub', 'tok', 'syd', 'cpt', 'gru', 'dxb', 'ewr', 'lhr', 'jnb', 'atl', 'blr', 'bom', 'cdg', 'del', 'dfw', 'hnl', 'icn', 'itm', 'lax', 'mad', 'man', 'mel', 'mex', 'mia', 'mxp', 'nrt', 'ord', 'sao', 'scl', 'sea', 'sjc', 'sto', 'tlv', 'waw', 'yto'];
5
6
  function flag(ctx, name, max = 2048) {
6
7
  const value = ctx.values[name];
@@ -26,8 +27,28 @@ function identifier(value) {
26
27
  throw new Error('An ID containing only letters, numbers, underscores, or hyphens is required.');
27
28
  return result.data;
28
29
  }
30
+ const customerSubcommands = ['show', 'summary', 'services', 'endpoints', 'contacts', 'organization', 'watchdog-targets', 'watchdog-scans', 'reports', 'investigations', 'contracts', 'billing', 'invoices', 'subscriptions', 'projects'];
31
+ /** Positional placeholders of each subcommand (as in ONE_HELP), so a missing argument is named. */
32
+ const POSITIONALS = {
33
+ customers: {
34
+ ...Object.fromEntries(customerSubcommands.map((command) => [command, '<customer-id>'])),
35
+ report: '<customer-id> <report-id>',
36
+ investigation: '<customer-id> <investigation-id>',
37
+ },
38
+ orgs: { show: '<organization-id>' },
39
+ monitoring: { metrics: '<target-id>...', targets: '<customer-id>', status: '<customer-id>', history: '<customer-id>' },
40
+ };
41
+ function positionalUsage(ctx) {
42
+ const [command] = ctx.rest;
43
+ const placeholders = POSITIONALS[ctx.command];
44
+ if (command === undefined || !placeholders || !Object.hasOwn(placeholders, command))
45
+ return undefined;
46
+ return `vigilbase ${ctx.command} ${command} ${placeholders[command]}`;
47
+ }
29
48
  function check(ctx, arity, flags = []) {
30
- if (ctx.rest.length !== arity)
49
+ if (ctx.rest.length < arity)
50
+ throw new Error(missingArguments(ctx.command, arity - ctx.rest.length, positionalUsage(ctx)));
51
+ if (ctx.rest.length > arity)
31
52
  throw new Error(`Unexpected arguments. Run \`vigilbase ${ctx.command} --help\` for usage.`);
32
53
  assertCommandFlags(ctx, flags);
33
54
  }
@@ -114,8 +135,10 @@ export function buildOneOperation(ctx) {
114
135
  return operation(fleetRoutes[command]);
115
136
  }
116
137
  if (command === 'metrics') {
117
- check(ctx, ctx.rest.length);
118
- const ids = z.array(z.string().uuid()).min(1).max(50).parse(ctx.rest.slice(1));
138
+ check(ctx, Math.max(ctx.rest.length, 2));
139
+ const ids = ctx.rest.slice(1).map(uuid);
140
+ if (ids.length > 50)
141
+ throw new Error('monitoring metrics accepts at most 50 target IDs.');
119
142
  return operation('/api/monitoring/metrics', { target_ids: [...new Set(ids)].join(',') });
120
143
  }
121
144
  if (command === 'targets' || command === 'status' || command === 'history') {
@@ -133,8 +156,11 @@ export function buildOneOperation(ctx) {
133
156
  }
134
157
  }
135
158
  if (ctx.command === 'support' && command === 'tickets') {
136
- check(ctx, ctx.rest.length === 0 ? 0 : 1, ['isAll', 'limit']);
137
- return operation('/api/support/tickets', { includeAll: ctx.values.isAll ? true : undefined, limit: integer(ctx, 'limit', 1, 100) });
159
+ check(ctx, ctx.rest.length === 0 ? 0 : 1, ['isAll', 'limit', 'customer-id']);
160
+ return operation('/api/support/tickets', {
161
+ includeAll: ctx.values.isAll ? true : undefined, limit: integer(ctx, 'limit', 1, 100),
162
+ customerId: ctx.values['customer-id'] === undefined ? undefined : uuid(ctx.values['customer-id']),
163
+ });
138
164
  }
139
165
  throw new Error(`Unknown ${ctx.command} command: ${command}. Run \`vigilbase ${ctx.command} --help\` for usage.`);
140
166
  }
@@ -153,7 +179,7 @@ export const handleOne = async (ctx) => {
153
179
  };
154
180
  export const ONE_HELP = {
155
181
  customers: `Usage: vigilbase customers <command> [--json]
156
- list List visible customers (also the default)
182
+ list List visible customers (also the default)
157
183
  show <customer-id> Full customer details
158
184
  summary <customer-id> Lightweight service/integration summary
159
185
  services <customer-id> Service records
@@ -163,7 +189,7 @@ export const ONE_HELP = {
163
189
  watchdog-targets <customer-id> Security/uptime targets
164
190
  watchdog-scans <customer-id> --limit 1..100 --offset 0..1000000 --target-id UUID
165
191
  reports <customer-id> Recon reports; --limit 1..100
166
- report <customer-id> <report-id> Recon report detail
192
+ report <customer-id> <report-id> Recon report detail
167
193
  investigations <customer-id> --limit 1..100 --cursor TEXT or --before ISO; --issue-id TEXT
168
194
  investigation <customer-id> <id> --revision 1..2147483647
169
195
  contracts <customer-id> --status draft|pending|active|expired|terminated
@@ -186,15 +212,15 @@ These commands read organization context; they do not switch the active organiza
186
212
  health Metrics backend and alerting readiness (also the default)
187
213
  probes Registered probe heartbeats (internal operators)
188
214
  probe-health Live probe health, with database fallback
189
- metrics <target-id>... Metrics for 1..50 target UUIDs
190
- targets <customer-id> Customer's monitoring targets
191
- status <customer-id> Current status; --light skips latency/SSL provider reads
192
- history <customer-id> --range 24h|7d|30d --region CODE --target-id UUID
215
+ metrics <target-id>... Metrics for 1..50 target UUIDs
216
+ targets <customer-id> Customer's monitoring targets
217
+ status <customer-id> Current status; --light skips latency/SSL provider reads
218
+ history <customer-id> --range 24h|7d|30d --region CODE --target-id UUID
193
219
  All operations require read:monitoring and the API's tenant access checks.
194
220
  History defaults to 7d. Health metadata preserves unknown, partial, and unavailable states.`,
195
- support: `Usage: vigilbase support tickets [--all] [--limit 1..100] [--json]
221
+ support: `Usage: vigilbase support tickets [--all] [--limit 1..100] [--customer-id <uuid>] [--json]
196
222
  Lists current organization's open tickets; --all includes closed tickets.
223
+ Vigilbase staff must choose the customer with --customer-id.
197
224
  The API defaults to 50 results. Requires support:access and a linked Pylon account.
198
225
  The response retains hasMore; the API does not expose cursor pagination.`,
199
226
  };
200
- //# sourceMappingURL=one.js.map
@@ -6,4 +6,3 @@ export declare const handleDescribe: CommandHandler;
6
6
  export declare const handleSkill: CommandHandler;
7
7
  export declare const handleBadge: CommandHandler;
8
8
  export declare const handleDoctor: CommandHandler;
9
- //# sourceMappingURL=public-tools.d.ts.map
@@ -1,17 +1,39 @@
1
1
  import { z } from 'zod';
2
2
  import { toolNameSchema, validateArguments } from './legacy-validation.js';
3
3
  import { NetworkError } from '../lib/network.js';
4
- import { VigilbaseApiError } from '../lib/client.js';
5
- import { getOneAccessToken, readCredentials } from '../auth/index.js';
4
+ import { PUBLIC_TOOLS_PATH, VigilbaseApiError } from '../lib/client.js';
5
+ import { getOneAccessToken, getOptionalOneAccessToken, hasUsableSignIn, readCredentials } from '../auth/index.js';
6
+ import { SignInUnsupportedError } from '../auth/store.js';
6
7
  import { formatExecuteResult, formatToolDescription, formatToolsList, } from '../lib/format.js';
7
8
  import { isOneAuthRequiredTool, isOneExecutableTool, ONE_AUTH_REQUIRED_TOOLS, resolveToolDefinition, VigilbaseOneClient, } from '../lib/one-client.js';
8
9
  import { EXIT, ok, outputJson, withSpinner, } from './helpers.js';
10
+ const ONE_SIGN_IN_REQUIRED = 'This tool needs a Vigilbase One sign-in: run `vigilbase login`.';
11
+ /**
12
+ * For --via one and auth-required tools only: any sign-in problem fails. Specific errors keep their
13
+ * message; those that don't already point to `vigilbase login` get it as their hint.
14
+ */
15
+ async function requireOneSignIn(config) {
16
+ let accessToken;
17
+ try {
18
+ accessToken = await getOneAccessToken(config);
19
+ }
20
+ catch (error) {
21
+ // Windows cannot sign in at all, so pointing to login would mislead.
22
+ if (error instanceof Error && !(error instanceof SignInUnsupportedError) && !error.message.includes('`vigilbase login`')) {
23
+ Object.assign(error, { hint: ONE_SIGN_IN_REQUIRED });
24
+ }
25
+ throw error;
26
+ }
27
+ if (!accessToken)
28
+ throw new Error(ONE_SIGN_IN_REQUIRED);
29
+ return accessToken;
30
+ }
9
31
  /** Public tools work without login. Auth-required tools need Vigilbase One. */
10
32
  export const handleList = async (ctx) => {
11
33
  validateArguments(ctx, 0);
12
34
  const catalog = await withSpinner(ctx, 'Loading tool catalog', () => ctx.publicClient.listTools());
13
- const accessToken = await getOneAccessToken(ctx.config);
14
- const authenticated = Boolean(accessToken);
35
+ // Offline: list never refreshes, so it cannot leave a refresh half-done.
36
+ const authenticated = await hasUsableSignIn(ctx.config, ctx.writer.stderr);
15
37
  if (ctx.mode === 'json') {
16
38
  outputJson(ctx, {
17
39
  ...catalog,
@@ -36,7 +58,10 @@ export const handleList = async (ctx) => {
36
58
  return ok();
37
59
  };
38
60
  export const handleRun = async (ctx) => {
39
- validateArguments(ctx, ctx.command === 'headers' || ctx.command === 'email' ? 1 : 2, ['via', 'isPublic']);
61
+ const usage = ctx.command === 'headers' ? 'vigilbase headers <url>'
62
+ : ctx.command === 'email' ? 'vigilbase email <domain>'
63
+ : 'vigilbase run <tool> <target>';
64
+ validateArguments(ctx, ctx.command === 'run' ? 2 : 1, ['via', 'isPublic'], usage);
40
65
  let toolName;
41
66
  let target;
42
67
  if (ctx.command === 'headers') {
@@ -51,11 +76,8 @@ export const handleRun = async (ctx) => {
51
76
  toolName = ctx.rest[0] ?? '';
52
77
  target = ctx.rest[1] ?? '';
53
78
  }
54
- if (!toolName || !target) {
55
- throw new Error(ctx.command === 'run'
56
- ? 'Usage: vigilbase run <tool> <target>'
57
- : `Usage: vigilbase ${ctx.command} <target>`);
58
- }
79
+ if (!toolName || !target)
80
+ throw new Error(`Usage: ${usage}`);
59
81
  toolName = toolNameSchema.parse(toolName);
60
82
  target = z.string().trim().min(1).max(2048).refine((value) => !/[\u0000-\u001f\u007f]/.test(value), 'Target must not contain control characters.').parse(target);
61
83
  const via = ctx.values.via;
@@ -65,15 +87,13 @@ export const handleRun = async (ctx) => {
65
87
  if (via && via !== 'one' && via !== 'public') {
66
88
  throw new Error('--via must be one of: public, one');
67
89
  }
68
- const accessToken = await getOneAccessToken(ctx.config);
69
90
  const forcePublic = Boolean(ctx.values.isPublic) || via === 'public';
70
91
  const forceOne = via === 'one';
71
92
  // Public tools stay free unless forced onto One. Auth-required tools need login.
93
+ // The public route is anonymous and never reads the credential store.
72
94
  const useOne = !forcePublic && (forceOne || isOneAuthRequiredTool(toolName));
73
95
  if (useOne) {
74
- if (!accessToken) {
75
- throw new Error(`Tool "${toolName}" requires Vigilbase One auth. Run \`vigilbase login\` first.`);
76
- }
96
+ const accessToken = await requireOneSignIn(ctx.config);
77
97
  if (!isOneExecutableTool(toolName)) {
78
98
  throw new Error(`Tool "${toolName}" is not executable via Vigilbase One CLI yet.`);
79
99
  }
@@ -96,7 +116,7 @@ export const handleRun = async (ctx) => {
96
116
  return result.success ? ok() : EXIT.ERROR;
97
117
  };
98
118
  export const handleDescribe = async (ctx) => {
99
- validateArguments(ctx, 1, ['isNoSkill']);
119
+ validateArguments(ctx, 1, ['isNoSkill'], 'vigilbase describe <tool>');
100
120
  toolNameSchema.parse(ctx.rest[0]);
101
121
  const toolName = ctx.rest[0];
102
122
  if (!toolName)
@@ -119,7 +139,7 @@ export const handleDescribe = async (ctx) => {
119
139
  return ok();
120
140
  };
121
141
  export const handleSkill = async (ctx) => {
122
- validateArguments(ctx, 1);
142
+ validateArguments(ctx, 1, [], 'vigilbase skill <tool>');
123
143
  toolNameSchema.parse(ctx.rest[0]);
124
144
  const toolName = ctx.rest[0];
125
145
  if (!toolName)
@@ -143,7 +163,7 @@ export const handleSkill = async (ctx) => {
143
163
  return ok();
144
164
  };
145
165
  export const handleBadge = async (ctx) => {
146
- validateArguments(ctx, 1, ['style']);
166
+ validateArguments(ctx, 1, ['style'], 'vigilbase badge <domain>');
147
167
  const domain = ctx.rest[0];
148
168
  if (!domain)
149
169
  throw new Error('Usage: vigilbase badge <domain>');
@@ -163,15 +183,21 @@ export const handleBadge = async (ctx) => {
163
183
  export const handleDoctor = async (ctx) => {
164
184
  validateArguments(ctx, 0);
165
185
  let oneCheckUrl = `${ctx.config.oneBaseUrl}/api/auth/get-session`;
166
- const [publicResult, oneResult] = await withSpinner(ctx, 'Checking public API and Vigilbase One', () => Promise.allSettled([
186
+ // A sign-in problem fails its own check, and One connectivity is then checked anonymously.
187
+ // The saved sign-in may refresh, with the configured timeout like any One command.
188
+ const signIn = getOptionalOneAccessToken(ctx.config);
189
+ const [publicResult, oneResult, signInResult] = await withSpinner(ctx, 'Checking public API and Vigilbase One', () => Promise.allSettled([
167
190
  ctx.publicClient.listTools(),
168
191
  (async () => {
169
- const accessToken = await getOneAccessToken(ctx.config);
170
- const saved = await readCredentials(ctx.config);
171
- if (accessToken && saved.version === 2)
172
- oneCheckUrl = `${saved.one.issuer}/api/auth/oauth2/userinfo`;
192
+ const { accessToken } = await signIn;
193
+ const saved = accessToken ? await readCredentials(ctx.config) : null;
194
+ // An Identity session is checked at the userinfo endpoint its issuer's discovery names.
195
+ if (saved?.version === 2)
196
+ oneCheckUrl = `${saved.one.issuer}/.well-known/openid-configuration`;
197
+ // Signed out, the check stays anonymous and never reads the credential store.
198
+ const client = new VigilbaseOneClient(ctx.config, accessToken ?? '', Boolean(accessToken));
173
199
  try {
174
- const session = await new VigilbaseOneClient(ctx.config, accessToken ?? '', true).getSession();
200
+ const session = await client.getSession();
175
201
  return { authenticated: Boolean(session.user?.id) };
176
202
  }
177
203
  catch (error) {
@@ -181,25 +207,34 @@ export const handleDoctor = async (ctx) => {
181
207
  }
182
208
  throw error;
183
209
  }
210
+ finally {
211
+ if (client.userinfoEndpoint)
212
+ oneCheckUrl = client.userinfoEndpoint;
213
+ }
184
214
  })(),
215
+ signIn.then(({ problem }) => {
216
+ if (problem)
217
+ throw new Error(problem);
218
+ }),
185
219
  ]));
186
220
  const checkResult = (result, url) => {
187
221
  if (result.status === 'fulfilled')
188
- return { ok: true, url };
222
+ return { ok: true, ...(url ? { url } : {}) };
189
223
  const error = result.reason;
190
224
  return {
191
225
  ok: false,
192
- url,
226
+ ...(url ? { url } : {}),
193
227
  error: error instanceof Error ? error.message : 'Connectivity check failed.',
194
228
  ...(error instanceof VigilbaseApiError || error instanceof NetworkError ? { status: error.status } : {}),
195
229
  ...(error instanceof NetworkError ? { code: error.code } : {}),
196
230
  };
197
231
  };
198
232
  const checks = {
199
- publicApi: checkResult(publicResult, `${ctx.config.publicBaseUrl}/api/agent/tools`),
233
+ publicApi: checkResult(publicResult, `${ctx.config.publicBaseUrl}${PUBLIC_TOOLS_PATH}`),
200
234
  one: checkResult(oneResult, oneCheckUrl),
235
+ signIn: checkResult(signInResult),
201
236
  };
202
- const isOk = checks.publicApi.ok && checks.one.ok;
237
+ const isOk = checks.publicApi.ok && checks.one.ok && checks.signIn.ok;
203
238
  const firstFailure = Object.values(checks).find((check) => !check.ok);
204
239
  const catalog = publicResult.status === 'fulfilled' ? publicResult.value : null;
205
240
  const payload = {
@@ -223,10 +258,9 @@ export const handleDoctor = async (ctx) => {
223
258
  }
224
259
  else {
225
260
  for (const [label, check] of Object.entries(checks)) {
226
- ctx.writer.stdout(`${check.ok ? 'ok' : 'fail'} ${label} ${check.url}${check.error ? ` — ${check.error}` : ''}`);
261
+ ctx.writer.stdout(`${check.ok ? 'ok' : 'fail'} ${label}${check.url ? ` ${check.url}` : ''}${check.error ? ` — ${check.error}` : ''}`);
227
262
  }
228
263
  ctx.writer.stdout(`auth=${payload.authenticated ? 'in' : 'out'} tools=${payload.tools.join(',') || 'unavailable'}`);
229
264
  }
230
265
  return isOk ? ok() : EXIT.ERROR;
231
266
  };
232
- //# sourceMappingURL=public-tools.js.map
@@ -1,3 +1,2 @@
1
1
  import { type CommandHandler } from './helpers.js';
2
2
  export declare const handleRuns: CommandHandler;
3
- //# sourceMappingURL=runs.d.ts.map
@@ -10,7 +10,7 @@ export const handleRuns = async (ctx) => {
10
10
  toolName = toolNameSchema.optional().parse(ctx.values.tool);
11
11
  }
12
12
  else if (subcommand === 'get' || subcommand === 'show') {
13
- validateArguments(ctx, 2);
13
+ validateArguments(ctx, 2, [], `vigilbase runs ${subcommand} <UUID>`);
14
14
  z.string().uuid().parse(ctx.rest[1]);
15
15
  }
16
16
  else if (z.string().uuid().safeParse(subcommand).success)
@@ -73,4 +73,3 @@ export const handleRuns = async (ctx) => {
73
73
  }
74
74
  throw new Error('Usage: vigilbase runs [list|get <id>] [--tool …] [--limit …] [--json]');
75
75
  };
76
- //# sourceMappingURL=runs.js.map
@@ -2,5 +2,4 @@ import { type SecurityRequest } from '../lib/security-client.js';
2
2
  import { type CommandContext, type CommandHandler } from './helpers.js';
3
3
  export declare function buildSecurityRequest(ctx: CommandContext): SecurityRequest;
4
4
  export declare const handleSecurity: CommandHandler;
5
- export declare const SECURITY_HELP = "vigilbase security \u2014 managed security in Vigilbase One\n\n [overview]\n incidents [list] --status --severity --attack-category\n --order-by --order-direction --limit --offset\n incidents show <id>\n incidents timeline <id> --limit --before\n incidents fabric <id> --dataset --min-weight --limit\n incidents share-links <id>\n incidents update <id> <status> --confirm [--note]\n alerts [list] --limit --asset-id --start\n alerts show <id>\n logs --limit --asset-id --provider --dataset --search\n --start --end --sort --frs-min --cursor\n audit --limit --cursor --action-prefix --outcome\n assets\n assets <allowlist|blocklist|remediation|autonomy|datasets> <asset-id>\n assets graph <asset-id> --dataset --hours --min-weight --limit\n fabric default-asset\n detections --asset-id\n providers\n connections [list]\n connections show <id>\n connections <available-assets|remediation> <id>\n connections <logpush-status|worker-stats> <connection-id> <job-id>\n analytics [overview] --metrics + time-window flags\n analytics <security-analysis|bot-activity|top-attacker-ips|bot-asns|dns-security|page-shield>\n analytics provider-events --provider --dataset --start --end\n [--asset-id --search --limit]\n zero-trust <device-health|app-tests|access|sessions|device-posture>\n zero-trust gateway <dns|http|network>\n cloudflare-account [inventory]\n cloudflare-account <audit|ingestion|posture>\n notifications [list] --limit\n notifications <settings|preferences|slack-channels>\n reports [list] --limit --offset\n reports show <id>\n reports settings\n intel quota\n intel <ip|asn|cidr|ja3|ja4> <query>\n settings <lifecycle-emails|broadcast-emails|applications>\n\nTime-window flags: --hours (1\u2013720, default 24) or --start/--end ISO timestamps;\noptional --asset-id. Apply to analytics (except provider-events), zero-trust,\nand cloudflare-account audit/ingestion/posture. Inventory has no window flags.\nLimits: list incidents/reports/audit 1\u2013100 (default 50); alerts/notifications\n1\u2013100 (default 100); timeline 1\u2013200 (default 100); logs 1\u20131000 (default 100);\nprovider-events 1\u2013500 (default 200); graph 1\u20131000 (default 200).\nOffsets: 0\u20131000000. Graph min-weight: 1\u20131000000 (default 1).\nAll: --json, --timeout <ms>, --customer-id <One customer UUID> (internal View-as).\nAll operations read data except confirmed incident status updates.\nUpdate status: acknowledged, mitigating, resolved, false_positive.\nSee SECURITY.md for every endpoint, supported value, alias, and pagination contract.\n";
6
- //# sourceMappingURL=security.d.ts.map
5
+ export declare const SECURITY_HELP = "vigilbase security \u2014 managed security in Vigilbase One\n\n [overview]\n incidents [list] --status --severity --attack-category\n --order-by --order-direction --limit --offset\n incidents show <id>\n incidents timeline <id> --limit --before\n incidents fabric <id> --dataset --min-weight --limit\n incidents share-links <id>\n incidents update <id> <status> --confirm [--note]\n alerts [list] --limit --asset-id --start\n alerts show <id>\n logs --limit --asset-id --provider --dataset --search\n --start --end --sort --frs-min --cursor\n audit --limit --cursor --action-prefix --outcome\n assets\n assets <allowlist|blocklist|remediation|autonomy|datasets> <asset-id>\n assets graph <asset-id> --dataset --hours --min-weight --limit\n fabric default-asset\n detections --asset-id <asset-id>\n providers\n connections [list]\n connections show <id>\n connections <available-assets|remediation> <id>\n connections <logpush-status|worker-stats> <connection-id> <job-id>\n analytics [overview] --metrics + time-window flags\n analytics <security-analysis|bot-activity|top-attacker-ips|bot-asns|dns-security|page-shield>\n analytics provider-events --provider --dataset --start --end\n [--asset-id --search --limit]\n zero-trust <device-health|app-tests|access|sessions|device-posture>\n zero-trust gateway <dns|http|network>\n cloudflare-account [inventory]\n cloudflare-account <audit|ingestion|posture>\n notifications [list] --limit\n notifications <settings|preferences|slack-channels>\n reports [list] --limit --offset\n reports show <id>\n reports settings\n intel quota\n intel <ip|asn|cidr|ja3|ja4> <query>\n settings <lifecycle-emails|broadcast-emails|applications>\n\nTime-window flags: --hours (1\u2013720, default 24) or --start/--end ISO timestamps;\noptional --asset-id. Apply to analytics (except provider-events), zero-trust,\nand cloudflare-account audit/ingestion/posture. Inventory has no window flags.\nLimits: list incidents/reports/audit 1\u2013100 (default 50); alerts/notifications\n1\u2013100 (default 100); timeline 1\u2013200 (default 100); logs 1\u20131000 (default 100);\nprovider-events 1\u2013500 (default 200); graph 1\u20131000 (default 200).\nOffsets: 0\u20131000000. Graph min-weight: 1\u20131000000 (default 1).\nAll: --json, --timeout <ms>, --customer-id <One customer UUID> (internal View-as).\nAll operations read data except confirmed incident status updates.\nUpdate status: acknowledged, mitigating, resolved, false_positive.\nSee SECURITY.md for every endpoint, supported value, alias, and pagination contract.\n";
@@ -1,6 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { SecurityClient } from '../lib/security-client.js';
3
3
  import { assertCommandFlags, asArray, asRecord, ok, outputJson, requireOneClient, withSpinner } from './helpers.js';
4
+ import { missingArguments } from './legacy-validation.js';
4
5
  const statuses = ['open', 'active', 'acknowledged', 'investigating', 'mitigating', 'mitigated', 'resolved', 'false_positive'];
5
6
  const updateStatuses = ['acknowledged', 'mitigating', 'resolved', 'false_positive'];
6
7
  function textFlag(ctx, flag) {
@@ -20,8 +21,11 @@ function integer(ctx, flag, max, fallback) {
20
21
  function allowed(ctx, flags) {
21
22
  assertCommandFlags(ctx, [...flags, 'customer-id']);
22
23
  }
23
- function arity(ctx, length) {
24
- if (ctx.rest.length !== length)
24
+ /** `usage` follows `vigilbase security` and ends with the positional placeholders, so a missing one is named. */
25
+ function arity(ctx, length, usage) {
26
+ if (ctx.rest.length < length)
27
+ throw new Error(missingArguments('security', length - ctx.rest.length, usage && `vigilbase security ${usage}`));
28
+ if (ctx.rest.length > length)
25
29
  throw new Error('Unexpected security arguments. Run `vigilbase security --help` for usage.');
26
30
  }
27
31
  function uuid(value) {
@@ -92,7 +96,7 @@ function extendedSecurityRequest(ctx, scope) {
92
96
  const views = { 'device-health': 'deviceHealth', 'app-tests': 'appTests', gateway: 'gateway', access: 'access', sessions: 'sessions', 'device-posture': 'devicePosture' };
93
97
  if (!sub || !views[sub])
94
98
  throw new Error('Choose a zero-trust command: device-health, app-tests, gateway, access, sessions, device-posture.');
95
- arity(ctx, sub === 'gateway' ? 3 : 2);
99
+ arity(ctx, sub === 'gateway' ? 3 : 2, 'zero-trust gateway <dns|http|network>');
96
100
  const query = window();
97
101
  if (sub === 'gateway')
98
102
  query.surface = z.enum(['dns', 'http', 'network']).parse(id);
@@ -128,28 +132,28 @@ function extendedSecurityRequest(ctx, scope) {
128
132
  }
129
133
  if (group === 'assets' && sub !== undefined) {
130
134
  const routes = {
131
- allowlist: [`/domains/${uuid(id)}/allowlist`, 'ipList'], blocklist: [`/domains/${uuid(id)}/blocklist`, 'ipList'],
132
- remediation: [`/assets/${uuid(id)}/remediation-settings`, 'assetRemediation'], autonomy: [`/assets/${uuid(id)}/vigil-autonomy`, 'autonomy'],
133
- datasets: [`/fabric/assets/${uuid(id)}/datasets`, 'datasets'], graph: [`/fabric/assets/${uuid(id)}/graph`, 'graph'],
135
+ allowlist: (assetId) => [`/domains/${assetId}/allowlist`, 'ipList'], blocklist: (assetId) => [`/domains/${assetId}/blocklist`, 'ipList'],
136
+ remediation: (assetId) => [`/assets/${assetId}/remediation-settings`, 'assetRemediation'], autonomy: (assetId) => [`/assets/${assetId}/vigil-autonomy`, 'autonomy'],
137
+ datasets: (assetId) => [`/fabric/assets/${assetId}/datasets`, 'datasets'], graph: (assetId) => [`/fabric/assets/${assetId}/graph`, 'graph'],
134
138
  };
135
- const route = routes[sub];
139
+ const route = Object.hasOwn(routes, sub) ? routes[sub] : undefined;
136
140
  if (!route)
137
141
  throw new Error(`Unknown assets command: ${sub}`);
138
- arity(ctx, 3);
142
+ arity(ctx, 3, `assets ${sub} <asset-id>`);
139
143
  if (sub !== 'graph')
140
144
  allowed(ctx, []);
141
- return request(...route, sub === 'graph' ? graph(false) : {});
145
+ return request(...route(uuid(id)), sub === 'graph' ? graph(false) : {});
142
146
  }
143
147
  if (group === 'fabric') {
144
- arity(ctx, 2);
145
- allowed(ctx, []);
146
148
  if (sub !== 'default-asset')
147
149
  throw new Error('Usage: vigilbase security fabric default-asset');
150
+ arity(ctx, 2);
151
+ allowed(ctx, []);
148
152
  return request('/fabric/default-asset', 'defaultAsset');
149
153
  }
150
154
  if (group === 'connections' && sub && ['available-assets', 'remediation', 'logpush-status', 'worker-stats'].includes(sub)) {
151
155
  const isJob = sub === 'logpush-status' || sub === 'worker-stats';
152
- arity(ctx, isJob ? 4 : 3);
156
+ arity(ctx, isJob ? 4 : 3, isJob ? `connections ${sub} <connection-id> <job-id>` : `connections ${sub} <id>`);
153
157
  allowed(ctx, []);
154
158
  const connectionId = uuid(id);
155
159
  if (sub === 'available-assets')
@@ -165,7 +169,7 @@ function extendedSecurityRequest(ctx, scope) {
165
169
  }
166
170
  if (group === 'alerts') {
167
171
  if (sub === 'show' || sub === 'get') {
168
- arity(ctx, 3);
172
+ arity(ctx, 3, `alerts ${sub} <id>`);
169
173
  allowed(ctx, []);
170
174
  return request(`/alerts/${uuid(id)}`, 'alert');
171
175
  }
@@ -179,7 +183,7 @@ function extendedSecurityRequest(ctx, scope) {
179
183
  return request('/alerts', 'alerts', { limit: integer(ctx, 'limit', 100, 100), asset_id: ctx.values['asset-id'] !== undefined ? uuid(ctx.values['asset-id']) : undefined, since });
180
184
  }
181
185
  if (group === 'incidents' && (sub === 'fabric' || sub === 'share-links')) {
182
- arity(ctx, 3);
186
+ arity(ctx, 3, `incidents ${sub} <id>`);
183
187
  if (sub === 'share-links')
184
188
  allowed(ctx, []);
185
189
  return request(`/incidents/${uuid(id)}/${sub}`, sub === 'fabric' ? 'graph' : 'shareLinks', sub === 'fabric' ? graph(true) : {});
@@ -211,17 +215,17 @@ export function buildSecurityRequest(ctx) {
211
215
  }
212
216
  if (['incidents', 'connections', 'reports'].includes(group)) {
213
217
  if (command === 'show' || command === 'get') {
214
- arity(ctx, 3);
218
+ arity(ctx, 3, `${group} ${command} <id>`);
215
219
  allowed(ctx, []);
216
220
  return request(`/${group}/${uuid(ctx.rest[2])}`, group === 'incidents' ? 'incident' : group === 'connections' ? 'connection' : 'report');
217
221
  }
218
222
  if (group === 'incidents' && command === 'timeline') {
219
- arity(ctx, 3);
223
+ arity(ctx, 3, 'incidents timeline <id>');
220
224
  allowed(ctx, ['before', 'limit']);
221
225
  return request(`/incidents/${uuid(ctx.rest[2])}/timeline`, 'timeline', { limit: integer(ctx, 'limit', 200, 100), before: textFlag(ctx, 'before') });
222
226
  }
223
227
  if (group === 'incidents' && command === 'update') {
224
- arity(ctx, 4);
228
+ arity(ctx, 4, 'incidents update <id> <status>');
225
229
  allowed(ctx, ['note', 'isConfirm']);
226
230
  const id = uuid(ctx.rest[2]);
227
231
  const status = z.enum(updateStatuses).parse(ctx.rest[3]);
@@ -250,10 +254,18 @@ export function buildSecurityRequest(ctx) {
250
254
  order_direction: z.enum(['asc', 'desc']).optional().parse(textFlag(ctx, 'order-direction')),
251
255
  });
252
256
  }
253
- if (group === 'assets' || group === 'detections') {
257
+ if (group === 'assets') {
258
+ arity(ctx, 1);
259
+ allowed(ctx, []);
260
+ return request('/domains', 'assets');
261
+ }
262
+ if (group === 'detections') {
263
+ // Detections are configured per asset; the API has no tenant-wide list.
254
264
  arity(ctx, 1);
255
- allowed(ctx, group === 'detections' ? ['asset-id'] : []);
256
- return request(group === 'assets' ? '/domains' : '/detections', group, group === 'detections' && ctx.values['asset-id'] !== undefined ? { asset_id: uuid(ctx.values['asset-id']) } : {});
265
+ allowed(ctx, ['asset-id']);
266
+ if (ctx.values['asset-id'] === undefined)
267
+ throw new Error('security detections requires --asset-id <uuid>. List asset IDs with `vigilbase security assets`.');
268
+ return request('/detections', 'detections', { asset_id: uuid(ctx.values['asset-id']) });
257
269
  }
258
270
  if (group === 'logs') {
259
271
  arity(ctx, 1);
@@ -289,7 +301,7 @@ export function buildSecurityRequest(ctx) {
289
301
  arity(ctx, 2);
290
302
  return request('/intel/quota', 'quota');
291
303
  }
292
- arity(ctx, 3);
304
+ arity(ctx, 3, 'intel <ip|asn|cidr|ja3|ja4> <query>');
293
305
  const type = z.enum(['ip', 'asn', 'cidr', 'ja3', 'ja4']).parse(command);
294
306
  const q = z.string().trim().min(1).max(512).parse(ctx.rest[2]);
295
307
  return request('/intel/lookup', 'intel', { q, type });
@@ -387,5 +399,4 @@ export const handleSecurity = async (ctx) => {
387
399
  display(ctx, request, payload);
388
400
  return ok();
389
401
  };
390
- export const SECURITY_HELP = "vigilbase security \u2014 managed security in Vigilbase One\n\n [overview]\n incidents [list] --status --severity --attack-category\n --order-by --order-direction --limit --offset\n incidents show <id>\n incidents timeline <id> --limit --before\n incidents fabric <id> --dataset --min-weight --limit\n incidents share-links <id>\n incidents update <id> <status> --confirm [--note]\n alerts [list] --limit --asset-id --start\n alerts show <id>\n logs --limit --asset-id --provider --dataset --search\n --start --end --sort --frs-min --cursor\n audit --limit --cursor --action-prefix --outcome\n assets\n assets <allowlist|blocklist|remediation|autonomy|datasets> <asset-id>\n assets graph <asset-id> --dataset --hours --min-weight --limit\n fabric default-asset\n detections --asset-id\n providers\n connections [list]\n connections show <id>\n connections <available-assets|remediation> <id>\n connections <logpush-status|worker-stats> <connection-id> <job-id>\n analytics [overview] --metrics + time-window flags\n analytics <security-analysis|bot-activity|top-attacker-ips|bot-asns|dns-security|page-shield>\n analytics provider-events --provider --dataset --start --end\n [--asset-id --search --limit]\n zero-trust <device-health|app-tests|access|sessions|device-posture>\n zero-trust gateway <dns|http|network>\n cloudflare-account [inventory]\n cloudflare-account <audit|ingestion|posture>\n notifications [list] --limit\n notifications <settings|preferences|slack-channels>\n reports [list] --limit --offset\n reports show <id>\n reports settings\n intel quota\n intel <ip|asn|cidr|ja3|ja4> <query>\n settings <lifecycle-emails|broadcast-emails|applications>\n\nTime-window flags: --hours (1\u2013720, default 24) or --start/--end ISO timestamps;\noptional --asset-id. Apply to analytics (except provider-events), zero-trust,\nand cloudflare-account audit/ingestion/posture. Inventory has no window flags.\nLimits: list incidents/reports/audit 1\u2013100 (default 50); alerts/notifications\n1\u2013100 (default 100); timeline 1\u2013200 (default 100); logs 1\u20131000 (default 100);\nprovider-events 1\u2013500 (default 200); graph 1\u20131000 (default 200).\nOffsets: 0\u20131000000. Graph min-weight: 1\u20131000000 (default 1).\nAll: --json, --timeout <ms>, --customer-id <One customer UUID> (internal View-as).\nAll operations read data except confirmed incident status updates.\nUpdate status: acknowledged, mitigating, resolved, false_positive.\nSee SECURITY.md for every endpoint, supported value, alias, and pagination contract.\n";
391
- //# sourceMappingURL=security.js.map
402
+ export const SECURITY_HELP = "vigilbase security \u2014 managed security in Vigilbase One\n\n [overview]\n incidents [list] --status --severity --attack-category\n --order-by --order-direction --limit --offset\n incidents show <id>\n incidents timeline <id> --limit --before\n incidents fabric <id> --dataset --min-weight --limit\n incidents share-links <id>\n incidents update <id> <status> --confirm [--note]\n alerts [list] --limit --asset-id --start\n alerts show <id>\n logs --limit --asset-id --provider --dataset --search\n --start --end --sort --frs-min --cursor\n audit --limit --cursor --action-prefix --outcome\n assets\n assets <allowlist|blocklist|remediation|autonomy|datasets> <asset-id>\n assets graph <asset-id> --dataset --hours --min-weight --limit\n fabric default-asset\n detections --asset-id <asset-id>\n providers\n connections [list]\n connections show <id>\n connections <available-assets|remediation> <id>\n connections <logpush-status|worker-stats> <connection-id> <job-id>\n analytics [overview] --metrics + time-window flags\n analytics <security-analysis|bot-activity|top-attacker-ips|bot-asns|dns-security|page-shield>\n analytics provider-events --provider --dataset --start --end\n [--asset-id --search --limit]\n zero-trust <device-health|app-tests|access|sessions|device-posture>\n zero-trust gateway <dns|http|network>\n cloudflare-account [inventory]\n cloudflare-account <audit|ingestion|posture>\n notifications [list] --limit\n notifications <settings|preferences|slack-channels>\n reports [list] --limit --offset\n reports show <id>\n reports settings\n intel quota\n intel <ip|asn|cidr|ja3|ja4> <query>\n settings <lifecycle-emails|broadcast-emails|applications>\n\nTime-window flags: --hours (1\u2013720, default 24) or --start/--end ISO timestamps;\noptional --asset-id. Apply to analytics (except provider-events), zero-trust,\nand cloudflare-account audit/ingestion/posture. Inventory has no window flags.\nLimits: list incidents/reports/audit 1\u2013100 (default 50); alerts/notifications\n1\u2013100 (default 100); timeline 1\u2013200 (default 100); logs 1\u20131000 (default 100);\nprovider-events 1\u2013500 (default 200); graph 1\u20131000 (default 200).\nOffsets: 0\u20131000000. Graph min-weight: 1\u20131000000 (default 1).\nAll: --json, --timeout <ms>, --customer-id <One customer UUID> (internal View-as).\nAll operations read data except confirmed incident status updates.\nUpdate status: acknowledged, mitigating, resolved, false_positive.\nSee SECURITY.md for every endpoint, supported value, alias, and pagination contract.\n";
@@ -1,3 +1,2 @@
1
1
  import { type CommandHandler } from './helpers.js';
2
2
  export declare const handleWatchdog: CommandHandler;
3
- //# sourceMappingURL=watchdog.d.ts.map
@@ -59,4 +59,3 @@ export const handleWatchdog = async (ctx) => {
59
59
  }
60
60
  throw new Error('Usage: vigilbase watchdog [list|scans] [--target-id …] [--limit …] [--json]');
61
61
  };
62
- //# sourceMappingURL=watchdog.js.map
package/dist/index.d.ts CHANGED
@@ -1,14 +1,13 @@
1
1
  export { runCli, CLI_VERSION } from './cli.js';
2
2
  export { VigilbaseClient, VigilbaseApiError } from './lib/client.js';
3
3
  export { createConfig, resolveBaseUrl, resolvePublicBaseUrl, resolveOneBaseUrl, } from './lib/config.js';
4
- export { discoverAuthProvider, identityProvider, managedAccessToken, revokeSavedCredentials, clearOneCredentials, credentialsPath, DeviceAuthError, getOneAccessToken, readCredentials, requestDeviceCode, waitForDeviceAuthorization, writeOneCredentials, } from './auth/index.js';
4
+ export { discoverAuthProvider, identityProvider, managedAccessToken, revokeSavedCredentials, clearOneCredentials, credentialsPath, DeviceAuthError, getOneAccessToken, identityCredentialsPath, readCredentials, requestDeviceCode, waitForDeviceAuthorization, writeOneCredentials, } from './auth/index.js';
5
5
  export { isOneAuthRequiredTool, isOneExecutableTool, ONE_AUTH_REQUIRED_TOOLS, ONE_AUTH_REQUIRED_TOOL_DEFINITIONS, ONE_EXECUTABLE_TOOLS, VigilbaseOneClient, } from './lib/one-client.js';
6
6
  export { EXIT } from './types.js';
7
- export type { AgentToolDefinition, AgentToolExecuteResponse, AgentToolsCatalogResponse, CliOutputMode, ExitCode, } from './types.js';
7
+ export type { AgentApiError, AgentApiErrorCode, AgentApiErrorResponse, AgentToolDefinition, AgentToolExecuteResponse, AgentToolsCatalogResponse, CliOutputMode, ExitCode, } from './types.js';
8
8
  export type { AuthProvider } from './auth/provider.js';
9
9
  export type { CredentialsFile, OneCredentials } from './auth/types.js';
10
10
  export { CloudflareClient } from './lib/cloudflare-client.js';
11
11
  export type { CloudflareScope, WorkspaceSection } from './lib/cloudflare-client.js';
12
12
  export { SecurityClient } from './lib/security-client.js';
13
13
  export type { SecurityPayload, SecurityQuery, SecurityRequest } from './lib/security-client.js';
14
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,9 +1,8 @@
1
1
  export { runCli, CLI_VERSION } from './cli.js';
2
2
  export { VigilbaseClient, VigilbaseApiError } from './lib/client.js';
3
3
  export { createConfig, resolveBaseUrl, resolvePublicBaseUrl, resolveOneBaseUrl, } from './lib/config.js';
4
- export { discoverAuthProvider, identityProvider, managedAccessToken, revokeSavedCredentials, clearOneCredentials, credentialsPath, DeviceAuthError, getOneAccessToken, readCredentials, requestDeviceCode, waitForDeviceAuthorization, writeOneCredentials, } from './auth/index.js';
4
+ export { discoverAuthProvider, identityProvider, managedAccessToken, revokeSavedCredentials, clearOneCredentials, credentialsPath, DeviceAuthError, getOneAccessToken, identityCredentialsPath, readCredentials, requestDeviceCode, waitForDeviceAuthorization, writeOneCredentials, } from './auth/index.js';
5
5
  export { isOneAuthRequiredTool, isOneExecutableTool, ONE_AUTH_REQUIRED_TOOLS, ONE_AUTH_REQUIRED_TOOL_DEFINITIONS, ONE_EXECUTABLE_TOOLS, VigilbaseOneClient, } from './lib/one-client.js';
6
6
  export { EXIT } from './types.js';
7
7
  export { CloudflareClient } from './lib/cloudflare-client.js';
8
8
  export { SecurityClient } from './lib/security-client.js';
9
- //# sourceMappingURL=index.js.map
@@ -26,4 +26,3 @@ export declare function shouldShowBanner(mode?: 'text' | 'json', env?: NodeJS.Pr
26
26
  export declare function renderBanner(options?: BannerOptions, stream?: {
27
27
  isTTY?: boolean;
28
28
  } | undefined, env?: NodeJS.ProcessEnv): string;
29
- //# sourceMappingURL=banner.d.ts.map
@@ -65,4 +65,3 @@ export function renderBanner(options = {}, stream = process.stdout, env = proces
65
65
  });
66
66
  return lines.join('\n');
67
67
  }
68
- //# sourceMappingURL=banner.js.map
@@ -1,18 +1,26 @@
1
- import type { AgentToolExecuteResponse, AgentToolsCatalogResponse } from '../types.js';
1
+ import { type AgentToolExecuteResponse, type AgentToolsCatalogResponse } from '../types.js';
2
2
  import type { CliConfig } from './config.js';
3
3
  export declare class VigilbaseApiError extends Error {
4
4
  readonly status: number;
5
5
  readonly body: unknown;
6
6
  readonly retryAfterSec?: number;
7
7
  readonly code?: string;
8
+ /** The server's sanitised explanation, set only for known vigilbase.com problem errors. */
9
+ readonly reason?: string;
10
+ /** CLI-authored remediation, never server text (see one-error-hints.ts). */
11
+ readonly hint?: string;
8
12
  constructor(message: string, options: {
9
13
  status: number;
10
14
  body?: unknown;
11
15
  retryAfterSec?: number;
12
16
  code?: string;
17
+ reason?: string;
18
+ hint?: string;
13
19
  });
14
20
  }
15
21
  export declare function retryAfterSeconds(response: Response, body: unknown): number | undefined;
22
+ /** The versioned public tools API. The unversioned /api/agent/tools aliases sunset on 2027-09-01. */
23
+ export declare const PUBLIC_TOOLS_PATH = "/api/v1/agent/tools";
16
24
  /**
17
25
  * Public (unauthenticated) vigilbase.com tools client.
18
26
  * Vigilbase One authenticated calls will use a separate client + device-auth tokens.
@@ -27,4 +35,3 @@ export declare class VigilbaseClient {
27
35
  fetchSkillMarkdown(skillUrl: string): Promise<string>;
28
36
  badgeUrl(domain: string, style?: 'default' | 'compact' | 'mini'): string;
29
37
  }
30
- //# sourceMappingURL=client.d.ts.map