@vibe-assurance/cli 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/vibe.js +4 -0
- package/package.json +2 -2
- package/src/api/client.js +32 -7
- package/src/commands/env.js +201 -0
- package/src/commands/login.js +17 -4
- package/src/commands/whoami.js +19 -3
- package/src/config/credentials.js +32 -1
- package/src/config/environments.js +73 -0
package/bin/vibe.js
CHANGED
|
@@ -14,6 +14,7 @@ const whoami = require('../src/commands/whoami');
|
|
|
14
14
|
const mcpServer = require('../src/commands/mcp-server');
|
|
15
15
|
const setupClaude = require('../src/commands/setup-claude');
|
|
16
16
|
const { registerProjectCommands } = require('../src/commands/projects');
|
|
17
|
+
const { registerEnvCommands } = require('../src/commands/env'); // CR-2026-061
|
|
17
18
|
|
|
18
19
|
program
|
|
19
20
|
.name('vibe')
|
|
@@ -48,4 +49,7 @@ program
|
|
|
48
49
|
// CR-2026-043: Register project management commands
|
|
49
50
|
registerProjectCommands(program);
|
|
50
51
|
|
|
52
|
+
// CR-2026-061: Register environment management commands
|
|
53
|
+
registerEnvCommands(program);
|
|
54
|
+
|
|
51
55
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibe-assurance/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Vibe Assurance CLI - Connect AI coding agents to your governance platform via MCP",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
],
|
|
22
22
|
"author": "Vibe Assurance",
|
|
23
23
|
"license": "MIT",
|
|
24
|
-
"homepage": "https://
|
|
24
|
+
"homepage": "https://vibeassurance.app/docs-cli.html",
|
|
25
25
|
"engines": {
|
|
26
26
|
"node": ">=18.0.0"
|
|
27
27
|
},
|
package/src/api/client.js
CHANGED
|
@@ -1,12 +1,31 @@
|
|
|
1
1
|
const axios = require('axios');
|
|
2
|
-
const { getCredentials, storeCredentials, deleteCredentials, getProjectId } = require('../config/credentials');
|
|
2
|
+
const { getCredentials, storeCredentials, deleteCredentials, getProjectId, getEnvironment } = require('../config/credentials');
|
|
3
|
+
const { getEnvironmentUrl, DEFAULT_ENVIRONMENT } = require('../config/environments');
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* CR-2026-061: Get API base URL
|
|
7
|
+
* Priority: VIBE_API_URL env var > stored environment > default (prod)
|
|
8
|
+
* @returns {Promise<string>} API base URL
|
|
9
|
+
*/
|
|
10
|
+
async function getApiBaseUrl() {
|
|
11
|
+
// Environment variable takes precedence (backward compatibility)
|
|
12
|
+
if (process.env.VIBE_API_URL) {
|
|
13
|
+
return process.env.VIBE_API_URL;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Use stored environment
|
|
17
|
+
const envName = await getEnvironment();
|
|
18
|
+
return getEnvironmentUrl(envName);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// For backward compatibility - synchronous version for simple cases
|
|
22
|
+
// Uses env var or default, doesn't read stored credentials
|
|
23
|
+
const API_BASE_URL = process.env.VIBE_API_URL || getEnvironmentUrl(DEFAULT_ENVIRONMENT);
|
|
6
24
|
|
|
7
25
|
/**
|
|
8
26
|
* Create an authenticated axios instance with token refresh handling
|
|
9
27
|
* CR-2026-043: Now includes X-Project-Id header for project scoping
|
|
28
|
+
* CR-2026-061: Uses stored environment for API URL
|
|
10
29
|
* @returns {Promise<import('axios').AxiosInstance>}
|
|
11
30
|
*/
|
|
12
31
|
async function createClient() {
|
|
@@ -15,13 +34,16 @@ async function createClient() {
|
|
|
15
34
|
throw new Error('Not authenticated. Run: vibe login');
|
|
16
35
|
}
|
|
17
36
|
|
|
37
|
+
// CR-2026-061: Get API URL from stored environment
|
|
38
|
+
const apiBaseUrl = await getApiBaseUrl();
|
|
39
|
+
|
|
18
40
|
// CR-2026-043: Get current project ID for scoping
|
|
19
41
|
const projectId = await getProjectId();
|
|
20
42
|
|
|
21
43
|
const headers = {
|
|
22
44
|
'Authorization': `Bearer ${creds.accessToken}`,
|
|
23
45
|
'Content-Type': 'application/json',
|
|
24
|
-
'User-Agent': 'vibe-cli/1.
|
|
46
|
+
'User-Agent': 'vibe-cli/1.7.0'
|
|
25
47
|
};
|
|
26
48
|
|
|
27
49
|
// CR-2026-043: Add project header if available
|
|
@@ -30,7 +52,7 @@ async function createClient() {
|
|
|
30
52
|
}
|
|
31
53
|
|
|
32
54
|
const client = axios.create({
|
|
33
|
-
baseURL:
|
|
55
|
+
baseURL: apiBaseUrl, // CR-2026-061: Dynamic URL
|
|
34
56
|
headers,
|
|
35
57
|
timeout: 30000 // 30 second timeout
|
|
36
58
|
});
|
|
@@ -73,11 +95,13 @@ async function createClient() {
|
|
|
73
95
|
|
|
74
96
|
/**
|
|
75
97
|
* Refresh access token using refresh token
|
|
98
|
+
* CR-2026-061: Uses dynamic API URL
|
|
76
99
|
* @param {string} refreshTokenValue
|
|
77
100
|
* @returns {Promise<Object>} New token object
|
|
78
101
|
*/
|
|
79
102
|
async function refreshToken(refreshTokenValue) {
|
|
80
|
-
const
|
|
103
|
+
const apiBaseUrl = await getApiBaseUrl(); // CR-2026-061
|
|
104
|
+
const response = await axios.post(`${apiBaseUrl}/api/auth/refresh`, {
|
|
81
105
|
refreshToken: refreshTokenValue
|
|
82
106
|
});
|
|
83
107
|
|
|
@@ -139,5 +163,6 @@ module.exports = {
|
|
|
139
163
|
post,
|
|
140
164
|
put,
|
|
141
165
|
delete: del,
|
|
142
|
-
API_BASE_URL
|
|
166
|
+
API_BASE_URL, // Sync version for backward compat
|
|
167
|
+
getApiBaseUrl // CR-2026-061: Async version
|
|
143
168
|
};
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment management commands
|
|
3
|
+
* CR-2026-061: CLI Environment Switching with Production Default
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const chalk = require('chalk');
|
|
7
|
+
const ora = require('ora');
|
|
8
|
+
const { getEnvironment, setEnvironment } = require('../config/credentials');
|
|
9
|
+
const {
|
|
10
|
+
ENVIRONMENTS,
|
|
11
|
+
DEFAULT_ENVIRONMENT,
|
|
12
|
+
getEnvironmentConfig,
|
|
13
|
+
isInternalOnly,
|
|
14
|
+
getEnvironmentNames
|
|
15
|
+
} = require('../config/environments');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* CR-2026-061: Show current environment
|
|
19
|
+
*/
|
|
20
|
+
async function showCurrentEnv() {
|
|
21
|
+
const spinner = ora('Checking environment...').start();
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const currentEnv = await getEnvironment();
|
|
25
|
+
const config = getEnvironmentConfig(currentEnv);
|
|
26
|
+
spinner.stop();
|
|
27
|
+
|
|
28
|
+
console.log('');
|
|
29
|
+
console.log(chalk.cyan('Current Environment:'));
|
|
30
|
+
console.log('');
|
|
31
|
+
console.log(` ${chalk.bold(config.name)} ${chalk.dim('(' + currentEnv + ')')}`);
|
|
32
|
+
console.log(` ${chalk.dim(config.url)}`);
|
|
33
|
+
|
|
34
|
+
if (config.internal) {
|
|
35
|
+
console.log(` ${chalk.yellow('⚠ Internal environment')}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Check if VIBE_API_URL override is active
|
|
39
|
+
if (process.env.VIBE_API_URL) {
|
|
40
|
+
console.log('');
|
|
41
|
+
console.log(chalk.yellow('Note: VIBE_API_URL environment variable is set'));
|
|
42
|
+
console.log(chalk.dim(` Override URL: ${process.env.VIBE_API_URL}`));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
console.log('');
|
|
46
|
+
} catch (err) {
|
|
47
|
+
spinner.fail('Failed to get environment');
|
|
48
|
+
console.error(chalk.red(err.message));
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* CR-2026-061: List all available environments
|
|
55
|
+
*/
|
|
56
|
+
async function listEnvironments(options = {}) {
|
|
57
|
+
const currentEnv = await getEnvironment();
|
|
58
|
+
const showInternal = options.internal || false;
|
|
59
|
+
|
|
60
|
+
console.log('');
|
|
61
|
+
console.log(chalk.cyan('Available Environments:'));
|
|
62
|
+
console.log('');
|
|
63
|
+
|
|
64
|
+
for (const [name, config] of Object.entries(ENVIRONMENTS)) {
|
|
65
|
+
// Skip internal environments unless --internal flag
|
|
66
|
+
if (config.internal && !showInternal) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const isCurrent = name === currentEnv;
|
|
71
|
+
const prefix = isCurrent ? chalk.green('✓') : ' ';
|
|
72
|
+
const envName = isCurrent ? chalk.green.bold(name) : chalk.bold(name);
|
|
73
|
+
const label = config.internal ? chalk.yellow(' (internal)') : '';
|
|
74
|
+
|
|
75
|
+
console.log(` ${prefix} ${envName}${label}`);
|
|
76
|
+
console.log(` ${chalk.dim(config.description)}`);
|
|
77
|
+
console.log(` ${chalk.dim(config.url)}`);
|
|
78
|
+
console.log('');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!showInternal) {
|
|
82
|
+
console.log(chalk.dim(' Use --internal to see internal environments'));
|
|
83
|
+
console.log('');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* CR-2026-061: Switch to a specific environment
|
|
89
|
+
* @param {string} envName - Environment name (prod, dev, local)
|
|
90
|
+
* @param {Object} options - Command options
|
|
91
|
+
*/
|
|
92
|
+
async function switchEnvironment(envName, options = {}) {
|
|
93
|
+
const config = getEnvironmentConfig(envName);
|
|
94
|
+
|
|
95
|
+
if (!config) {
|
|
96
|
+
console.error(chalk.red(`Unknown environment: ${envName}`));
|
|
97
|
+
console.log(chalk.dim('Available: ' + getEnvironmentNames().join(', ')));
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Check if internal flag is required
|
|
102
|
+
if (isInternalOnly(envName) && !options.internal) {
|
|
103
|
+
console.error(chalk.red(`Environment '${envName}' requires --internal flag`));
|
|
104
|
+
console.log('');
|
|
105
|
+
console.log(chalk.yellow('⚠ This environment is for internal development only.'));
|
|
106
|
+
console.log(chalk.dim(' If you are a Vibe Assurance developer, run:'));
|
|
107
|
+
console.log(chalk.dim(` vibe env ${envName} --internal`));
|
|
108
|
+
console.log('');
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const spinner = ora(`Switching to ${config.name}...`).start();
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
await setEnvironment(envName);
|
|
116
|
+
spinner.succeed(`Switched to ${chalk.bold(config.name)}`);
|
|
117
|
+
|
|
118
|
+
console.log('');
|
|
119
|
+
console.log(` ${chalk.dim('API URL:')} ${config.url}`);
|
|
120
|
+
|
|
121
|
+
if (config.internal) {
|
|
122
|
+
console.log('');
|
|
123
|
+
console.log(chalk.yellow('⚠ You are now using an internal environment.'));
|
|
124
|
+
console.log(chalk.dim(' Run `vibe env prod` to switch back to production.'));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
console.log('');
|
|
128
|
+
console.log(chalk.dim('Note: You may need to run `vibe login` to authenticate with this environment.'));
|
|
129
|
+
console.log('');
|
|
130
|
+
} catch (err) {
|
|
131
|
+
spinner.fail('Failed to switch environment');
|
|
132
|
+
console.error(chalk.red(err.message));
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* CR-2026-061: Register environment commands with Commander
|
|
139
|
+
* @param {import('commander').Command} program - Commander program instance
|
|
140
|
+
*/
|
|
141
|
+
function registerEnvCommands(program) {
|
|
142
|
+
const env = program
|
|
143
|
+
.command('env')
|
|
144
|
+
.description('Manage API environment (prod, dev, local)');
|
|
145
|
+
|
|
146
|
+
// vibe env (no subcommand) - show current
|
|
147
|
+
env
|
|
148
|
+
.action(async () => {
|
|
149
|
+
await showCurrentEnv();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// vibe env current
|
|
153
|
+
env
|
|
154
|
+
.command('current')
|
|
155
|
+
.description('Show current environment')
|
|
156
|
+
.action(async () => {
|
|
157
|
+
await showCurrentEnv();
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// vibe env list
|
|
161
|
+
env
|
|
162
|
+
.command('list')
|
|
163
|
+
.description('List available environments')
|
|
164
|
+
.option('--internal', 'Show internal environments (dev, local)')
|
|
165
|
+
.action(async (options) => {
|
|
166
|
+
await listEnvironments(options);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// vibe env prod
|
|
170
|
+
env
|
|
171
|
+
.command('prod')
|
|
172
|
+
.description('Switch to production environment')
|
|
173
|
+
.action(async () => {
|
|
174
|
+
await switchEnvironment('prod', {});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// vibe env dev
|
|
178
|
+
env
|
|
179
|
+
.command('dev')
|
|
180
|
+
.description('Switch to development environment (internal only)')
|
|
181
|
+
.option('--internal', 'Confirm internal environment access')
|
|
182
|
+
.action(async (options) => {
|
|
183
|
+
await switchEnvironment('dev', options);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// vibe env local
|
|
187
|
+
env
|
|
188
|
+
.command('local')
|
|
189
|
+
.description('Switch to local development environment (internal only)')
|
|
190
|
+
.option('--internal', 'Confirm internal environment access')
|
|
191
|
+
.action(async (options) => {
|
|
192
|
+
await switchEnvironment('local', options);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
module.exports = {
|
|
197
|
+
registerEnvCommands,
|
|
198
|
+
showCurrentEnv,
|
|
199
|
+
listEnvironments,
|
|
200
|
+
switchEnvironment
|
|
201
|
+
};
|
package/src/commands/login.js
CHANGED
|
@@ -5,8 +5,9 @@ const chalk = require('chalk');
|
|
|
5
5
|
const ora = require('ora');
|
|
6
6
|
const inquirer = require('inquirer');
|
|
7
7
|
const axios = require('axios');
|
|
8
|
-
const { storeCredentials, hasValidCredentials, setProjectId, setUserInfo } = require('../config/credentials');
|
|
9
|
-
const {
|
|
8
|
+
const { storeCredentials, hasValidCredentials, setProjectId, setUserInfo, getEnvironment } = require('../config/credentials');
|
|
9
|
+
const { getApiBaseUrl } = require('../api/client');
|
|
10
|
+
const { getEnvironmentConfig } = require('../config/environments');
|
|
10
11
|
|
|
11
12
|
// Local callback server port (chosen to be unlikely to conflict)
|
|
12
13
|
const CALLBACK_PORT = 38274;
|
|
@@ -14,6 +15,7 @@ const CALLBACK_URL = `http://localhost:${CALLBACK_PORT}/callback`;
|
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Login command - authenticates user via OAuth flow
|
|
18
|
+
* CR-2026-061: Uses dynamic environment URL
|
|
17
19
|
*/
|
|
18
20
|
async function login() {
|
|
19
21
|
// Check if already logged in
|
|
@@ -23,6 +25,13 @@ async function login() {
|
|
|
23
25
|
return;
|
|
24
26
|
}
|
|
25
27
|
|
|
28
|
+
// CR-2026-061: Show current environment
|
|
29
|
+
const envName = await getEnvironment();
|
|
30
|
+
const envConfig = getEnvironmentConfig(envName);
|
|
31
|
+
if (envConfig.internal) {
|
|
32
|
+
console.log(chalk.yellow(`⚠ Logging in to ${envConfig.name} environment (${envConfig.url})`));
|
|
33
|
+
}
|
|
34
|
+
|
|
26
35
|
const spinner = ora('Opening browser for authentication...').start();
|
|
27
36
|
|
|
28
37
|
// Track server for cleanup
|
|
@@ -122,7 +131,8 @@ async function login() {
|
|
|
122
131
|
// Start listening and open browser
|
|
123
132
|
server.listen(CALLBACK_PORT, async () => {
|
|
124
133
|
try {
|
|
125
|
-
const
|
|
134
|
+
const apiBaseUrl = await getApiBaseUrl(); // CR-2026-061: Dynamic URL
|
|
135
|
+
const authUrl = `${apiBaseUrl}/api/auth/cli?callback=${encodeURIComponent(CALLBACK_URL)}`;
|
|
126
136
|
await open(authUrl);
|
|
127
137
|
spinner.text = 'Waiting for authentication in browser...';
|
|
128
138
|
} catch (err) {
|
|
@@ -172,8 +182,11 @@ async function selectProject() {
|
|
|
172
182
|
const { getCredentials } = require('../config/credentials');
|
|
173
183
|
const creds = await getCredentials();
|
|
174
184
|
|
|
185
|
+
// CR-2026-061: Get API URL from stored environment
|
|
186
|
+
const apiBaseUrl = await getApiBaseUrl();
|
|
187
|
+
|
|
175
188
|
// Fetch user profile which now includes projects (CR-2026-043 backend change)
|
|
176
|
-
const response = await axios.get(`${
|
|
189
|
+
const response = await axios.get(`${apiBaseUrl}/api/auth/me`, {
|
|
177
190
|
headers: {
|
|
178
191
|
'Authorization': `Bearer ${creds.accessToken}`,
|
|
179
192
|
'Content-Type': 'application/json'
|
package/src/commands/whoami.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Whoami command - shows current authenticated user
|
|
3
|
+
* CR-2026-061: Added environment display
|
|
3
4
|
*/
|
|
4
5
|
|
|
5
6
|
const chalk = require('chalk');
|
|
6
7
|
const ora = require('ora');
|
|
7
8
|
const axios = require('axios');
|
|
8
|
-
const { hasValidCredentials, getUserInfo, getCredentials, getProjectName } = require('../config/credentials');
|
|
9
|
-
const {
|
|
9
|
+
const { hasValidCredentials, getUserInfo, getCredentials, getProjectName, getEnvironment } = require('../config/credentials');
|
|
10
|
+
const { getApiBaseUrl } = require('../api/client');
|
|
11
|
+
const { getEnvironmentConfig } = require('../config/environments');
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* Show current user info
|
|
@@ -24,11 +26,21 @@ async function whoami() {
|
|
|
24
26
|
const cachedUser = await getUserInfo();
|
|
25
27
|
const projectName = await getProjectName();
|
|
26
28
|
|
|
29
|
+
// CR-2026-061: Get current environment
|
|
30
|
+
const envName = await getEnvironment();
|
|
31
|
+
const envConfig = getEnvironmentConfig(envName);
|
|
32
|
+
const envLabel = envConfig.internal
|
|
33
|
+
? chalk.yellow(`${envConfig.name} (internal)`)
|
|
34
|
+
: chalk.green(envConfig.name);
|
|
35
|
+
|
|
27
36
|
if (cachedUser) {
|
|
28
37
|
console.log(chalk.cyan(`\nSigned in as ${chalk.bold(cachedUser.username)} (${cachedUser.email})`));
|
|
29
38
|
if (projectName) {
|
|
30
39
|
console.log(chalk.dim(`Current project: ${projectName}`));
|
|
31
40
|
}
|
|
41
|
+
// CR-2026-061: Show environment
|
|
42
|
+
console.log(`Environment: ${envLabel}`);
|
|
43
|
+
console.log(chalk.dim(` ${envConfig.url}`));
|
|
32
44
|
return;
|
|
33
45
|
}
|
|
34
46
|
|
|
@@ -37,7 +49,8 @@ async function whoami() {
|
|
|
37
49
|
|
|
38
50
|
try {
|
|
39
51
|
const creds = await getCredentials();
|
|
40
|
-
const
|
|
52
|
+
const apiBaseUrl = await getApiBaseUrl(); // CR-2026-061: Dynamic URL
|
|
53
|
+
const response = await axios.get(`${apiBaseUrl}/api/auth/me`, {
|
|
41
54
|
headers: {
|
|
42
55
|
'Authorization': `Bearer ${creds.accessToken}`,
|
|
43
56
|
'Content-Type': 'application/json'
|
|
@@ -52,6 +65,9 @@ async function whoami() {
|
|
|
52
65
|
if (projectName) {
|
|
53
66
|
console.log(chalk.dim(`Current project: ${projectName}`));
|
|
54
67
|
}
|
|
68
|
+
// CR-2026-061: Show environment
|
|
69
|
+
console.log(`Environment: ${envLabel}`);
|
|
70
|
+
console.log(chalk.dim(` ${envConfig.url}`));
|
|
55
71
|
} else {
|
|
56
72
|
console.log(chalk.yellow('Could not retrieve user info.'));
|
|
57
73
|
}
|
|
@@ -2,6 +2,7 @@ const keytar = require('keytar');
|
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const os = require('os');
|
|
5
|
+
const { DEFAULT_ENVIRONMENT } = require('./environments');
|
|
5
6
|
|
|
6
7
|
const SERVICE_NAME = 'vibe-assurance';
|
|
7
8
|
const ACCOUNT_NAME = 'auth-token';
|
|
@@ -188,6 +189,34 @@ async function setUserInfo(username, email) {
|
|
|
188
189
|
}
|
|
189
190
|
}
|
|
190
191
|
|
|
192
|
+
/**
|
|
193
|
+
* CR-2026-061: Get stored environment
|
|
194
|
+
* @returns {Promise<string>} Environment name (prod, dev, local)
|
|
195
|
+
*/
|
|
196
|
+
async function getEnvironment() {
|
|
197
|
+
const creds = await getCredentials();
|
|
198
|
+
return creds?.environment || DEFAULT_ENVIRONMENT;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* CR-2026-061: Set environment (updates existing credentials)
|
|
203
|
+
* @param {string} environment - Environment name to store
|
|
204
|
+
* @returns {Promise<void>}
|
|
205
|
+
*/
|
|
206
|
+
async function setEnvironment(environment) {
|
|
207
|
+
const creds = await getCredentials();
|
|
208
|
+
if (creds) {
|
|
209
|
+
await storeCredentials({
|
|
210
|
+
...creds,
|
|
211
|
+
environment
|
|
212
|
+
});
|
|
213
|
+
} else {
|
|
214
|
+
// No credentials yet - store just the environment
|
|
215
|
+
// This allows setting env before login
|
|
216
|
+
await storeCredentials({ environment });
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
191
220
|
module.exports = {
|
|
192
221
|
storeCredentials,
|
|
193
222
|
getCredentials,
|
|
@@ -197,5 +226,7 @@ module.exports = {
|
|
|
197
226
|
getProjectName,
|
|
198
227
|
setProjectId,
|
|
199
228
|
getUserInfo,
|
|
200
|
-
setUserInfo
|
|
229
|
+
setUserInfo,
|
|
230
|
+
getEnvironment, // CR-2026-061
|
|
231
|
+
setEnvironment // CR-2026-061
|
|
201
232
|
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment configuration for Vibe Assurance CLI
|
|
3
|
+
* CR-2026-061: Environment switching with production default
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const ENVIRONMENTS = {
|
|
7
|
+
prod: {
|
|
8
|
+
name: 'Production',
|
|
9
|
+
url: 'https://vibeassurance.app',
|
|
10
|
+
internal: false,
|
|
11
|
+
description: 'Production server (default)'
|
|
12
|
+
},
|
|
13
|
+
dev: {
|
|
14
|
+
name: 'Development',
|
|
15
|
+
url: 'https://agent-platform-dev.azurewebsites.net',
|
|
16
|
+
internal: true,
|
|
17
|
+
description: 'Development server (internal only)'
|
|
18
|
+
},
|
|
19
|
+
local: {
|
|
20
|
+
name: 'Local',
|
|
21
|
+
url: 'http://localhost:3000',
|
|
22
|
+
internal: true,
|
|
23
|
+
description: 'Local development server (internal only)'
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const DEFAULT_ENVIRONMENT = 'prod';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get environment configuration by name
|
|
31
|
+
* @param {string} envName - Environment name (prod, dev, local)
|
|
32
|
+
* @returns {Object|null} Environment config or null if not found
|
|
33
|
+
*/
|
|
34
|
+
function getEnvironmentConfig(envName) {
|
|
35
|
+
return ENVIRONMENTS[envName] || null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get API URL for an environment
|
|
40
|
+
* @param {string} envName - Environment name
|
|
41
|
+
* @returns {string} API URL
|
|
42
|
+
*/
|
|
43
|
+
function getEnvironmentUrl(envName) {
|
|
44
|
+
const env = ENVIRONMENTS[envName];
|
|
45
|
+
return env ? env.url : ENVIRONMENTS[DEFAULT_ENVIRONMENT].url;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Check if environment requires internal flag
|
|
50
|
+
* @param {string} envName - Environment name
|
|
51
|
+
* @returns {boolean} True if internal flag required
|
|
52
|
+
*/
|
|
53
|
+
function isInternalOnly(envName) {
|
|
54
|
+
const env = ENVIRONMENTS[envName];
|
|
55
|
+
return env ? env.internal : false;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Get all environment names
|
|
60
|
+
* @returns {string[]} Array of environment names
|
|
61
|
+
*/
|
|
62
|
+
function getEnvironmentNames() {
|
|
63
|
+
return Object.keys(ENVIRONMENTS);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = {
|
|
67
|
+
ENVIRONMENTS,
|
|
68
|
+
DEFAULT_ENVIRONMENT,
|
|
69
|
+
getEnvironmentConfig,
|
|
70
|
+
getEnvironmentUrl,
|
|
71
|
+
isInternalOnly,
|
|
72
|
+
getEnvironmentNames
|
|
73
|
+
};
|