workos 0.10.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +20 -1
  2. package/dist/bin.js +108 -20
  3. package/dist/bin.js.map +1 -1
  4. package/dist/commands/claim.d.ts +11 -0
  5. package/dist/commands/claim.js +111 -0
  6. package/dist/commands/claim.js.map +1 -0
  7. package/dist/commands/debug.d.ts +16 -0
  8. package/dist/commands/debug.js +350 -0
  9. package/dist/commands/debug.js.map +1 -0
  10. package/dist/commands/env.js +11 -4
  11. package/dist/commands/env.js.map +1 -1
  12. package/dist/lib/__test-helpers__/mock-unclaimed-env-api-error.d.ts +7 -0
  13. package/dist/lib/__test-helpers__/mock-unclaimed-env-api-error.js +12 -0
  14. package/dist/lib/__test-helpers__/mock-unclaimed-env-api-error.js.map +1 -0
  15. package/dist/lib/agent-interface.js +17 -3
  16. package/dist/lib/agent-interface.js.map +1 -1
  17. package/dist/lib/config-store.d.ts +26 -3
  18. package/dist/lib/config-store.js +82 -0
  19. package/dist/lib/config-store.js.map +1 -1
  20. package/dist/lib/credential-proxy.d.ts +10 -1
  21. package/dist/lib/credential-proxy.js +96 -38
  22. package/dist/lib/credential-proxy.js.map +1 -1
  23. package/dist/lib/env-writer.d.ts +1 -0
  24. package/dist/lib/env-writer.js.map +1 -1
  25. package/dist/lib/installer-core.d.ts +3 -3
  26. package/dist/lib/resolve-install-credentials.d.ts +11 -0
  27. package/dist/lib/resolve-install-credentials.js +53 -0
  28. package/dist/lib/resolve-install-credentials.js.map +1 -0
  29. package/dist/lib/run-with-core.js +5 -0
  30. package/dist/lib/run-with-core.js.map +1 -1
  31. package/dist/lib/unclaimed-env-api.d.ts +42 -0
  32. package/dist/lib/unclaimed-env-api.js +139 -0
  33. package/dist/lib/unclaimed-env-api.js.map +1 -0
  34. package/dist/lib/unclaimed-env-provision.d.ts +24 -0
  35. package/dist/lib/unclaimed-env-provision.js +77 -0
  36. package/dist/lib/unclaimed-env-provision.js.map +1 -0
  37. package/dist/lib/unclaimed-warning.d.ts +15 -0
  38. package/dist/lib/unclaimed-warning.js +74 -0
  39. package/dist/lib/unclaimed-warning.js.map +1 -0
  40. package/dist/utils/box.d.ts +5 -0
  41. package/dist/utils/box.js +14 -0
  42. package/dist/utils/box.js.map +1 -0
  43. package/dist/utils/help-json.js +15 -0
  44. package/dist/utils/help-json.js.map +1 -1
  45. package/package.json +1 -1
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `workos claim` — claim an unclaimed environment.
3
+ *
4
+ * Reads claim token from active environment, generates a nonce via
5
+ * createClaimNonce(), opens browser to dashboard claim URL, and polls
6
+ * until the environment is claimed.
7
+ */
8
+ /**
9
+ * Run the claim flow.
10
+ */
11
+ export declare function runClaim(): Promise<void>;
@@ -0,0 +1,111 @@
1
+ /**
2
+ * `workos claim` — claim an unclaimed environment.
3
+ *
4
+ * Reads claim token from active environment, generates a nonce via
5
+ * createClaimNonce(), opens browser to dashboard claim URL, and polls
6
+ * until the environment is claimed.
7
+ */
8
+ import open from 'opn';
9
+ import clack from '../utils/clack.js';
10
+ import { getActiveEnvironment, isUnclaimedEnvironment, markEnvironmentClaimed } from '../lib/config-store.js';
11
+ import { createClaimNonce, UnclaimedEnvApiError } from '../lib/unclaimed-env-api.js';
12
+ import { logInfo, logError } from '../utils/debug.js';
13
+ import { isJsonMode, outputJson, exitWithError } from '../utils/output.js';
14
+ import { sleep } from '../lib/helper-functions.js';
15
+ const POLL_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
16
+ const POLL_INTERVAL_MS = 5_000; // 5 seconds
17
+ const MAX_CONSECUTIVE_FAILURES = 10;
18
+ /**
19
+ * Run the claim flow.
20
+ */
21
+ export async function runClaim() {
22
+ const activeEnv = getActiveEnvironment();
23
+ if (!activeEnv || !isUnclaimedEnvironment(activeEnv)) {
24
+ if (isJsonMode()) {
25
+ outputJson({ status: 'no_unclaimed_environment', message: 'No unclaimed environment found. Nothing to claim.' });
26
+ }
27
+ else {
28
+ clack.log.info('No unclaimed environment found. Nothing to claim.');
29
+ }
30
+ return;
31
+ }
32
+ // claimToken and clientId guaranteed present by UnclaimedEnvironmentConfig
33
+ logInfo('[claim] Starting claim flow for environment:', activeEnv.name);
34
+ try {
35
+ clack.log.step('Generating claim link...');
36
+ const result = await createClaimNonce(activeEnv.clientId, activeEnv.claimToken);
37
+ if (result.alreadyClaimed) {
38
+ markEnvironmentClaimed();
39
+ if (isJsonMode()) {
40
+ outputJson({ status: 'already_claimed', message: 'Environment already claimed!' });
41
+ }
42
+ else {
43
+ clack.log.success('Environment already claimed!');
44
+ clack.log.info('Run `workos auth login` to connect your account.');
45
+ }
46
+ return;
47
+ }
48
+ const claimUrl = `https://dashboard.workos.com/claim?nonce=${result.nonce}`;
49
+ if (isJsonMode()) {
50
+ outputJson({ status: 'claim_url', claimUrl, nonce: result.nonce });
51
+ return;
52
+ }
53
+ clack.log.info(`Open this URL to claim your environment:\n\n ${claimUrl}`);
54
+ try {
55
+ open(claimUrl, { wait: false });
56
+ clack.log.info('Browser opened automatically');
57
+ }
58
+ catch (openError) {
59
+ logError('[claim] Failed to open browser:', openError instanceof Error ? openError.message : String(openError));
60
+ clack.log.info('Could not open browser — open the URL above manually.');
61
+ }
62
+ // Poll for claim completion
63
+ const spinner = clack.spinner();
64
+ spinner.start('Waiting for claim...');
65
+ const startTime = Date.now();
66
+ let consecutiveFailures = 0;
67
+ while (Date.now() - startTime < POLL_TIMEOUT_MS) {
68
+ await sleep(POLL_INTERVAL_MS);
69
+ try {
70
+ const check = await createClaimNonce(activeEnv.clientId, activeEnv.claimToken);
71
+ if (check.alreadyClaimed) {
72
+ spinner.stop('Environment claimed!');
73
+ markEnvironmentClaimed();
74
+ clack.log.info('Run `workos auth login` to connect your account.');
75
+ return;
76
+ }
77
+ consecutiveFailures = 0;
78
+ }
79
+ catch (pollError) {
80
+ const statusCode = pollError instanceof UnclaimedEnvApiError ? pollError.statusCode : undefined;
81
+ if (statusCode === 401) {
82
+ // 401 means the server invalidated the claim token — this happens
83
+ // when the environment is claimed. Safe to promote to sandbox.
84
+ spinner.stop('Claim token is invalid or expired.');
85
+ markEnvironmentClaimed();
86
+ clack.log.warn('Run `workos auth login` to set up your environment.');
87
+ return;
88
+ }
89
+ consecutiveFailures++;
90
+ logError('[claim] Poll error:', pollError instanceof Error ? pollError.message : 'Unknown');
91
+ if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
92
+ spinner.stop('Too many connection failures');
93
+ clack.log.error(`Polling failed ${consecutiveFailures} times in a row. Check your network and try again.\n` +
94
+ `You can also complete the claim at: ${claimUrl}`);
95
+ return;
96
+ }
97
+ if (consecutiveFailures >= 3) {
98
+ spinner.message('Still waiting... (connection issues detected)');
99
+ }
100
+ }
101
+ }
102
+ spinner.stop('Claim timed out');
103
+ clack.log.info('Complete the claim in your browser, then run `workos env list` to verify.');
104
+ }
105
+ catch (error) {
106
+ const message = error instanceof Error ? error.message : 'Unknown error';
107
+ logError('[claim] Error:', message);
108
+ exitWithError({ code: 'claim_failed', message: `Claim failed: ${message}` });
109
+ }
110
+ }
111
+ //# sourceMappingURL=claim.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claim.js","sourceRoot":"","sources":["../../src/commands/claim.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `workos claim` — claim an unclaimed environment.\n *\n * Reads claim token from active environment, generates a nonce via\n * createClaimNonce(), opens browser to dashboard claim URL, and polls\n * until the environment is claimed.\n */\n\nimport open from 'opn';\nimport clack from '../utils/clack.js';\nimport { getActiveEnvironment, isUnclaimedEnvironment, markEnvironmentClaimed } from '../lib/config-store.js';\nimport { createClaimNonce, UnclaimedEnvApiError } from '../lib/unclaimed-env-api.js';\nimport { logInfo, logError } from '../utils/debug.js';\nimport { isJsonMode, outputJson, exitWithError } from '../utils/output.js';\nimport { sleep } from '../lib/helper-functions.js';\n\nconst POLL_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes\nconst POLL_INTERVAL_MS = 5_000; // 5 seconds\nconst MAX_CONSECUTIVE_FAILURES = 10;\n\n/**\n * Run the claim flow.\n */\nexport async function runClaim(): Promise<void> {\n const activeEnv = getActiveEnvironment();\n\n if (!activeEnv || !isUnclaimedEnvironment(activeEnv)) {\n if (isJsonMode()) {\n outputJson({ status: 'no_unclaimed_environment', message: 'No unclaimed environment found. Nothing to claim.' });\n } else {\n clack.log.info('No unclaimed environment found. Nothing to claim.');\n }\n return;\n }\n\n // claimToken and clientId guaranteed present by UnclaimedEnvironmentConfig\n\n logInfo('[claim] Starting claim flow for environment:', activeEnv.name);\n\n try {\n clack.log.step('Generating claim link...');\n\n const result = await createClaimNonce(activeEnv.clientId, activeEnv.claimToken);\n\n if (result.alreadyClaimed) {\n markEnvironmentClaimed();\n if (isJsonMode()) {\n outputJson({ status: 'already_claimed', message: 'Environment already claimed!' });\n } else {\n clack.log.success('Environment already claimed!');\n clack.log.info('Run `workos auth login` to connect your account.');\n }\n return;\n }\n\n const claimUrl = `https://dashboard.workos.com/claim?nonce=${result.nonce}`;\n\n if (isJsonMode()) {\n outputJson({ status: 'claim_url', claimUrl, nonce: result.nonce });\n return;\n }\n\n clack.log.info(`Open this URL to claim your environment:\\n\\n ${claimUrl}`);\n\n try {\n open(claimUrl, { wait: false });\n clack.log.info('Browser opened automatically');\n } catch (openError) {\n logError('[claim] Failed to open browser:', openError instanceof Error ? openError.message : String(openError));\n clack.log.info('Could not open browser — open the URL above manually.');\n }\n\n // Poll for claim completion\n const spinner = clack.spinner();\n spinner.start('Waiting for claim...');\n\n const startTime = Date.now();\n let consecutiveFailures = 0;\n\n while (Date.now() - startTime < POLL_TIMEOUT_MS) {\n await sleep(POLL_INTERVAL_MS);\n try {\n const check = await createClaimNonce(activeEnv.clientId, activeEnv.claimToken);\n if (check.alreadyClaimed) {\n spinner.stop('Environment claimed!');\n markEnvironmentClaimed();\n clack.log.info('Run `workos auth login` to connect your account.');\n return;\n }\n consecutiveFailures = 0;\n } catch (pollError) {\n const statusCode = pollError instanceof UnclaimedEnvApiError ? pollError.statusCode : undefined;\n if (statusCode === 401) {\n // 401 means the server invalidated the claim token — this happens\n // when the environment is claimed. Safe to promote to sandbox.\n spinner.stop('Claim token is invalid or expired.');\n markEnvironmentClaimed();\n clack.log.warn('Run `workos auth login` to set up your environment.');\n return;\n }\n consecutiveFailures++;\n logError('[claim] Poll error:', pollError instanceof Error ? pollError.message : 'Unknown');\n if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {\n spinner.stop('Too many connection failures');\n clack.log.error(\n `Polling failed ${consecutiveFailures} times in a row. Check your network and try again.\\n` +\n `You can also complete the claim at: ${claimUrl}`,\n );\n return;\n }\n if (consecutiveFailures >= 3) {\n spinner.message('Still waiting... (connection issues detected)');\n }\n }\n }\n\n spinner.stop('Claim timed out');\n clack.log.info('Complete the claim in your browser, then run `workos env list` to verify.');\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error';\n logError('[claim] Error:', message);\n exitWithError({ code: 'claim_failed', message: `Claim failed: ${message}` });\n }\n}\n"]}
@@ -0,0 +1,16 @@
1
+ export declare function runDebugState({ showSecrets }: {
2
+ showSecrets: boolean;
3
+ }): Promise<void>;
4
+ export declare function runDebugReset({ force, credentialsOnly, configOnly, }: {
5
+ force: boolean;
6
+ credentialsOnly: boolean;
7
+ configOnly: boolean;
8
+ }): Promise<void>;
9
+ export declare function runDebugSimulate({ expiredToken, noKeyring, unclaimed, noAuth, }: {
10
+ expiredToken: boolean;
11
+ noKeyring: boolean;
12
+ unclaimed: boolean;
13
+ noAuth: boolean;
14
+ }): Promise<void>;
15
+ export declare function runDebugEnv(): Promise<void>;
16
+ export declare function runDebugToken(): Promise<void>;
@@ -0,0 +1,350 @@
1
+ import chalk from 'chalk';
2
+ import clack from '../utils/clack.js';
3
+ import { getCredentials, saveCredentials, clearCredentials, isTokenExpired, diagnoseCredentials, getCredentialsPath, setInsecureStorage, } from '../lib/credentials.js';
4
+ import { getConfig, saveConfig, clearConfig, getConfigPath, setInsecureConfigStorage, diagnoseConfig, } from '../lib/config-store.js';
5
+ import { isJsonMode, outputJson, exitWithError } from '../utils/output.js';
6
+ import { isNonInteractiveEnvironment } from '../utils/environment.js';
7
+ function maskSecret(value) {
8
+ if (!value)
9
+ return undefined;
10
+ if (value.length <= 8)
11
+ return '****';
12
+ return value.slice(0, 4) + '****' + value.slice(-4);
13
+ }
14
+ function formatTimeRemaining(ms) {
15
+ if (ms <= 0)
16
+ return 'expired';
17
+ const seconds = Math.floor(ms / 1000);
18
+ const minutes = Math.floor(seconds / 60);
19
+ const hours = Math.floor(minutes / 60);
20
+ if (hours > 0)
21
+ return `${hours}h ${minutes % 60}m`;
22
+ if (minutes > 0)
23
+ return `${minutes}m ${seconds % 60}s`;
24
+ return `${seconds}s`;
25
+ }
26
+ function parseJwt(token) {
27
+ try {
28
+ const parts = token.split('.');
29
+ if (parts.length !== 3)
30
+ return null;
31
+ return JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf-8'));
32
+ }
33
+ catch {
34
+ return null;
35
+ }
36
+ }
37
+ function determineCredentialSource(diagnostics) {
38
+ const hasKeyring = diagnostics.some((l) => l.startsWith('keyring: found'));
39
+ const hasFile = diagnostics.some((l) => l.includes('exists=true'));
40
+ const isInsecure = diagnostics.some((l) => l.includes('insecureStorage=true'));
41
+ if (isInsecure)
42
+ return hasFile ? 'file' : 'none';
43
+ if (hasKeyring)
44
+ return 'keyring';
45
+ if (hasFile)
46
+ return 'file';
47
+ return 'none';
48
+ }
49
+ // --- debug state ---
50
+ export async function runDebugState({ showSecrets }) {
51
+ const creds = getCredentials();
52
+ const config = getConfig();
53
+ const diagnostics = diagnoseCredentials();
54
+ const credSource = determineCredentialSource(diagnostics);
55
+ const maybeRedact = showSecrets ? (v) => v : maskSecret;
56
+ const credentialsOutput = { present: !!creds, source: credSource };
57
+ if (creds) {
58
+ const timeRemaining = creds.expiresAt - Date.now();
59
+ const expired = isTokenExpired(creds);
60
+ Object.assign(credentialsOutput, {
61
+ userId: creds.userId,
62
+ email: creds.email ?? null,
63
+ accessToken: maybeRedact(creds.accessToken),
64
+ refreshToken: creds.refreshToken ? 'present' : 'absent',
65
+ expiresAt: creds.expiresAt,
66
+ expiresIn: expired
67
+ ? `expired ${formatTimeRemaining(-timeRemaining)} ago`
68
+ : `in ${formatTimeRemaining(timeRemaining)}`,
69
+ isExpired: expired,
70
+ });
71
+ if (creds.staging) {
72
+ credentialsOutput.staging = {
73
+ clientId: creds.staging.clientId,
74
+ apiKey: maybeRedact(creds.staging.apiKey),
75
+ fetchedAt: creds.staging.fetchedAt,
76
+ };
77
+ }
78
+ }
79
+ const configOutput = { present: !!config };
80
+ if (config) {
81
+ configOutput.activeEnvironment = config.activeEnvironment ?? null;
82
+ configOutput.environments = Object.fromEntries(Object.entries(config.environments).map(([key, env]) => [
83
+ key,
84
+ {
85
+ name: env.name,
86
+ type: env.type,
87
+ apiKey: maybeRedact(env.apiKey),
88
+ clientId: env.clientId ?? null,
89
+ endpoint: env.endpoint ?? null,
90
+ ...(env.type === 'unclaimed' && { claimToken: maybeRedact(env.claimToken) }),
91
+ },
92
+ ]));
93
+ }
94
+ const configDiagnostics = diagnoseConfig();
95
+ const configSource = determineCredentialSource(configDiagnostics);
96
+ configOutput.source = configSource;
97
+ const result = {
98
+ credentials: credentialsOutput,
99
+ config: configOutput,
100
+ storage: {
101
+ credentialsPath: getCredentialsPath(),
102
+ configPath: getConfigPath(),
103
+ credentialDiagnostics: diagnostics,
104
+ configDiagnostics,
105
+ },
106
+ };
107
+ if (isJsonMode()) {
108
+ outputJson(result);
109
+ return;
110
+ }
111
+ console.log(chalk.bold('Credentials'));
112
+ console.log(` present: ${creds ? chalk.green('true') : chalk.yellow('false')}`);
113
+ console.log(` source: ${credSource}`);
114
+ if (creds) {
115
+ console.log(` userId: ${creds.userId}`);
116
+ console.log(` email: ${creds.email ?? chalk.dim('none')}`);
117
+ console.log(` token: ${maybeRedact(creds.accessToken)}`);
118
+ console.log(` refresh: ${creds.refreshToken ? 'present' : 'absent'}`);
119
+ const expired = isTokenExpired(creds);
120
+ const timeRemaining = creds.expiresAt - Date.now();
121
+ console.log(` expires: ${expired ? chalk.red(`expired ${formatTimeRemaining(-timeRemaining)} ago`) : chalk.green(`in ${formatTimeRemaining(timeRemaining)}`)}`);
122
+ if (creds.staging) {
123
+ console.log(` staging: clientId=${creds.staging.clientId} apiKey=${maybeRedact(creds.staging.apiKey)}`);
124
+ }
125
+ }
126
+ console.log();
127
+ console.log(chalk.bold('Config'));
128
+ console.log(` present: ${config ? chalk.green('true') : chalk.yellow('false')}`);
129
+ console.log(` source: ${configSource}`);
130
+ if (config) {
131
+ console.log(` active: ${config.activeEnvironment ?? chalk.dim('none')}`);
132
+ for (const [key, env] of Object.entries(config.environments)) {
133
+ console.log(` env[${key}]: type=${env.type} apiKey=${maybeRedact(env.apiKey)}`);
134
+ if (env.type === 'unclaimed')
135
+ console.log(` claimToken=${maybeRedact(env.claimToken)}`);
136
+ }
137
+ }
138
+ console.log();
139
+ console.log(chalk.bold('Storage — Credentials'));
140
+ console.log(` path: ${getCredentialsPath()}`);
141
+ for (const line of diagnostics) {
142
+ console.log(` ${chalk.dim(line)}`);
143
+ }
144
+ console.log();
145
+ console.log(chalk.bold('Storage — Config'));
146
+ console.log(` path: ${getConfigPath()}`);
147
+ for (const line of configDiagnostics) {
148
+ console.log(` ${chalk.dim(line)}`);
149
+ }
150
+ }
151
+ // --- debug reset ---
152
+ export async function runDebugReset({ force, credentialsOnly, configOnly, }) {
153
+ // Both flags = clear both (same as neither)
154
+ const clearCreds = !configOnly || credentialsOnly;
155
+ const clearConf = !credentialsOnly || configOnly;
156
+ const targets = [clearCreds && 'credentials', clearConf && 'config'].filter(Boolean).join(' and ');
157
+ if (!force) {
158
+ if (isNonInteractiveEnvironment()) {
159
+ exitWithError({
160
+ code: 'non_interactive_reset',
161
+ message: 'Use --force to reset in non-interactive mode',
162
+ });
163
+ }
164
+ const confirmed = await clack.confirm({
165
+ message: `Clear all ${targets}? This cannot be undone.`,
166
+ });
167
+ if (clack.isCancel(confirmed) || !confirmed) {
168
+ if (isJsonMode()) {
169
+ outputJson({ cleared: false, cancelled: true });
170
+ }
171
+ else {
172
+ clack.log.info('Reset cancelled');
173
+ }
174
+ return;
175
+ }
176
+ }
177
+ if (clearCreds)
178
+ clearCredentials();
179
+ if (clearConf)
180
+ clearConfig();
181
+ if (isJsonMode()) {
182
+ outputJson({ cleared: true, credentials: clearCreds, config: clearConf });
183
+ }
184
+ else {
185
+ clack.log.success(`Cleared ${targets}`);
186
+ }
187
+ }
188
+ // --- debug simulate ---
189
+ export async function runDebugSimulate({ expiredToken, noKeyring, unclaimed, noAuth, }) {
190
+ // Validate: at least one flag
191
+ if (!expiredToken && !noKeyring && !unclaimed && !noAuth) {
192
+ exitWithError({
193
+ code: 'no_simulation_flags',
194
+ message: 'Specify at least one simulation flag: --expired-token, --no-keyring, --unclaimed, --no-auth',
195
+ });
196
+ }
197
+ // Validate: contradictory
198
+ if (expiredToken && noAuth) {
199
+ exitWithError({
200
+ code: 'contradictory_flags',
201
+ message: "Cannot combine --expired-token and --no-auth (can't expire a cleared token)",
202
+ });
203
+ }
204
+ const actions = [];
205
+ // Apply in order: storage tier first, then credential mutations, then config mutations
206
+ if (noKeyring) {
207
+ // Migrate current state to file storage
208
+ const creds = getCredentials();
209
+ const config = getConfig();
210
+ setInsecureStorage(true);
211
+ setInsecureConfigStorage(true);
212
+ if (creds)
213
+ saveCredentials(creds);
214
+ if (config)
215
+ saveConfig(config);
216
+ actions.push('Forced file-only storage (keyring bypassed)');
217
+ }
218
+ if (expiredToken) {
219
+ const creds = getCredentials();
220
+ if (!creds) {
221
+ exitWithError({
222
+ code: 'no_credentials',
223
+ message: 'Cannot simulate expired token — no credentials found. Log in first.',
224
+ });
225
+ }
226
+ saveCredentials({ ...creds, expiresAt: Date.now() - 60_000 });
227
+ actions.push('Set token expiresAt to 1 minute ago');
228
+ }
229
+ if (noAuth) {
230
+ clearCredentials();
231
+ actions.push('Cleared credentials (config preserved)');
232
+ }
233
+ if (unclaimed) {
234
+ const config = getConfig() ?? { environments: {} };
235
+ const envName = 'simulated-unclaimed';
236
+ config.environments[envName] = {
237
+ name: envName,
238
+ type: 'unclaimed',
239
+ apiKey: 'sk_test_simulated_unclaimed_000000000000',
240
+ clientId: 'client_simulated',
241
+ claimToken: 'claim_simulated_token_000000000000',
242
+ };
243
+ config.activeEnvironment = envName;
244
+ saveConfig(config);
245
+ actions.push(`Created unclaimed environment "${envName}" and set as active`);
246
+ }
247
+ if (isJsonMode()) {
248
+ outputJson({ simulated: true, actions });
249
+ }
250
+ else {
251
+ for (const action of actions) {
252
+ clack.log.success(action);
253
+ }
254
+ }
255
+ }
256
+ const ENV_VAR_CATALOG = [
257
+ { name: 'WORKOS_API_KEY', effect: 'Bypasses credential resolution — used directly for API calls' },
258
+ { name: 'WORKOS_CLIENT_ID', effect: 'Overrides client ID from settings' },
259
+ { name: 'WORKOS_FORCE_TTY', effect: 'Forces human (non-JSON) output mode, even when piped' },
260
+ { name: 'WORKOS_NO_PROMPT', effect: 'Forces non-interactive/JSON mode' },
261
+ { name: 'WORKOS_TELEMETRY', effect: 'Set to "false" to disable telemetry' },
262
+ { name: 'WORKOS_API_URL', effect: 'Overrides API base URL (default: https://api.workos.com)' },
263
+ { name: 'WORKOS_DASHBOARD_URL', effect: 'Overrides dashboard URL (default: https://dashboard.workos.com)' },
264
+ { name: 'WORKOS_AUTHKIT_DOMAIN', effect: 'Overrides AuthKit domain from settings' },
265
+ { name: 'WORKOS_LLM_GATEWAY_URL', effect: 'Overrides LLM gateway URL from settings' },
266
+ { name: 'INSTALLER_DEV', effect: 'Enables dev mode — loads .env.local at startup' },
267
+ { name: 'INSTALLER_DISABLE_PROXY', effect: 'Disables the credential proxy for gateway auth' },
268
+ ];
269
+ export async function runDebugEnv() {
270
+ const vars = ENV_VAR_CATALOG.map(({ name, effect }) => ({
271
+ name,
272
+ value: process.env[name],
273
+ effect,
274
+ }));
275
+ const setVars = vars.filter((v) => v.value !== undefined);
276
+ const unsetVars = vars.filter((v) => v.value === undefined);
277
+ if (isJsonMode()) {
278
+ outputJson({
279
+ variables: Object.fromEntries(vars.map((v) => [v.name, { value: v.value ?? null, effect: v.effect }])),
280
+ set: setVars.map((v) => v.name),
281
+ unset: unsetVars.map((v) => v.name),
282
+ });
283
+ return;
284
+ }
285
+ if (setVars.length > 0) {
286
+ console.log(chalk.bold('Set'));
287
+ for (const v of setVars) {
288
+ console.log(` ${chalk.green(v.name)}=${v.value}`);
289
+ console.log(` ${chalk.dim(v.effect)}`);
290
+ }
291
+ console.log();
292
+ }
293
+ console.log(chalk.bold(`Unset${setVars.length > 0 ? '' : ' (none active)'}`));
294
+ for (const v of unsetVars) {
295
+ console.log(` ${chalk.dim(v.name)} — ${chalk.dim(v.effect)}`);
296
+ }
297
+ }
298
+ // --- debug token ---
299
+ export async function runDebugToken() {
300
+ const creds = getCredentials();
301
+ if (!creds) {
302
+ if (isJsonMode()) {
303
+ outputJson({ present: false });
304
+ }
305
+ else {
306
+ console.log(chalk.yellow('No credentials found'));
307
+ }
308
+ return;
309
+ }
310
+ const claims = parseJwt(creds.accessToken);
311
+ const expired = isTokenExpired(creds);
312
+ const timeRemaining = creds.expiresAt - Date.now();
313
+ if (isJsonMode()) {
314
+ outputJson({
315
+ present: true,
316
+ format: claims ? 'jwt' : 'opaque',
317
+ expired,
318
+ expiresAt: creds.expiresAt,
319
+ expiresIn: expired
320
+ ? `expired ${formatTimeRemaining(-timeRemaining)} ago`
321
+ : `in ${formatTimeRemaining(timeRemaining)}`,
322
+ claims: claims ?? null,
323
+ refreshToken: { present: !!creds.refreshToken },
324
+ });
325
+ return;
326
+ }
327
+ if (claims) {
328
+ console.log(chalk.bold('JWT Token'));
329
+ console.log(` expires: ${expired ? chalk.red(`expired ${formatTimeRemaining(-timeRemaining)} ago`) : chalk.green(`in ${formatTimeRemaining(timeRemaining)}`)}`);
330
+ console.log();
331
+ console.log(chalk.bold('Claims'));
332
+ for (const [key, value] of Object.entries(claims)) {
333
+ if (key === 'exp' || key === 'iat' || key === 'nbf') {
334
+ const date = new Date(value * 1000).toISOString();
335
+ console.log(` ${key}: ${value} (${date})`);
336
+ }
337
+ else {
338
+ console.log(` ${key}: ${JSON.stringify(value)}`);
339
+ }
340
+ }
341
+ }
342
+ else {
343
+ console.log(chalk.bold('Opaque Token'));
344
+ console.log(chalk.dim(' Token is not a JWT — cannot decode claims'));
345
+ console.log(` expires: ${expired ? chalk.red(`expired ${formatTimeRemaining(-timeRemaining)} ago`) : chalk.green(`in ${formatTimeRemaining(timeRemaining)}`)}`);
346
+ }
347
+ console.log();
348
+ console.log(` refresh token: ${creds.refreshToken ? chalk.green('present') : chalk.yellow('absent')}`);
349
+ }
350
+ //# sourceMappingURL=debug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.js","sourceRoot":"","sources":["../../src/commands/debug.ts"],"names":[],"mappings":"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","sourcesContent":["import chalk from 'chalk';\nimport clack from '../utils/clack.js';\nimport {\n getCredentials,\n saveCredentials,\n clearCredentials,\n isTokenExpired,\n diagnoseCredentials,\n getCredentialsPath,\n setInsecureStorage,\n} from '../lib/credentials.js';\nimport {\n getConfig,\n saveConfig,\n clearConfig,\n getConfigPath,\n setInsecureConfigStorage,\n diagnoseConfig,\n} from '../lib/config-store.js';\nimport { isJsonMode, outputJson, exitWithError } from '../utils/output.js';\nimport { isNonInteractiveEnvironment } from '../utils/environment.js';\n\nfunction maskSecret(value: string | undefined): string | undefined {\n if (!value) return undefined;\n if (value.length <= 8) return '****';\n return value.slice(0, 4) + '****' + value.slice(-4);\n}\n\nfunction formatTimeRemaining(ms: number): string {\n if (ms <= 0) return 'expired';\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n if (hours > 0) return `${hours}h ${minutes % 60}m`;\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`;\n return `${seconds}s`;\n}\n\nfunction parseJwt(token: string): Record<string, unknown> | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n return JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf-8'));\n } catch {\n return null;\n }\n}\n\nfunction determineCredentialSource(diagnostics: string[]): 'keyring' | 'file' | 'none' {\n const hasKeyring = diagnostics.some((l) => l.startsWith('keyring: found'));\n const hasFile = diagnostics.some((l) => l.includes('exists=true'));\n const isInsecure = diagnostics.some((l) => l.includes('insecureStorage=true'));\n\n if (isInsecure) return hasFile ? 'file' : 'none';\n if (hasKeyring) return 'keyring';\n if (hasFile) return 'file';\n return 'none';\n}\n\n// --- debug state ---\n\nexport async function runDebugState({ showSecrets }: { showSecrets: boolean }): Promise<void> {\n const creds = getCredentials();\n const config = getConfig();\n const diagnostics = diagnoseCredentials();\n const credSource = determineCredentialSource(diagnostics);\n const maybeRedact = showSecrets ? (v: string | undefined) => v : maskSecret;\n\n const credentialsOutput: Record<string, unknown> = { present: !!creds, source: credSource };\n\n if (creds) {\n const timeRemaining = creds.expiresAt - Date.now();\n const expired = isTokenExpired(creds);\n Object.assign(credentialsOutput, {\n userId: creds.userId,\n email: creds.email ?? null,\n accessToken: maybeRedact(creds.accessToken),\n refreshToken: creds.refreshToken ? 'present' : 'absent',\n expiresAt: creds.expiresAt,\n expiresIn: expired\n ? `expired ${formatTimeRemaining(-timeRemaining)} ago`\n : `in ${formatTimeRemaining(timeRemaining)}`,\n isExpired: expired,\n });\n if (creds.staging) {\n credentialsOutput.staging = {\n clientId: creds.staging.clientId,\n apiKey: maybeRedact(creds.staging.apiKey),\n fetchedAt: creds.staging.fetchedAt,\n };\n }\n }\n\n const configOutput: Record<string, unknown> = { present: !!config };\n\n if (config) {\n configOutput.activeEnvironment = config.activeEnvironment ?? null;\n configOutput.environments = Object.fromEntries(\n Object.entries(config.environments).map(([key, env]) => [\n key,\n {\n name: env.name,\n type: env.type,\n apiKey: maybeRedact(env.apiKey),\n clientId: env.clientId ?? null,\n endpoint: env.endpoint ?? null,\n ...(env.type === 'unclaimed' && { claimToken: maybeRedact(env.claimToken) }),\n },\n ]),\n );\n }\n\n const configDiagnostics = diagnoseConfig();\n const configSource = determineCredentialSource(configDiagnostics);\n configOutput.source = configSource;\n\n const result = {\n credentials: credentialsOutput,\n config: configOutput,\n storage: {\n credentialsPath: getCredentialsPath(),\n configPath: getConfigPath(),\n credentialDiagnostics: diagnostics,\n configDiagnostics,\n },\n };\n\n if (isJsonMode()) {\n outputJson(result);\n return;\n }\n\n console.log(chalk.bold('Credentials'));\n console.log(` present: ${creds ? chalk.green('true') : chalk.yellow('false')}`);\n console.log(` source: ${credSource}`);\n if (creds) {\n console.log(` userId: ${creds.userId}`);\n console.log(` email: ${creds.email ?? chalk.dim('none')}`);\n console.log(` token: ${maybeRedact(creds.accessToken)}`);\n console.log(` refresh: ${creds.refreshToken ? 'present' : 'absent'}`);\n const expired = isTokenExpired(creds);\n const timeRemaining = creds.expiresAt - Date.now();\n console.log(\n ` expires: ${expired ? chalk.red(`expired ${formatTimeRemaining(-timeRemaining)} ago`) : chalk.green(`in ${formatTimeRemaining(timeRemaining)}`)}`,\n );\n if (creds.staging) {\n console.log(` staging: clientId=${creds.staging.clientId} apiKey=${maybeRedact(creds.staging.apiKey)}`);\n }\n }\n\n console.log();\n console.log(chalk.bold('Config'));\n console.log(` present: ${config ? chalk.green('true') : chalk.yellow('false')}`);\n console.log(` source: ${configSource}`);\n if (config) {\n console.log(` active: ${config.activeEnvironment ?? chalk.dim('none')}`);\n for (const [key, env] of Object.entries(config.environments)) {\n console.log(` env[${key}]: type=${env.type} apiKey=${maybeRedact(env.apiKey)}`);\n if (env.type === 'unclaimed') console.log(` claimToken=${maybeRedact(env.claimToken)}`);\n }\n }\n\n console.log();\n console.log(chalk.bold('Storage — Credentials'));\n console.log(` path: ${getCredentialsPath()}`);\n for (const line of diagnostics) {\n console.log(` ${chalk.dim(line)}`);\n }\n\n console.log();\n console.log(chalk.bold('Storage — Config'));\n console.log(` path: ${getConfigPath()}`);\n for (const line of configDiagnostics) {\n console.log(` ${chalk.dim(line)}`);\n }\n}\n\n// --- debug reset ---\n\nexport async function runDebugReset({\n force,\n credentialsOnly,\n configOnly,\n}: {\n force: boolean;\n credentialsOnly: boolean;\n configOnly: boolean;\n}): Promise<void> {\n // Both flags = clear both (same as neither)\n const clearCreds = !configOnly || credentialsOnly;\n const clearConf = !credentialsOnly || configOnly;\n\n const targets = [clearCreds && 'credentials', clearConf && 'config'].filter(Boolean).join(' and ');\n\n if (!force) {\n if (isNonInteractiveEnvironment()) {\n exitWithError({\n code: 'non_interactive_reset',\n message: 'Use --force to reset in non-interactive mode',\n });\n }\n\n const confirmed = await clack.confirm({\n message: `Clear all ${targets}? This cannot be undone.`,\n });\n\n if (clack.isCancel(confirmed) || !confirmed) {\n if (isJsonMode()) {\n outputJson({ cleared: false, cancelled: true });\n } else {\n clack.log.info('Reset cancelled');\n }\n return;\n }\n }\n\n if (clearCreds) clearCredentials();\n if (clearConf) clearConfig();\n\n if (isJsonMode()) {\n outputJson({ cleared: true, credentials: clearCreds, config: clearConf });\n } else {\n clack.log.success(`Cleared ${targets}`);\n }\n}\n\n// --- debug simulate ---\n\nexport async function runDebugSimulate({\n expiredToken,\n noKeyring,\n unclaimed,\n noAuth,\n}: {\n expiredToken: boolean;\n noKeyring: boolean;\n unclaimed: boolean;\n noAuth: boolean;\n}): Promise<void> {\n // Validate: at least one flag\n if (!expiredToken && !noKeyring && !unclaimed && !noAuth) {\n exitWithError({\n code: 'no_simulation_flags',\n message: 'Specify at least one simulation flag: --expired-token, --no-keyring, --unclaimed, --no-auth',\n });\n }\n\n // Validate: contradictory\n if (expiredToken && noAuth) {\n exitWithError({\n code: 'contradictory_flags',\n message: \"Cannot combine --expired-token and --no-auth (can't expire a cleared token)\",\n });\n }\n\n const actions: string[] = [];\n\n // Apply in order: storage tier first, then credential mutations, then config mutations\n\n if (noKeyring) {\n // Migrate current state to file storage\n const creds = getCredentials();\n const config = getConfig();\n\n setInsecureStorage(true);\n setInsecureConfigStorage(true);\n\n if (creds) saveCredentials(creds);\n if (config) saveConfig(config);\n\n actions.push('Forced file-only storage (keyring bypassed)');\n }\n\n if (expiredToken) {\n const creds = getCredentials();\n if (!creds) {\n exitWithError({\n code: 'no_credentials',\n message: 'Cannot simulate expired token — no credentials found. Log in first.',\n });\n }\n saveCredentials({ ...creds, expiresAt: Date.now() - 60_000 });\n actions.push('Set token expiresAt to 1 minute ago');\n }\n\n if (noAuth) {\n clearCredentials();\n actions.push('Cleared credentials (config preserved)');\n }\n\n if (unclaimed) {\n const config = getConfig() ?? { environments: {} };\n const envName = 'simulated-unclaimed';\n config.environments[envName] = {\n name: envName,\n type: 'unclaimed',\n apiKey: 'sk_test_simulated_unclaimed_000000000000',\n clientId: 'client_simulated',\n claimToken: 'claim_simulated_token_000000000000',\n };\n config.activeEnvironment = envName;\n saveConfig(config);\n actions.push(`Created unclaimed environment \"${envName}\" and set as active`);\n }\n\n if (isJsonMode()) {\n outputJson({ simulated: true, actions });\n } else {\n for (const action of actions) {\n clack.log.success(action);\n }\n }\n}\n\n// --- debug env ---\n\ninterface EnvVarInfo {\n name: string;\n value: string | undefined;\n effect: string;\n}\n\nconst ENV_VAR_CATALOG: { name: string; effect: string }[] = [\n { name: 'WORKOS_API_KEY', effect: 'Bypasses credential resolution — used directly for API calls' },\n { name: 'WORKOS_CLIENT_ID', effect: 'Overrides client ID from settings' },\n { name: 'WORKOS_FORCE_TTY', effect: 'Forces human (non-JSON) output mode, even when piped' },\n { name: 'WORKOS_NO_PROMPT', effect: 'Forces non-interactive/JSON mode' },\n { name: 'WORKOS_TELEMETRY', effect: 'Set to \"false\" to disable telemetry' },\n { name: 'WORKOS_API_URL', effect: 'Overrides API base URL (default: https://api.workos.com)' },\n { name: 'WORKOS_DASHBOARD_URL', effect: 'Overrides dashboard URL (default: https://dashboard.workos.com)' },\n { name: 'WORKOS_AUTHKIT_DOMAIN', effect: 'Overrides AuthKit domain from settings' },\n { name: 'WORKOS_LLM_GATEWAY_URL', effect: 'Overrides LLM gateway URL from settings' },\n { name: 'INSTALLER_DEV', effect: 'Enables dev mode — loads .env.local at startup' },\n { name: 'INSTALLER_DISABLE_PROXY', effect: 'Disables the credential proxy for gateway auth' },\n];\n\nexport async function runDebugEnv(): Promise<void> {\n const vars: EnvVarInfo[] = ENV_VAR_CATALOG.map(({ name, effect }) => ({\n name,\n value: process.env[name],\n effect,\n }));\n\n const setVars = vars.filter((v) => v.value !== undefined);\n const unsetVars = vars.filter((v) => v.value === undefined);\n\n if (isJsonMode()) {\n outputJson({\n variables: Object.fromEntries(vars.map((v) => [v.name, { value: v.value ?? null, effect: v.effect }])),\n set: setVars.map((v) => v.name),\n unset: unsetVars.map((v) => v.name),\n });\n return;\n }\n\n if (setVars.length > 0) {\n console.log(chalk.bold('Set'));\n for (const v of setVars) {\n console.log(` ${chalk.green(v.name)}=${v.value}`);\n console.log(` ${chalk.dim(v.effect)}`);\n }\n console.log();\n }\n\n console.log(chalk.bold(`Unset${setVars.length > 0 ? '' : ' (none active)'}`));\n for (const v of unsetVars) {\n console.log(` ${chalk.dim(v.name)} — ${chalk.dim(v.effect)}`);\n }\n}\n\n// --- debug token ---\n\nexport async function runDebugToken(): Promise<void> {\n const creds = getCredentials();\n\n if (!creds) {\n if (isJsonMode()) {\n outputJson({ present: false });\n } else {\n console.log(chalk.yellow('No credentials found'));\n }\n return;\n }\n\n const claims = parseJwt(creds.accessToken);\n const expired = isTokenExpired(creds);\n const timeRemaining = creds.expiresAt - Date.now();\n\n if (isJsonMode()) {\n outputJson({\n present: true,\n format: claims ? 'jwt' : 'opaque',\n expired,\n expiresAt: creds.expiresAt,\n expiresIn: expired\n ? `expired ${formatTimeRemaining(-timeRemaining)} ago`\n : `in ${formatTimeRemaining(timeRemaining)}`,\n claims: claims ?? null,\n refreshToken: { present: !!creds.refreshToken },\n });\n return;\n }\n\n if (claims) {\n console.log(chalk.bold('JWT Token'));\n console.log(\n ` expires: ${expired ? chalk.red(`expired ${formatTimeRemaining(-timeRemaining)} ago`) : chalk.green(`in ${formatTimeRemaining(timeRemaining)}`)}`,\n );\n console.log();\n console.log(chalk.bold('Claims'));\n for (const [key, value] of Object.entries(claims)) {\n if (key === 'exp' || key === 'iat' || key === 'nbf') {\n const date = new Date((value as number) * 1000).toISOString();\n console.log(` ${key}: ${value} (${date})`);\n } else {\n console.log(` ${key}: ${JSON.stringify(value)}`);\n }\n }\n } else {\n console.log(chalk.bold('Opaque Token'));\n console.log(chalk.dim(' Token is not a JWT — cannot decode claims'));\n console.log(\n ` expires: ${expired ? chalk.red(`expired ${formatTimeRemaining(-timeRemaining)} ago`) : chalk.green(`in ${formatTimeRemaining(timeRemaining)}`)}`,\n );\n }\n\n console.log();\n console.log(` refresh token: ${creds.refreshToken ? chalk.green('present') : chalk.yellow('absent')}`);\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import chalk from 'chalk';
2
2
  import clack from '../utils/clack.js';
