@vigilbase/cli 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLOUDFLARE.md +2 -5
- package/COMMANDS.md +150 -112
- package/LOCAL.md +73 -83
- package/ONE.md +2 -4
- package/README.md +337 -171
- package/SECURITY.md +2 -2
- package/dist/auth/device-auth.d.ts +0 -1
- package/dist/auth/device-auth.js +6 -5
- package/dist/auth/index.d.ts +1 -2
- package/dist/auth/index.js +1 -2
- package/dist/auth/provider.d.ts +1 -1
- package/dist/auth/provider.js +16 -7
- package/dist/auth/refresh.d.ts +23 -4
- package/dist/auth/refresh.js +78 -22
- package/dist/auth/store.d.ts +78 -4
- package/dist/auth/store.js +385 -74
- package/dist/auth/token-metadata.d.ts +0 -1
- package/dist/auth/token-metadata.js +0 -1
- package/dist/auth/types.d.ts +0 -1
- package/dist/auth/types.js +0 -1
- package/dist/bin.d.ts +0 -1
- package/dist/bin.js +0 -1
- package/dist/cli.d.ts +4 -2
- package/dist/cli.js +7 -8
- package/dist/commands/account.d.ts +0 -1
- package/dist/commands/account.js +0 -1
- package/dist/commands/auth.d.ts +0 -1
- package/dist/commands/auth.js +69 -21
- package/dist/commands/billing.d.ts +0 -1
- package/dist/commands/billing.js +0 -1
- package/dist/commands/cloudflare.d.ts +1 -2
- package/dist/commands/cloudflare.js +6 -6
- package/dist/commands/helpers.d.ts +0 -1
- package/dist/commands/helpers.js +0 -1
- package/dist/commands/index.d.ts +0 -1
- package/dist/commands/index.js +0 -1
- package/dist/commands/legacy-validation.d.ts +0 -1
- package/dist/commands/legacy-validation.js +0 -1
- package/dist/commands/local.d.ts +6 -1
- package/dist/commands/local.js +34 -11
- package/dist/commands/one.d.ts +0 -1
- package/dist/commands/one.js +6 -7
- package/dist/commands/public-tools.d.ts +0 -1
- package/dist/commands/public-tools.js +52 -18
- package/dist/commands/runs.d.ts +0 -1
- package/dist/commands/runs.js +0 -1
- package/dist/commands/security.d.ts +1 -2
- package/dist/commands/security.js +1 -2
- package/dist/commands/watchdog.d.ts +0 -1
- package/dist/commands/watchdog.js +0 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +1 -2
- package/dist/lib/banner.d.ts +0 -1
- package/dist/lib/banner.js +0 -1
- package/dist/lib/client.d.ts +4 -2
- package/dist/lib/client.js +42 -18
- package/dist/lib/cloudflare-client.d.ts +0 -1
- package/dist/lib/cloudflare-client.js +0 -1
- package/dist/lib/config.d.ts +16 -3
- package/dist/lib/config.js +41 -14
- package/dist/lib/format.d.ts +2 -1
- package/dist/lib/format.js +19 -8
- package/dist/lib/help.d.ts +1 -2
- package/dist/lib/help.js +29 -18
- package/dist/lib/network.d.ts +10 -1
- package/dist/lib/network.js +31 -4
- package/dist/lib/one-client.d.ts +2 -1
- package/dist/lib/one-client.js +3 -1
- package/dist/lib/one-operations.d.ts +0 -1
- package/dist/lib/one-operations.js +0 -1
- package/dist/lib/open-url.d.ts +0 -1
- package/dist/lib/open-url.js +0 -1
- package/dist/lib/platform.d.ts +2 -0
- package/dist/lib/platform.js +4 -0
- package/dist/lib/progress.d.ts +0 -1
- package/dist/lib/progress.js +0 -1
- package/dist/lib/security-client.d.ts +0 -1
- package/dist/lib/security-client.js +0 -1
- package/dist/lib/skill-fetch.d.ts +0 -1
- package/dist/lib/skill-fetch.js +0 -1
- package/dist/lib/system-trust.d.ts +0 -1
- package/dist/lib/system-trust.js +0 -1
- package/dist/lib/tui.d.ts +0 -1
- package/dist/lib/tui.js +0 -1
- package/dist/local/cloudflare-checkup/cf/allowlist.d.ts +0 -1
- package/dist/local/cloudflare-checkup/cf/allowlist.js +0 -1
- package/dist/local/cloudflare-checkup/cf/auth-lifecycle.d.ts +0 -1
- package/dist/local/cloudflare-checkup/cf/auth-lifecycle.js +0 -1
- package/dist/local/cloudflare-checkup/cf/child-env.d.ts +0 -1
- package/dist/local/cloudflare-checkup/cf/child-env.js +0 -1
- package/dist/local/cloudflare-checkup/cf/install.d.ts +0 -1
- package/dist/local/cloudflare-checkup/cf/install.js +0 -1
- package/dist/local/cloudflare-checkup/cf/locate.d.ts +0 -1
- package/dist/local/cloudflare-checkup/cf/locate.js +0 -1
- package/dist/local/cloudflare-checkup/cf/run-cf.d.ts +0 -1
- package/dist/local/cloudflare-checkup/cf/run-cf.js +0 -1
- package/dist/local/cloudflare-checkup/collector.d.ts +0 -1
- package/dist/local/cloudflare-checkup/collector.js +0 -1
- package/dist/local/cloudflare-checkup/contract.d.ts +14 -3
- package/dist/local/cloudflare-checkup/contract.js +9 -3
- package/dist/local/cloudflare-checkup/email-verification.d.ts +0 -1
- package/dist/local/cloudflare-checkup/email-verification.js +0 -1
- package/dist/local/cloudflare-checkup/errors.d.ts +2 -1
- package/dist/local/cloudflare-checkup/errors.js +6 -2
- package/dist/local/cloudflare-checkup/output.d.ts +0 -1
- package/dist/local/cloudflare-checkup/output.js +0 -1
- package/dist/local/cloudflare-checkup/prompts.d.ts +0 -1
- package/dist/local/cloudflare-checkup/prompts.js +0 -1
- package/dist/local/cloudflare-checkup/rate-budget.d.ts +0 -1
- package/dist/local/cloudflare-checkup/rate-budget.js +0 -1
- package/dist/local/cloudflare-checkup/snapshot-file.d.ts +0 -1
- package/dist/local/cloudflare-checkup/snapshot-file.js +0 -1
- package/dist/local/cloudflare-checkup/submit-client.d.ts +19 -5
- package/dist/local/cloudflare-checkup/submit-client.js +63 -17
- package/dist/local/cloudflare-checkup/terminal-ui.d.ts +0 -1
- package/dist/local/cloudflare-checkup/terminal-ui.js +0 -1
- package/dist/types.d.ts +25 -3
- package/dist/types.js +16 -1
- package/dist/version.d.ts +0 -1
- package/dist/version.js +0 -1
- package/package.json +5 -9
- package/dist/auth/device-auth.d.ts.map +0 -1
- package/dist/auth/device-auth.js.map +0 -1
- package/dist/auth/index.d.ts.map +0 -1
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/provider.d.ts.map +0 -1
- package/dist/auth/provider.js.map +0 -1
- package/dist/auth/refresh.d.ts.map +0 -1
- package/dist/auth/refresh.js.map +0 -1
- package/dist/auth/store.d.ts.map +0 -1
- package/dist/auth/store.js.map +0 -1
- package/dist/auth/token-metadata.d.ts.map +0 -1
- package/dist/auth/token-metadata.js.map +0 -1
- package/dist/auth/types.d.ts.map +0 -1
- package/dist/auth/types.js.map +0 -1
- package/dist/bin.d.ts.map +0 -1
- package/dist/bin.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/account.d.ts.map +0 -1
- package/dist/commands/account.js.map +0 -1
- package/dist/commands/auth.d.ts.map +0 -1
- package/dist/commands/auth.js.map +0 -1
- package/dist/commands/billing.d.ts.map +0 -1
- package/dist/commands/billing.js.map +0 -1
- package/dist/commands/cloudflare.d.ts.map +0 -1
- package/dist/commands/cloudflare.js.map +0 -1
- package/dist/commands/helpers.d.ts.map +0 -1
- package/dist/commands/helpers.js.map +0 -1
- package/dist/commands/index.d.ts.map +0 -1
- package/dist/commands/index.js.map +0 -1
- package/dist/commands/legacy-validation.d.ts.map +0 -1
- package/dist/commands/legacy-validation.js.map +0 -1
- package/dist/commands/local.d.ts.map +0 -1
- package/dist/commands/local.js.map +0 -1
- package/dist/commands/one.d.ts.map +0 -1
- package/dist/commands/one.js.map +0 -1
- package/dist/commands/public-tools.d.ts.map +0 -1
- package/dist/commands/public-tools.js.map +0 -1
- package/dist/commands/runs.d.ts.map +0 -1
- package/dist/commands/runs.js.map +0 -1
- package/dist/commands/security.d.ts.map +0 -1
- package/dist/commands/security.js.map +0 -1
- package/dist/commands/watchdog.d.ts.map +0 -1
- package/dist/commands/watchdog.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/banner.d.ts.map +0 -1
- package/dist/lib/banner.js.map +0 -1
- package/dist/lib/client.d.ts.map +0 -1
- package/dist/lib/client.js.map +0 -1
- package/dist/lib/cloudflare-client.d.ts.map +0 -1
- package/dist/lib/cloudflare-client.js.map +0 -1
- package/dist/lib/config.d.ts.map +0 -1
- package/dist/lib/config.js.map +0 -1
- package/dist/lib/format.d.ts.map +0 -1
- package/dist/lib/format.js.map +0 -1
- package/dist/lib/help.d.ts.map +0 -1
- package/dist/lib/help.js.map +0 -1
- package/dist/lib/network.d.ts.map +0 -1
- package/dist/lib/network.js.map +0 -1
- package/dist/lib/one-client.d.ts.map +0 -1
- package/dist/lib/one-client.js.map +0 -1
- package/dist/lib/one-operations.d.ts.map +0 -1
- package/dist/lib/one-operations.js.map +0 -1
- package/dist/lib/open-url.d.ts.map +0 -1
- package/dist/lib/open-url.js.map +0 -1
- package/dist/lib/progress.d.ts.map +0 -1
- package/dist/lib/progress.js.map +0 -1
- package/dist/lib/security-client.d.ts.map +0 -1
- package/dist/lib/security-client.js.map +0 -1
- package/dist/lib/skill-fetch.d.ts.map +0 -1
- package/dist/lib/skill-fetch.js.map +0 -1
- package/dist/lib/system-trust.d.ts.map +0 -1
- package/dist/lib/system-trust.js.map +0 -1
- package/dist/lib/tui.d.ts.map +0 -1
- package/dist/lib/tui.js.map +0 -1
- package/dist/local/cloudflare-checkup/cf/allowlist.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/cf/allowlist.js.map +0 -1
- package/dist/local/cloudflare-checkup/cf/auth-lifecycle.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/cf/auth-lifecycle.js.map +0 -1
- package/dist/local/cloudflare-checkup/cf/child-env.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/cf/child-env.js.map +0 -1
- package/dist/local/cloudflare-checkup/cf/install.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/cf/install.js.map +0 -1
- package/dist/local/cloudflare-checkup/cf/locate.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/cf/locate.js.map +0 -1
- package/dist/local/cloudflare-checkup/cf/run-cf.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/cf/run-cf.js.map +0 -1
- package/dist/local/cloudflare-checkup/collector.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/collector.js.map +0 -1
- package/dist/local/cloudflare-checkup/contract.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/contract.js.map +0 -1
- package/dist/local/cloudflare-checkup/email-verification.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/email-verification.js.map +0 -1
- package/dist/local/cloudflare-checkup/errors.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/errors.js.map +0 -1
- package/dist/local/cloudflare-checkup/output.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/output.js.map +0 -1
- package/dist/local/cloudflare-checkup/prompts.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/prompts.js.map +0 -1
- package/dist/local/cloudflare-checkup/rate-budget.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/rate-budget.js.map +0 -1
- package/dist/local/cloudflare-checkup/snapshot-file.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/snapshot-file.js.map +0 -1
- package/dist/local/cloudflare-checkup/submit-client.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/submit-client.js.map +0 -1
- package/dist/local/cloudflare-checkup/terminal-ui.d.ts.map +0 -1
- package/dist/local/cloudflare-checkup/terminal-ui.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js.map +0 -1
package/dist/commands/account.js
CHANGED
package/dist/commands/auth.d.ts
CHANGED
package/dist/commands/auth.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readIdentityTokenMetadata } from '../auth/token-metadata.js';
|
|
2
2
|
import { discoverAuthProvider } from '../auth/provider.js';
|
|
3
|
-
import { revokeSavedCredentials, withCredentialsLock } from '../auth/refresh.js';
|
|
3
|
+
import { revokeIdentityCredentials, revokeIdentityGrant, revokeSavedCredentials, withCredentialsLock } from '../auth/refresh.js';
|
|
4
|
+
import { checkCredentialsLocation, clearIdentityCredentials, clearOneCredentials, hasIgnoredIdentityCredentials, readReplacedIdentityGrant, readStoredCredentials } from '../auth/store.js';
|
|
4
5
|
import { getOneAccessToken, readCredentials, requestDeviceCode, waitForDeviceAuthorization, writeOneCredentials, } from '../auth/index.js';
|
|
5
6
|
import { VigilbaseOneClient, ONE_AUTH_REQUIRED_TOOLS } from '../lib/one-client.js';
|
|
6
7
|
import { VigilbaseApiError } from '../lib/client.js';
|
|
@@ -22,6 +23,30 @@ export async function readTokenFromStdin(input = process.stdin) {
|
|
|
22
23
|
throw new Error('Token input must contain exactly one nonempty token.');
|
|
23
24
|
return token;
|
|
24
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Revoke the Identity grant a new login replaces, before the new grant exists. Identity treats a revoked refresh
|
|
28
|
+
* token presented again as reuse and ends every CLI grant of the user, so revoking after the new grant was issued
|
|
29
|
+
* could end it too. The lock is held from the read to the removal of the old file, so no concurrent command can
|
|
30
|
+
* refresh with the token in between, and no later command presents it again.
|
|
31
|
+
*/
|
|
32
|
+
async function retirePreviousIdentityGrant(ctx) {
|
|
33
|
+
await withCredentialsLock(ctx.config, async () => {
|
|
34
|
+
const previous = await readReplacedIdentityGrant(ctx.config);
|
|
35
|
+
// After a refresh with an uncertain result the token may be rotated already; presenting it trips the same check.
|
|
36
|
+
if (!previous || previous.refreshPending)
|
|
37
|
+
return;
|
|
38
|
+
try {
|
|
39
|
+
await revokeIdentityGrant(ctx.config, previous);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
ctx.writer.stderr("Warning: Couldn't revoke your previous sign-in; it will expire on its own.");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// The grant came from identity-credentials.json, or from a CLI 0.2.0 credentials.json when that file is absent.
|
|
46
|
+
const { identity } = await readStoredCredentials(ctx.config, () => { });
|
|
47
|
+
await (identity ? clearIdentityCredentials(ctx.config) : clearOneCredentials(ctx.config));
|
|
48
|
+
}, true);
|
|
49
|
+
}
|
|
25
50
|
export const handleLogin = async (ctx) => {
|
|
26
51
|
if (ctx.rest.length)
|
|
27
52
|
throw new Error('Usage: vigilbase login [--token-stdin | --token <bearer>] [--no-open]');
|
|
@@ -29,6 +54,9 @@ export const handleLogin = async (ctx) => {
|
|
|
29
54
|
if (ctx.loginHandler) {
|
|
30
55
|
return ctx.loginHandler(ctx.config);
|
|
31
56
|
}
|
|
57
|
+
// Fail on Windows or an unsafe credentials directory or file before validating a token or starting device
|
|
58
|
+
// authorization: once a device grant is approved, a failed save would leave it unsaved and unrevoked.
|
|
59
|
+
await checkCredentialsLocation(ctx.config);
|
|
32
60
|
if (ctx.values.isTokenStdin && (ctx.values.token !== undefined || ctx.env.VIGILBASE_ONE_TOKEN !== undefined)) {
|
|
33
61
|
throw new Error('Use --token-stdin without --token or VIGILBASE_ONE_TOKEN.');
|
|
34
62
|
}
|
|
@@ -50,15 +78,19 @@ export const handleLogin = async (ctx) => {
|
|
|
50
78
|
email: session.user.email ?? undefined,
|
|
51
79
|
name: session.user.name ?? undefined,
|
|
52
80
|
};
|
|
53
|
-
await withCredentialsLock(ctx.config, () =>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
81
|
+
await withCredentialsLock(ctx.config, async () => {
|
|
82
|
+
// Identity credentials win when tokens are read, so revoke them before saving this session.
|
|
83
|
+
await revokeIdentityCredentials(ctx.config);
|
|
84
|
+
await writeOneCredentials(ctx.config, {
|
|
85
|
+
accessToken: explicitToken,
|
|
86
|
+
tokenType: 'Bearer',
|
|
87
|
+
expiresAt: typeof session.session?.expiresAt === 'string'
|
|
88
|
+
? session.session.expiresAt
|
|
89
|
+
: undefined,
|
|
90
|
+
user,
|
|
91
|
+
obtainedAt: new Date().toISOString(),
|
|
92
|
+
});
|
|
93
|
+
}, true);
|
|
62
94
|
if (ctx.mode === 'json') {
|
|
63
95
|
outputJson(ctx, {
|
|
64
96
|
success: true,
|
|
@@ -76,6 +108,8 @@ export const handleLogin = async (ctx) => {
|
|
|
76
108
|
const preferNoOpen = Boolean(ctx.values.isNoOpen) || isHeadlessEnvironment(ctx.env);
|
|
77
109
|
ctx.writer.stderr(`login ${ctx.config.oneBaseUrl}`);
|
|
78
110
|
ctx.config.authProvider = await discoverAuthProvider(ctx.config);
|
|
111
|
+
if (ctx.config.authProvider)
|
|
112
|
+
await retirePreviousIdentityGrant(ctx);
|
|
79
113
|
const device = await withSpinner(ctx, 'Requesting device code', () => requestDeviceCode(ctx.config));
|
|
80
114
|
const verifyUrl = resolveDeviceVerificationUrl(ctx.config.authProvider?.issuer ?? ctx.config.oneBaseUrl, device);
|
|
81
115
|
const prettyCode = formatUserCode(device.user_code);
|
|
@@ -131,15 +165,20 @@ export const handleLogin = async (ctx) => {
|
|
|
131
165
|
if (ctx.config.authProvider && (!token.refresh_token || !expiresAt || !token.expires_in || token.expires_in > 300))
|
|
132
166
|
throw new Error('Identity returned an invalid token grant.');
|
|
133
167
|
const identityMetadata = ctx.config.authProvider ? readIdentityTokenMetadata(token.access_token, { issuer: ctx.config.authProvider.issuer, clientId: ctx.config.clientId, resource: ctx.config.authProvider.resource }) : undefined;
|
|
134
|
-
await withCredentialsLock(ctx.config, () =>
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
168
|
+
await withCredentialsLock(ctx.config, async () => {
|
|
169
|
+
// A legacy session is saved in credentials.json, which saved Identity credentials would override.
|
|
170
|
+
if (!ctx.config.authProvider)
|
|
171
|
+
await revokeIdentityCredentials(ctx.config);
|
|
172
|
+
await writeOneCredentials(ctx.config, {
|
|
173
|
+
...(ctx.config.authProvider ? { issuer: ctx.config.authProvider.issuer, clientId: ctx.config.clientId, resource: ctx.config.authProvider.resource, refreshToken: token.refresh_token, orgId: identityMetadata?.organizationId } : {}),
|
|
174
|
+
accessToken: token.access_token,
|
|
175
|
+
tokenType: token.token_type,
|
|
176
|
+
scope: token.scope,
|
|
177
|
+
expiresAt,
|
|
178
|
+
user,
|
|
179
|
+
obtainedAt: new Date().toISOString(),
|
|
180
|
+
});
|
|
181
|
+
}, true);
|
|
143
182
|
if (ctx.mode === 'json') {
|
|
144
183
|
outputJson(ctx, {
|
|
145
184
|
success: true,
|
|
@@ -160,7 +199,10 @@ export const handleLogout = async (ctx) => {
|
|
|
160
199
|
if (ctx.rest.length)
|
|
161
200
|
throw new Error('Usage: vigilbase logout');
|
|
162
201
|
assertCommandFlags(ctx, []);
|
|
163
|
-
const cleared = await revokeSavedCredentials(ctx.config)
|
|
202
|
+
const cleared = await revokeSavedCredentials(ctx.config, (warning) => {
|
|
203
|
+
if (ctx.mode !== 'json')
|
|
204
|
+
ctx.writer.stderr(`Warning: ${warning}`);
|
|
205
|
+
});
|
|
164
206
|
if (ctx.mode === 'json') {
|
|
165
207
|
outputJson(ctx, { success: true, cleared });
|
|
166
208
|
}
|
|
@@ -177,6 +219,7 @@ export const handleWhoami = async (ctx) => {
|
|
|
177
219
|
throw new Error('Usage: vigilbase whoami');
|
|
178
220
|
assertCommandFlags(ctx, []);
|
|
179
221
|
const credentials = await readCredentials(ctx.config);
|
|
222
|
+
const legacyIdentityFileIgnored = await hasIgnoredIdentityCredentials(ctx.config);
|
|
180
223
|
const accessToken = await getOneAccessToken(ctx.config);
|
|
181
224
|
let liveUser = null;
|
|
182
225
|
if (accessToken) {
|
|
@@ -211,7 +254,10 @@ export const handleWhoami = async (ctx) => {
|
|
|
211
254
|
scope: signedIn ? credentials.one?.scope ?? null : null,
|
|
212
255
|
obtainedAt: signedIn ? credentials.one?.obtainedAt ?? null : null,
|
|
213
256
|
authRequiredTools: signedIn ? [...ONE_AUTH_REQUIRED_TOOLS] : [],
|
|
257
|
+
legacyIdentityFileIgnored,
|
|
214
258
|
};
|
|
259
|
+
// CLI 0.2.0 can save a second Identity grant in credentials.json; logout revokes it.
|
|
260
|
+
const legacyNote = 'Note: found a credentials file from CLI 0.2.0. `vigilbase logout` will revoke and remove it.';
|
|
215
261
|
if (ctx.mode === 'json') {
|
|
216
262
|
outputJson(ctx, payload);
|
|
217
263
|
}
|
|
@@ -219,6 +265,7 @@ export const handleWhoami = async (ctx) => {
|
|
|
219
265
|
outputLines(ctx, [
|
|
220
266
|
'Not signed in. Public tools still work.',
|
|
221
267
|
'Run `vigilbase login` to unlock auth-required tools (website-security, react2shell, fortibleed-check).',
|
|
268
|
+
...(legacyIdentityFileIgnored ? [legacyNote] : []),
|
|
222
269
|
]);
|
|
223
270
|
}
|
|
224
271
|
else {
|
|
@@ -229,8 +276,9 @@ export const handleWhoami = async (ctx) => {
|
|
|
229
276
|
lines.push(`Expires: ${credentials.one.expiresAt}`);
|
|
230
277
|
}
|
|
231
278
|
lines.push(`Auth-required tools: ${ONE_AUTH_REQUIRED_TOOLS.join(', ')}`);
|
|
279
|
+
if (legacyIdentityFileIgnored)
|
|
280
|
+
lines.push(legacyNote);
|
|
232
281
|
outputLines(ctx, lines);
|
|
233
282
|
}
|
|
234
283
|
return ok();
|
|
235
284
|
};
|
|
236
|
-
//# sourceMappingURL=auth.js.map
|
package/dist/commands/billing.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import { type CommandHandler } from './helpers.js';
|
|
2
|
-
export declare const CLOUDFLARE_HELP = "Usage: vigilbase cf <command> [options]\nAlias: vigilbase cloudflare\n\nInventory and workspace:\n zones List zones (default); --customer-id, --account-id, --zone-id\n zone <zone-id> Zone detail; --customer-id selects live details, optional --account-id\n accounts
|
|
2
|
+
export declare const CLOUDFLARE_HELP = "Usage: vigilbase cf <command> [options]\nAlias: vigilbase cloudflare\n\nInventory and workspace:\n zones List zones (default); --customer-id, --account-id, --zone-id\n zone <zone-id> Zone detail; --customer-id selects live details, optional --account-id\n accounts List accessible accounts; --customer-id, --account-id\n account <account-id> Stored account detail; --customer-id\n workspace [section] Workspace bootstrap or section; --customer-id, --account-id, --zone-id\n Sections: overview, reports, zones, rule-analyzer, accounts, checkups, settings\n\nZone reads (optional --customer-id; IDs can use --zone-id):\n dns <zone-id> DNS records, TTL and proxy state\n waf <zone-id> WAF rules, expressions, analytics and suggestions\n speed-settings <zone-id> Performance settings (internal users only)\n\nAccount reads (optional --customer-id; IDs can use --account-id):\n audit-logs <account-id> Latest provider audit events (up to 100; service-read permission)\n zero-trust <account-id> Users, Access applications, tunnels and authentication analytics\n developer-platform <account-id>\n Workers, Workers analytics and Pages\n magic-transit <account-id> Prefixes, routes and traffic analytics\n Zero Trust, Developer Platform and Magic Transit require deployment-read permission.\n\nAnalytics and checkups:\n analytics --customer-id <uuid> [--account-id <id> | --zone-id <id>] [--days 1..30]\n Default 7 days; live zone analytics uses the most recent 23 hours.\n checkup [status] Latest completed checkup; --customer-id, --account-id\n checkup start Start and persist a scan; --customer-id, --account-id\n checkup progress <run-uuid> Read saved progress once\n checkup result <run-uuid> Read the stored Cloudflare checkup result\n checkups aliases checkup; list/show alias status; run aliases start.\n\nCommon options: --json, --one-url <origin>, --timeout <milliseconds>, --help\nCustomer IDs are UUIDs; account and zone IDs are 32 hexadecimal characters.\nOne login, tenant bindings and permissions apply to every command.\nCheckup start creates a scan run. These commands do not edit provider configuration.\nSee CLOUDFLARE.md for full grammar, API mapping, data limits and examples.";
|
|
3
3
|
export declare const handleCloudflare: CommandHandler;
|
|
4
|
-
//# sourceMappingURL=cloudflare.d.ts.map
|
|
@@ -9,9 +9,9 @@ Alias: vigilbase cloudflare
|
|
|
9
9
|
Inventory and workspace:
|
|
10
10
|
zones List zones (default); --customer-id, --account-id, --zone-id
|
|
11
11
|
zone <zone-id> Zone detail; --customer-id selects live details, optional --account-id
|
|
12
|
-
accounts
|
|
12
|
+
accounts List accessible accounts; --customer-id, --account-id
|
|
13
13
|
account <account-id> Stored account detail; --customer-id
|
|
14
|
-
workspace [section]
|
|
14
|
+
workspace [section] Workspace bootstrap or section; --customer-id, --account-id, --zone-id
|
|
15
15
|
Sections: overview, reports, zones, rule-analyzer, accounts, checkups, settings
|
|
16
16
|
|
|
17
17
|
Zone reads (optional --customer-id; IDs can use --zone-id):
|
|
@@ -22,15 +22,16 @@ Zone reads (optional --customer-id; IDs can use --zone-id):
|
|
|
22
22
|
Account reads (optional --customer-id; IDs can use --account-id):
|
|
23
23
|
audit-logs <account-id> Latest provider audit events (up to 100; service-read permission)
|
|
24
24
|
zero-trust <account-id> Users, Access applications, tunnels and authentication analytics
|
|
25
|
-
developer-platform <account-id>
|
|
25
|
+
developer-platform <account-id>
|
|
26
|
+
Workers, Workers analytics and Pages
|
|
26
27
|
magic-transit <account-id> Prefixes, routes and traffic analytics
|
|
27
28
|
Zero Trust, Developer Platform and Magic Transit require deployment-read permission.
|
|
28
29
|
|
|
29
30
|
Analytics and checkups:
|
|
30
31
|
analytics --customer-id <uuid> [--account-id <id> | --zone-id <id>] [--days 1..30]
|
|
31
32
|
Default 7 days; live zone analytics uses the most recent 23 hours.
|
|
32
|
-
checkup [status]
|
|
33
|
-
checkup start
|
|
33
|
+
checkup [status] Latest completed checkup; --customer-id, --account-id
|
|
34
|
+
checkup start Start and persist a scan; --customer-id, --account-id
|
|
34
35
|
checkup progress <run-uuid> Read saved progress once
|
|
35
36
|
checkup result <run-uuid> Read the stored Cloudflare checkup result
|
|
36
37
|
checkups aliases checkup; list/show alias status; run aliases start.
|
|
@@ -338,4 +339,3 @@ export const handleCloudflare = async (ctx) => {
|
|
|
338
339
|
fields(ctx, report);
|
|
339
340
|
});
|
|
340
341
|
};
|
|
341
|
-
//# sourceMappingURL=cloudflare.js.map
|
|
@@ -96,4 +96,3 @@ export declare function requireOneClient(ctx: CommandContext): Promise<Vigilbase
|
|
|
96
96
|
export declare function withSpinner<T>(ctx: CommandContext, label: string, work: () => Promise<T>): Promise<T>;
|
|
97
97
|
export declare function ok(): ExitCode;
|
|
98
98
|
export { EXIT };
|
|
99
|
-
//# sourceMappingURL=helpers.d.ts.map
|
package/dist/commands/helpers.js
CHANGED
package/dist/commands/index.d.ts
CHANGED
package/dist/commands/index.js
CHANGED
|
@@ -17,4 +17,3 @@ export const invitationSchema = z.object({
|
|
|
17
17
|
role: z.enum(['admin', 'member', 'readonly', 'partner_owner', 'partner_sales', 'partner_operations', 'partner_finance', 'partner_readonly', 'billing_only', 'sales_only']).default('member'),
|
|
18
18
|
});
|
|
19
19
|
export const toolNameSchema = z.string().trim().min(1).max(128).regex(/^[a-z0-9-]+$/, 'Tool names must contain lowercase letters, digits, or hyphens.');
|
|
20
|
-
//# sourceMappingURL=legacy-validation.js.map
|
package/dist/commands/local.d.ts
CHANGED
|
@@ -27,4 +27,9 @@ export declare function displayPath(path: string, env?: NodeJS.ProcessEnv, platf
|
|
|
27
27
|
* `-2`, `-3`, … only when a run in the same second already used the name.
|
|
28
28
|
*/
|
|
29
29
|
export declare function defaultSnapshotName(accountId: string, at: Date, attempt?: number): string;
|
|
30
|
-
|
|
30
|
+
/**
|
|
31
|
+
* `submit` for a saved file. A loopback origin is named with `--base-url`, so a
|
|
32
|
+
* development run never suggests an upload to production; production is the
|
|
33
|
+
* CLI's default and is not named.
|
|
34
|
+
*/
|
|
35
|
+
export declare function submitCommand(path: string, origin: string): string;
|
package/dist/commands/local.js
CHANGED
|
@@ -33,7 +33,7 @@ import { buildSnapshot, collectAccount, estimateRequests, listAccounts } from '.
|
|
|
33
33
|
import { accountName, countEntries, countEntriesByKind, dataCategories, loadSnapshotFile, writeSnapshotFile, zoneCount, } from '../local/cloudflare-checkup/snapshot-file.js';
|
|
34
34
|
import { confirmDefaultYes, confirmUpload, hasInteractiveInput, promptLine } from '../local/cloudflare-checkup/prompts.js';
|
|
35
35
|
import { SAME_ADDRESS_WAIT, emailLocale, parseEmailFlag, verifyEmail } from '../local/cloudflare-checkup/email-verification.js';
|
|
36
|
-
import { SubmitClient, VerificationClient,
|
|
36
|
+
import { SubmitClient, VerificationClient, assertServerAccepts, displayRequester, isLoopbackOrigin, resolveSubmitOrigin, } from '../local/cloudflare-checkup/submit-client.js';
|
|
37
37
|
import { displayText, formatBytes, formatClock, formatDuration, maskId, readsSummary, shortSha, startCountsProgress } from '../local/cloudflare-checkup/output.js';
|
|
38
38
|
import { CheckupTui } from '../local/cloudflare-checkup/terminal-ui.js';
|
|
39
39
|
import { EXIT, assertCommandFlags, ok, outputJson } from './helpers.js';
|
|
@@ -1159,10 +1159,23 @@ function clientOptions(ctx, origin) {
|
|
|
1159
1159
|
...(ctx.values.timeout !== undefined ? { timeoutMs: ctx.config.timeoutMs } : {}),
|
|
1160
1160
|
};
|
|
1161
1161
|
}
|
|
1162
|
+
/**
|
|
1163
|
+
* Before the email is asked for (or `--email` is used): vigilbase.com says
|
|
1164
|
+
* whether local checkups are on and which CLI and snapshot schema it accepts,
|
|
1165
|
+
* so a switched-off local mode (LOCAL_MODE_DISABLED) or an old CLI
|
|
1166
|
+
* (CLI_UPGRADE_REQUIRED) never costs an emailed code. Without a usable answer
|
|
1167
|
+
* the run goes on, and the session check after the email decides as before.
|
|
1168
|
+
*/
|
|
1169
|
+
async function checkAvailability(ctx, origin, schemaVersion) {
|
|
1170
|
+
const client = new VerificationClient(clientOptions(ctx, origin));
|
|
1171
|
+
const availability = await busy(ctx, 'Checking vigilbase.com', () => client.availability());
|
|
1172
|
+
if (availability)
|
|
1173
|
+
assertServerAccepts(availability, CLI_VERSION, schemaVersion);
|
|
1174
|
+
}
|
|
1162
1175
|
/**
|
|
1163
1176
|
* The email verification (prompts on stderr, answers from piped stdin
|
|
1164
|
-
* without a terminal), then `✓ Verified j***@acme.com`.
|
|
1165
|
-
* before
|
|
1177
|
+
* without a terminal), then `✓ Verified j***@acme.com`. No address is sent
|
|
1178
|
+
* before one is entered, and cf is not touched before it is verified.
|
|
1166
1179
|
*/
|
|
1167
1180
|
async function verifyRequester(ctx, options, origin) {
|
|
1168
1181
|
const verified = await verifyEmail({
|
|
@@ -1230,16 +1243,25 @@ class CheckupSession {
|
|
|
1230
1243
|
/** Failures after the snapshot is saved that a later `submit <file>` can fix without collecting again. */
|
|
1231
1244
|
const UPLOAD_LATER_CODES = new Set(['SESSION_INVALID', 'SESSION_EXPIRED', 'SESSION_CLOSED', 'VERIFICATION_EXPIRED', 'VERIFICATION_INVALID',
|
|
1232
1245
|
'SUBMIT_FAILED', 'VIGILBASE_RATE_LIMITED', 'VIGILBASE_CHALLENGED', 'LOCAL_MODE_DISABLED']);
|
|
1246
|
+
/**
|
|
1247
|
+
* `submit` for a saved file. A loopback origin is named with `--base-url`, so a
|
|
1248
|
+
* development run never suggests an upload to production; production is the
|
|
1249
|
+
* CLI's default and is not named.
|
|
1250
|
+
*/
|
|
1251
|
+
export function submitCommand(path, origin) {
|
|
1252
|
+
const baseUrl = isLoopbackOrigin(origin) ? ` --base-url ${shellArg(origin)}` : '';
|
|
1253
|
+
return `${NPX_COMMAND} cloudflare-checkup submit ${shellArg(path)}${baseUrl}`;
|
|
1254
|
+
}
|
|
1233
1255
|
/**
|
|
1234
1256
|
* Right before such an error is reported (stderr, both modes): the `submit`
|
|
1235
1257
|
* command for the saved file. A line of its own, because hints are capped at
|
|
1236
1258
|
* 300 characters and a path has no fixed length; in the terminal UI, the
|
|
1237
1259
|
* command has a line of its own too, never wrapped, so it can be copied.
|
|
1238
1260
|
*/
|
|
1239
|
-
function noteSavedSnapshot(ctx, error, path) {
|
|
1261
|
+
function noteSavedSnapshot(ctx, error, path, origin) {
|
|
1240
1262
|
if (!(error instanceof LocalCheckupError) || !UPLOAD_LATER_CODES.has(error.code))
|
|
1241
1263
|
return;
|
|
1242
|
-
const submit =
|
|
1264
|
+
const submit = submitCommand(path, origin);
|
|
1243
1265
|
if (ctx.tui)
|
|
1244
1266
|
ctx.tui.uploadLater(submit);
|
|
1245
1267
|
else
|
|
@@ -1247,7 +1269,7 @@ function noteSavedSnapshot(ctx, error, path) {
|
|
|
1247
1269
|
}
|
|
1248
1270
|
/** Session checks that need no upload: CLI version, single use, and the bound account. */
|
|
1249
1271
|
function assertSessionUsable(session, accountId) {
|
|
1250
|
-
|
|
1272
|
+
assertServerAccepts(session, CLI_VERSION, SNAPSHOT_SCHEMA_VERSION);
|
|
1251
1273
|
if (session.state === 'completed')
|
|
1252
1274
|
throw new LocalCheckupError('SESSION_USED', 'This checkup already has results, so it cannot accept a new snapshot.');
|
|
1253
1275
|
// A checkup the email verification just started is never processing; this guards any other state.
|
|
@@ -1288,7 +1310,8 @@ async function runOneCommand(ctx, options) {
|
|
|
1288
1310
|
// A bad --out never costs an emailed code (collectSnapshot checks it again).
|
|
1289
1311
|
if (options.out !== undefined)
|
|
1290
1312
|
await assertOutWritable(options.out, Boolean(ctx.values.isOverwrite));
|
|
1291
|
-
// 1-3.
|
|
1313
|
+
// 1-3. Availability, then the email, then the checkup it started are checked before cf is touched.
|
|
1314
|
+
await checkAvailability(ctx, origin, SNAPSHOT_SCHEMA_VERSION);
|
|
1292
1315
|
const checkup = new CheckupSession(ctx, origin, await verifyRequester(ctx, options, origin));
|
|
1293
1316
|
const early = await busy(ctx, 'Checking the checkup', () => checkup.getSession());
|
|
1294
1317
|
assertSessionUsable(early, options.accountId);
|
|
@@ -1312,7 +1335,7 @@ async function runOneCommand(ctx, options) {
|
|
|
1312
1335
|
result = await uploadLoaded(ctx, { checkup, session, origin, loaded });
|
|
1313
1336
|
}
|
|
1314
1337
|
catch (error) {
|
|
1315
|
-
noteSavedSnapshot(ctx, error, outcome.path);
|
|
1338
|
+
noteSavedSnapshot(ctx, error, outcome.path, origin);
|
|
1316
1339
|
throw error;
|
|
1317
1340
|
}
|
|
1318
1341
|
if (ctx.mode === 'json') {
|
|
@@ -1410,7 +1433,8 @@ async function submitFile(ctx, options) {
|
|
|
1410
1433
|
ctx.writer.stderr(head);
|
|
1411
1434
|
else
|
|
1412
1435
|
ctx.writer.stdout(head);
|
|
1413
|
-
// The file
|
|
1436
|
+
// The file, then vigilbase.com's availability, are checked before the email is verified, so neither costs a code.
|
|
1437
|
+
await checkAvailability(ctx, origin, loaded.snapshot.schemaVersion);
|
|
1414
1438
|
const checkup = new CheckupSession(ctx, origin, await verifyRequester(ctx, options, origin));
|
|
1415
1439
|
const session = await busy(ctx, 'Checking the checkup', () => checkup.getSession());
|
|
1416
1440
|
const result = await uploadLoaded(ctx, { checkup, session, origin, loaded });
|
|
@@ -1455,7 +1479,7 @@ async function uploadLoaded(ctx, input) {
|
|
|
1455
1479
|
const { checkup, session, origin, loaded } = input;
|
|
1456
1480
|
const { snapshot } = loaded;
|
|
1457
1481
|
assertFresh(snapshot);
|
|
1458
|
-
|
|
1482
|
+
assertServerAccepts(session, CLI_VERSION, snapshot.schemaVersion);
|
|
1459
1483
|
if (session.accountId !== null && session.accountId !== snapshot.accountId) {
|
|
1460
1484
|
throw new LocalCheckupError('ACCOUNT_MISMATCH', `This checkup is bound to Cloudflare account ${maskId(session.accountId)}, but the snapshot is for ${maskId(snapshot.accountId)}. Nothing was uploaded.`);
|
|
1461
1485
|
}
|
|
@@ -1517,4 +1541,3 @@ async function uploadLoaded(ctx, input) {
|
|
|
1517
1541
|
...(result.resultsUrl !== undefined ? { resultsUrl: result.resultsUrl } : {}),
|
|
1518
1542
|
};
|
|
1519
1543
|
}
|
|
1520
|
-
//# sourceMappingURL=local.js.map
|
package/dist/commands/one.d.ts
CHANGED
|
@@ -3,4 +3,3 @@ import { type CommandContext, type CommandHandler } from './helpers.js';
|
|
|
3
3
|
export declare function buildOneOperation(ctx: CommandContext): OneOperation;
|
|
4
4
|
export declare const handleOne: CommandHandler;
|
|
5
5
|
export declare const ONE_HELP: Record<string, string>;
|
|
6
|
-
//# sourceMappingURL=one.d.ts.map
|
package/dist/commands/one.js
CHANGED
|
@@ -153,7 +153,7 @@ export const handleOne = async (ctx) => {
|
|
|
153
153
|
};
|
|
154
154
|
export const ONE_HELP = {
|
|
155
155
|
customers: `Usage: vigilbase customers <command> [--json]
|
|
156
|
-
list
|
|
156
|
+
list List visible customers (also the default)
|
|
157
157
|
show <customer-id> Full customer details
|
|
158
158
|
summary <customer-id> Lightweight service/integration summary
|
|
159
159
|
services <customer-id> Service records
|
|
@@ -163,7 +163,7 @@ export const ONE_HELP = {
|
|
|
163
163
|
watchdog-targets <customer-id> Security/uptime targets
|
|
164
164
|
watchdog-scans <customer-id> --limit 1..100 --offset 0..1000000 --target-id UUID
|
|
165
165
|
reports <customer-id> Recon reports; --limit 1..100
|
|
166
|
-
report <customer-id> <report-id>
|
|
166
|
+
report <customer-id> <report-id> Recon report detail
|
|
167
167
|
investigations <customer-id> --limit 1..100 --cursor TEXT or --before ISO; --issue-id TEXT
|
|
168
168
|
investigation <customer-id> <id> --revision 1..2147483647
|
|
169
169
|
contracts <customer-id> --status draft|pending|active|expired|terminated
|
|
@@ -186,10 +186,10 @@ These commands read organization context; they do not switch the active organiza
|
|
|
186
186
|
health Metrics backend and alerting readiness (also the default)
|
|
187
187
|
probes Registered probe heartbeats (internal operators)
|
|
188
188
|
probe-health Live probe health, with database fallback
|
|
189
|
-
metrics <target-id>...
|
|
190
|
-
targets <customer-id>
|
|
191
|
-
status <customer-id>
|
|
192
|
-
history <customer-id>
|
|
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
|
|
193
193
|
All operations require read:monitoring and the API's tenant access checks.
|
|
194
194
|
History defaults to 7d. Health metadata preserves unknown, partial, and unavailable states.`,
|
|
195
195
|
support: `Usage: vigilbase support tickets [--all] [--limit 1..100] [--json]
|
|
@@ -197,4 +197,3 @@ Lists current organization's open tickets; --all includes closed tickets.
|
|
|
197
197
|
The API defaults to 50 results. Requires support:access and a linked Pylon account.
|
|
198
198
|
The response retains hasMore; the API does not expose cursor pagination.`,
|
|
199
199
|
};
|
|
200
|
-
//# sourceMappingURL=one.js.map
|
|
@@ -2,16 +2,38 @@ import { z } from 'zod';
|
|
|
2
2
|
import { toolNameSchema, validateArguments } from './legacy-validation.js';
|
|
3
3
|
import { NetworkError } from '../lib/network.js';
|
|
4
4
|
import { VigilbaseApiError } from '../lib/client.js';
|
|
5
|
-
import { getOneAccessToken, readCredentials } from '../auth/index.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
|
-
|
|
14
|
-
const authenticated =
|
|
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,
|
|
@@ -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
|
-
|
|
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
|
}
|
|
@@ -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
|
-
|
|
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
|
|
170
|
-
const saved = await readCredentials(ctx.config);
|
|
171
|
-
|
|
172
|
-
|
|
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
|
|
200
|
+
const session = await client.getSession();
|
|
175
201
|
return { authenticated: Boolean(session.user?.id) };
|
|
176
202
|
}
|
|
177
203
|
catch (error) {
|
|
@@ -181,15 +207,23 @@ 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 } : {}),
|
|
@@ -198,8 +232,9 @@ export const handleDoctor = async (ctx) => {
|
|
|
198
232
|
const checks = {
|
|
199
233
|
publicApi: checkResult(publicResult, `${ctx.config.publicBaseUrl}/api/agent/tools`),
|
|
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
|
package/dist/commands/runs.d.ts
CHANGED
package/dist/commands/runs.js
CHANGED
|
@@ -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]
|
|
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\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";
|