3
- import { getConfig, saveConfig } from '../lib/config-store.js';
3
+ import { getConfig, saveConfig, isUnclaimedEnvironment } from '../lib/config-store.js';
4
4
  import { outputSuccess, outputJson, exitWithError, isJsonMode } from '../utils/output.js';
5
5
  import { isNonInteractiveEnvironment } from '../utils/environment.js';
6
6
  const ENV_NAME_REGEX = /^[a-z0-9\-_]+$/;
@@ -178,7 +178,8 @@ export async function runEnvList() {
178
178
  return;
179
179
  }
180
180
  // Human-mode table
181
- const nameW = Math.max(6, ...entries.map(([k]) => k.length)) + 2;
181
+ const hasUnclaimed = entries.some(([, env]) => isUnclaimedEnvironment(env));
182
+ const nameW = Math.max(6, ...entries.map(([k, env]) => k.length + (isUnclaimedEnvironment(env) ? ' (unclaimed)'.length : 0))) + 2;
182
183
  const typeW = 12;
183
184
  const header = [
184
185
  chalk.yellow(' '),
@@ -192,10 +193,16 @@ export async function runEnvList() {
192
193
  for (const [key, env] of entries) {
193
194
  const isActive = key === config.activeEnvironment;
194
195
  const marker = isActive ? chalk.green('▸ ') : ' ';
195
- const name = isActive ? chalk.green(key.padEnd(nameW)) : key.padEnd(nameW);
196
- const type = env.type === 'sandbox' ? 'Sandbox' : 'Production';
196
+ const unclaimed = isUnclaimedEnvironment(env);
197
+ const displayName = unclaimed ? `${key} ${chalk.yellow('(unclaimed)')}` : key;
198
+ const name = isActive ? chalk.green(displayName.padEnd(nameW)) : displayName.padEnd(nameW);
199
+ const type = unclaimed ? 'Unclaimed' : env.type === 'sandbox' ? 'Sandbox' : 'Production';
197
200
  const endpoint = env.endpoint || chalk.dim('default');
198
201
  console.log([marker, name, type.padEnd(typeW), endpoint].join(' '));
199
202
  }
203
+ if (hasUnclaimed) {
204
+ console.log('');
205
+ console.log(chalk.dim(' Run `workos claim` to keep this environment.'));
206
+ }
200
207
  }
201
208
  //# sourceMappingURL=env.js.map