@provartesting/provardx-cli 1.5.0-dev.2 → 1.5.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/README.md +163 -12
- package/bin/mcp-start.js +74 -0
- package/lib/commands/provar/auth/clear.d.ts +7 -0
- package/lib/commands/provar/auth/clear.js +36 -0
- package/lib/commands/provar/auth/clear.js.map +1 -0
- package/lib/commands/provar/auth/login.d.ts +10 -0
- package/lib/commands/provar/auth/login.js +90 -0
- package/lib/commands/provar/auth/login.js.map +1 -0
- package/lib/commands/provar/auth/rotate.d.ts +7 -0
- package/lib/commands/provar/auth/rotate.js +42 -0
- package/lib/commands/provar/auth/rotate.js.map +1 -0
- package/lib/commands/provar/auth/status.d.ts +7 -0
- package/lib/commands/provar/auth/status.js +107 -0
- package/lib/commands/provar/auth/status.js.map +1 -0
- package/lib/commands/provar/mcp/start.d.ts +2 -0
- package/lib/commands/provar/mcp/start.js +14 -1
- package/lib/commands/provar/mcp/start.js.map +1 -1
- package/lib/mcp/docs/NITROX_CATALOG_SOURCE.json +6 -0
- package/lib/mcp/docs/NITROX_COMPONENT_CATALOG.md +2001 -0
- package/lib/mcp/docs/PROVAR_TEST_STEP_REFERENCE.md +1430 -0
- package/lib/mcp/docs/PROVAR_TOOL_GUIDE.md +175 -0
- package/lib/mcp/licensing/algasClient.js +14 -5
- package/lib/mcp/licensing/algasClient.js.map +1 -1
- package/lib/mcp/licensing/ideDetection.d.ts +0 -12
- package/lib/mcp/licensing/ideDetection.js +1 -73
- package/lib/mcp/licensing/ideDetection.js.map +1 -1
- package/lib/mcp/licensing/licenseCache.js +7 -1
- package/lib/mcp/licensing/licenseCache.js.map +1 -1
- package/lib/mcp/licensing/licenseValidator.d.ts +3 -3
- package/lib/mcp/licensing/licenseValidator.js +11 -4
- package/lib/mcp/licensing/licenseValidator.js.map +1 -1
- package/lib/mcp/prompts/guidePrompts.d.ts +4 -0
- package/lib/mcp/prompts/guidePrompts.js +324 -0
- package/lib/mcp/prompts/guidePrompts.js.map +1 -0
- package/lib/mcp/prompts/index.d.ts +2 -0
- package/lib/mcp/prompts/index.js +23 -0
- package/lib/mcp/prompts/index.js.map +1 -0
- package/lib/mcp/prompts/loopPrompts.d.ts +6 -0
- package/lib/mcp/prompts/loopPrompts.js +435 -0
- package/lib/mcp/prompts/loopPrompts.js.map +1 -0
- package/lib/mcp/prompts/migrationPrompts.d.ts +4 -0
- package/lib/mcp/prompts/migrationPrompts.js +207 -0
- package/lib/mcp/prompts/migrationPrompts.js.map +1 -0
- package/lib/mcp/rules/provar_best_practices_rules.json +256 -544
- package/lib/mcp/security/pathPolicy.d.ts +5 -0
- package/lib/mcp/security/pathPolicy.js +58 -3
- package/lib/mcp/security/pathPolicy.js.map +1 -1
- package/lib/mcp/server.d.ts +17 -0
- package/lib/mcp/server.js +151 -6
- package/lib/mcp/server.js.map +1 -1
- package/lib/mcp/tools/antTools.d.ts +15 -0
- package/lib/mcp/tools/antTools.js +347 -170
- package/lib/mcp/tools/antTools.js.map +1 -1
- package/lib/mcp/tools/automationTools.d.ts +18 -8
- package/lib/mcp/tools/automationTools.js +332 -176
- package/lib/mcp/tools/automationTools.js.map +1 -1
- package/lib/mcp/tools/bestPracticesEngine.js +161 -23
- package/lib/mcp/tools/bestPracticesEngine.js.map +1 -1
- package/lib/mcp/tools/connectionTools.d.ts +4 -0
- package/lib/mcp/tools/connectionTools.js +172 -0
- package/lib/mcp/tools/connectionTools.js.map +1 -0
- package/lib/mcp/tools/defectTools.d.ts +1 -1
- package/lib/mcp/tools/defectTools.js +56 -50
- package/lib/mcp/tools/defectTools.js.map +1 -1
- package/lib/mcp/tools/hierarchyValidate.d.ts +1 -1
- package/lib/mcp/tools/hierarchyValidate.js +127 -42
- package/lib/mcp/tools/hierarchyValidate.js.map +1 -1
- package/lib/mcp/tools/nitroXTools.d.ts +23 -0
- package/lib/mcp/tools/nitroXTools.js +823 -0
- package/lib/mcp/tools/nitroXTools.js.map +1 -0
- package/lib/mcp/tools/pageObjectGenerate.js +132 -57
- package/lib/mcp/tools/pageObjectGenerate.js.map +1 -1
- package/lib/mcp/tools/pageObjectValidate.js +136 -46
- package/lib/mcp/tools/pageObjectValidate.js.map +1 -1
- package/lib/mcp/tools/projectInspect.js +51 -30
- package/lib/mcp/tools/projectInspect.js.map +1 -1
- package/lib/mcp/tools/projectValidateFromPath.js +70 -49
- package/lib/mcp/tools/projectValidateFromPath.js.map +1 -1
- package/lib/mcp/tools/propertiesTools.d.ts +2 -0
- package/lib/mcp/tools/propertiesTools.js +332 -78
- package/lib/mcp/tools/propertiesTools.js.map +1 -1
- package/lib/mcp/tools/qualityHubApiTools.d.ts +3 -0
- package/lib/mcp/tools/qualityHubApiTools.js +138 -0
- package/lib/mcp/tools/qualityHubApiTools.js.map +1 -0
- package/lib/mcp/tools/qualityHubTools.js +219 -70
- package/lib/mcp/tools/qualityHubTools.js.map +1 -1
- package/lib/mcp/tools/rcaTools.d.ts +3 -2
- package/lib/mcp/tools/rcaTools.js +189 -56
- package/lib/mcp/tools/rcaTools.js.map +1 -1
- package/lib/mcp/tools/sfSpawn.d.ts +25 -3
- package/lib/mcp/tools/sfSpawn.js +154 -6
- package/lib/mcp/tools/sfSpawn.js.map +1 -1
- package/lib/mcp/tools/testCaseGenerate.js +226 -78
- package/lib/mcp/tools/testCaseGenerate.js.map +1 -1
- package/lib/mcp/tools/testCaseStepTools.d.ts +4 -0
- package/lib/mcp/tools/testCaseStepTools.js +226 -0
- package/lib/mcp/tools/testCaseStepTools.js.map +1 -0
- package/lib/mcp/tools/testCaseValidate.d.ts +11 -0
- package/lib/mcp/tools/testCaseValidate.js +300 -44
- package/lib/mcp/tools/testCaseValidate.js.map +1 -1
- package/lib/mcp/tools/testPlanTools.d.ts +1 -0
- package/lib/mcp/tools/testPlanTools.js +299 -59
- package/lib/mcp/tools/testPlanTools.js.map +1 -1
- package/lib/mcp/tools/testPlanValidate.js +56 -18
- package/lib/mcp/tools/testPlanValidate.js.map +1 -1
- package/lib/mcp/tools/testSuiteValidate.js +37 -11
- package/lib/mcp/tools/testSuiteValidate.js.map +1 -1
- package/lib/mcp/update/updateChecker.d.ts +14 -0
- package/lib/mcp/update/updateChecker.js +228 -0
- package/lib/mcp/update/updateChecker.js.map +1 -0
- package/lib/services/auth/credentials.d.ts +21 -0
- package/lib/services/auth/credentials.js +75 -0
- package/lib/services/auth/credentials.js.map +1 -0
- package/lib/services/auth/loginFlow.d.ts +68 -0
- package/lib/services/auth/loginFlow.js +216 -0
- package/lib/services/auth/loginFlow.js.map +1 -0
- package/lib/services/projectValidation.d.ts +5 -2
- package/lib/services/projectValidation.js +83 -31
- package/lib/services/projectValidation.js.map +1 -1
- package/lib/services/qualityHub/client.d.ts +161 -0
- package/lib/services/qualityHub/client.js +226 -0
- package/lib/services/qualityHub/client.js.map +1 -0
- package/messages/sf.provar.auth.clear.md +16 -0
- package/messages/sf.provar.auth.login.md +31 -0
- package/messages/sf.provar.auth.rotate.md +23 -0
- package/messages/sf.provar.auth.status.md +16 -0
- package/messages/sf.provar.mcp.start.md +83 -48
- package/oclif.manifest.json +325 -28
- package/package.json +23 -12
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
[](https://npmjs.org/package/@provartesting/provardx-cli)
|
|
4
4
|
[](https://npmjs.org/package/@provartesting/provardx-cli)
|
|
5
5
|
[](https://github.com/ProvarTesting/provardx-cli/blob/main/LICENSE.md)
|
|
6
|
+
[](https://aqqlrlhga7.execute-api.us-east-1.amazonaws.com/dev/auth/request-access)
|
|
6
7
|
|
|
7
8
|
# What is the ProvarDX CLI?
|
|
8
9
|
|
|
@@ -10,6 +11,8 @@ The Provar DX CLI is a Salesforce CLI plugin for Provar customers who want to au
|
|
|
10
11
|
|
|
11
12
|
# Installation, Update, and Uninstall
|
|
12
13
|
|
|
14
|
+
**Requires Node.js 18–24 (LTS 22 recommended).** Node 25+ is not yet supported due to a breaking change in a transitive dependency. Check with `node --version`.
|
|
15
|
+
|
|
13
16
|
Install the plugin
|
|
14
17
|
|
|
15
18
|
```sh-session
|
|
@@ -30,33 +33,83 @@ $ sf plugins uninstall @provartesting/provardx-cli
|
|
|
30
33
|
|
|
31
34
|
# MCP Server (AI-Assisted Quality)
|
|
32
35
|
|
|
33
|
-
The Provar DX CLI includes a built-in **Model Context Protocol (MCP) server** that connects AI assistants (Claude Desktop, Claude Code, Cursor) directly to your Provar project. Once connected, an AI agent can inspect your project structure, generate Page Objects and test cases,
|
|
36
|
+
The Provar DX CLI includes a built-in **Model Context Protocol (MCP) server** that connects AI assistants (Claude Desktop, Claude Code, Cursor) directly to your Provar project. Once connected, an AI agent can inspect your project structure, generate Page Objects and test cases, validate every level of the test hierarchy with quality scores, and work with NitroX (Hybrid Model) component page objects for LWC, Screen Flow, Industry Components, Experience Cloud, and HTML5.
|
|
37
|
+
|
|
38
|
+
Validation runs in two modes: **local only** (structural rules, no key required) or **Quality Hub API** (170+ rules, quality scoring — requires a `pv_k_` API key). Don't have an account? **[Request access](https://aqqlrlhga7.execute-api.us-east-1.amazonaws.com/dev/auth/request-access)**.
|
|
39
|
+
|
|
40
|
+
## Quick setup
|
|
41
|
+
|
|
42
|
+
**Requires:** Provar Automation IDE installed with an activated license. Node.js 18–24 must be on your PATH.
|
|
43
|
+
|
|
44
|
+
### Option A — Zero-install (recommended for Claude Desktop)
|
|
45
|
+
|
|
46
|
+
No prior setup needed. Paste this into your Claude Desktop config file and restart the app:
|
|
47
|
+
|
|
48
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
49
|
+
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"mcpServers": {
|
|
54
|
+
"provar": {
|
|
55
|
+
"command": "npx",
|
|
56
|
+
"args": ["-y", "@provartesting/provardx-cli", "mcp", "start", "--allowed-paths", "/path/to/your/provar/project"]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`npx -y` downloads the package automatically on first use — no `sf` or separate install step required.
|
|
63
|
+
|
|
64
|
+
**Claude Code** — run once to register the server:
|
|
34
65
|
|
|
35
66
|
```sh
|
|
36
|
-
|
|
67
|
+
claude mcp add provar -s user -- npx -y @provartesting/provardx-cli mcp start --allowed-paths /path/to/your/provar/project
|
|
37
68
|
```
|
|
38
69
|
|
|
39
|
-
|
|
70
|
+
### Option B — Global sf plugin install
|
|
40
71
|
|
|
41
|
-
|
|
72
|
+
Prefer a persistent global install? Install once, then use the `sf` command:
|
|
42
73
|
|
|
43
|
-
|
|
74
|
+
```sh
|
|
75
|
+
# 1. Install the plugin
|
|
76
|
+
sf plugins install @provartesting/provardx-cli
|
|
44
77
|
|
|
45
|
-
|
|
78
|
+
# 2. (Optional) Authenticate for full 170+ rule validation
|
|
79
|
+
sf provar auth login
|
|
80
|
+
```
|
|
46
81
|
|
|
47
|
-
|
|
48
|
-
2. **Cache** — successful validations are cached at `~/Provar/.licenses/.mcp-license-cache.json` (2 h TTL). Subsequent starts within the TTL window skip the disk scan.
|
|
49
|
-
3. **Grace fallback** — if the IDE license files cannot be found or read and the cache is stale (but ≤ 48 h old), the server starts with a warning on stderr using the cached result so CI pipelines are not broken by transient local file-access issues.
|
|
50
|
-
4. **Fail closed** — if no valid license is detected the command exits with a non-zero exit code and a clear error message.
|
|
82
|
+
**Claude Desktop** config using the global install:
|
|
51
83
|
|
|
52
|
-
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"mcpServers": {
|
|
87
|
+
"provar": {
|
|
88
|
+
"command": "sf",
|
|
89
|
+
"args": ["provar", "mcp", "start", "--allowed-paths", "/path/to/your/provar/project"]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
53
94
|
|
|
54
|
-
|
|
95
|
+
> **Windows (Claude Desktop):** Use `sf.cmd` instead of `sf` if the server fails to start.
|
|
96
|
+
|
|
97
|
+
**Claude Code** using the global install:
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
claude mcp add provar -s user -- sf provar mcp start --allowed-paths /path/to/your/provar/project
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
📖 **[docs/mcp.md](https://github.com/ProvarTesting/provardx-cli/blob/main/docs/mcp.md) — full setup, all 35+ tools, 11 MCP prompts, troubleshooting.**
|
|
55
104
|
|
|
56
105
|
---
|
|
57
106
|
|
|
58
107
|
# Commands
|
|
59
108
|
|
|
109
|
+
- [`sf provar auth login`](#sf-provar-auth-login)
|
|
110
|
+
- [`sf provar auth rotate`](#sf-provar-auth-rotate)
|
|
111
|
+
- [`sf provar auth status`](#sf-provar-auth-status)
|
|
112
|
+
- [`sf provar auth clear`](#sf-provar-auth-clear)
|
|
60
113
|
- [`sf provar mcp start`](#sf-provar-mcp-start)
|
|
61
114
|
- [`sf provar config get`](#sf-provar-config-get)
|
|
62
115
|
- [`sf provar config set`](#sf-provar-config-set)
|
|
@@ -84,6 +137,99 @@ When `NODE_ENV=test` the validation step is skipped entirely. This is intended o
|
|
|
84
137
|
- [`sf provar manager test run report`](#sf-provar-manager-test-run-report) _(deprecated — use `sf provar quality-hub test run report`)_
|
|
85
138
|
- [`sf provar manager test run abort`](#sf-provar-manager-test-run-abort) _(deprecated — use `sf provar quality-hub test run abort`)_
|
|
86
139
|
|
|
140
|
+
## `sf provar auth login`
|
|
141
|
+
|
|
142
|
+
Log in to Provar Quality Hub and store your API key.
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
USAGE
|
|
146
|
+
$ sf provar auth login [--url <value>]
|
|
147
|
+
|
|
148
|
+
FLAGS
|
|
149
|
+
--url=<value> Override the Quality Hub API base URL (for non-production environments).
|
|
150
|
+
|
|
151
|
+
DESCRIPTION
|
|
152
|
+
Opens a browser to the Provar login page. After you authenticate, your API key is
|
|
153
|
+
stored at ~/.provar/credentials.json and used automatically by the Provar MCP tools
|
|
154
|
+
and CI/CD integrations. The key is valid for approximately 90 days.
|
|
155
|
+
|
|
156
|
+
For CI/CD pipelines (GitHub Actions, Jenkins, etc.) where a browser cannot open:
|
|
157
|
+
run sf provar auth login once on your local machine, copy the api_key value from
|
|
158
|
+
~/.provar/credentials.json, and store it as the PROVAR_API_KEY environment variable
|
|
159
|
+
or secret in your pipeline. Rotate the secret every ~90 days when the key expires.
|
|
160
|
+
|
|
161
|
+
Don't have an account? Request access at:
|
|
162
|
+
https://aqqlrlhga7.execute-api.us-east-1.amazonaws.com/dev/auth/request-access
|
|
163
|
+
|
|
164
|
+
EXAMPLES
|
|
165
|
+
Log in interactively:
|
|
166
|
+
|
|
167
|
+
$ sf provar auth login
|
|
168
|
+
|
|
169
|
+
Log in against a staging environment:
|
|
170
|
+
|
|
171
|
+
$ sf provar auth login --url https://dev.api.example.com
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## `sf provar auth rotate`
|
|
175
|
+
|
|
176
|
+
Rotate your stored API key without re-authenticating via browser.
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
USAGE
|
|
180
|
+
$ sf provar auth rotate
|
|
181
|
+
|
|
182
|
+
DESCRIPTION
|
|
183
|
+
Exchanges your current pv_k_ key for a new one atomically. The old key is
|
|
184
|
+
invalidated immediately. The new key is written to ~/.provar/credentials.json.
|
|
185
|
+
|
|
186
|
+
Use this to rotate your key on a regular schedule (~every 90 days) without
|
|
187
|
+
going through the browser login flow. If your current key is already expired,
|
|
188
|
+
run sf provar auth login instead.
|
|
189
|
+
|
|
190
|
+
EXAMPLES
|
|
191
|
+
Rotate the stored API key:
|
|
192
|
+
|
|
193
|
+
$ sf provar auth rotate
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## `sf provar auth status`
|
|
197
|
+
|
|
198
|
+
Show the current API key configuration and validate it against Quality Hub.
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
USAGE
|
|
202
|
+
$ sf provar auth status
|
|
203
|
+
|
|
204
|
+
DESCRIPTION
|
|
205
|
+
Reports whether an API key is configured, where it came from (environment variable
|
|
206
|
+
or credentials file), and performs a live check against the Quality Hub API to
|
|
207
|
+
confirm the key is still valid.
|
|
208
|
+
|
|
209
|
+
EXAMPLES
|
|
210
|
+
Check auth status:
|
|
211
|
+
|
|
212
|
+
$ sf provar auth status
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## `sf provar auth clear`
|
|
216
|
+
|
|
217
|
+
Remove the stored API key.
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
USAGE
|
|
221
|
+
$ sf provar auth clear
|
|
222
|
+
|
|
223
|
+
DESCRIPTION
|
|
224
|
+
Deletes ~/.provar/credentials.json and revokes the key server-side. After clearing,
|
|
225
|
+
the MCP tools fall back to local validation mode. Has no effect if no key is stored.
|
|
226
|
+
|
|
227
|
+
EXAMPLES
|
|
228
|
+
Remove the stored key:
|
|
229
|
+
|
|
230
|
+
$ sf provar auth clear
|
|
231
|
+
```
|
|
232
|
+
|
|
87
233
|
## `sf provar mcp start`
|
|
88
234
|
|
|
89
235
|
Start a local MCP server for Provar tools over stdio transport.
|
|
@@ -136,6 +282,11 @@ TOOLS EXPOSED
|
|
|
136
282
|
provar.testplan.add-instance — wire a test case into a plan suite by writing a .testinstance file
|
|
137
283
|
provar.testplan.create-suite — create a new test suite directory with .planitem inside a plan
|
|
138
284
|
provar.testplan.remove-instance — remove a .testinstance file from a plan suite
|
|
285
|
+
provar.nitrox.discover — discover projects containing NitroX (Hybrid Model) page objects
|
|
286
|
+
provar.nitrox.read — read NitroX .po.json files and return parsed content
|
|
287
|
+
provar.nitrox.validate — validate a NitroX .po.json against schema rules
|
|
288
|
+
provar.nitrox.generate — generate a new NitroX .po.json from a component description
|
|
289
|
+
provar.nitrox.patch — apply a JSON merge-patch to an existing NitroX .po.json file
|
|
139
290
|
|
|
140
291
|
EXAMPLES
|
|
141
292
|
Start MCP server (accepts stdio connections from Claude Desktop / Cursor):
|
package/bin/mcp-start.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Lightweight zero-install entrypoint for the Provar MCP server.
|
|
3
|
+
// Usage: npx -y @provartesting/provardx-cli@beta mcp start --allowed-paths /path/to/project
|
|
4
|
+
|
|
5
|
+
const args = process.argv.slice(2);
|
|
6
|
+
|
|
7
|
+
if (args[0] !== 'mcp' || args[1] !== 'start') {
|
|
8
|
+
process.stderr.write(
|
|
9
|
+
'Usage: provardx mcp start --allowed-paths <path> [--auto-defects] [--auto-update] [--no-update-check]\n'
|
|
10
|
+
);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const remaining = args.slice(2);
|
|
15
|
+
/** @type {string[]} */
|
|
16
|
+
const allowedPaths = [];
|
|
17
|
+
let autoDefects = false;
|
|
18
|
+
let autoUpdate = false;
|
|
19
|
+
let noUpdateCheck = false;
|
|
20
|
+
|
|
21
|
+
for (let i = 0; i < remaining.length; i++) {
|
|
22
|
+
const arg = remaining[i];
|
|
23
|
+
if (arg === '--allowed-paths' || arg === '-a') {
|
|
24
|
+
if (i + 1 >= remaining.length) {
|
|
25
|
+
process.stderr.write('[provar-mcp] Error: --allowed-paths requires a path value.\n');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
allowedPaths.push(remaining[++i]);
|
|
29
|
+
} else if (arg.startsWith('--allowed-paths=')) {
|
|
30
|
+
allowedPaths.push(arg.slice('--allowed-paths='.length));
|
|
31
|
+
} else if (arg === '--auto-defects') {
|
|
32
|
+
autoDefects = true;
|
|
33
|
+
} else if (arg === '--auto-update') {
|
|
34
|
+
autoUpdate = true;
|
|
35
|
+
} else if (arg === '--no-update-check') {
|
|
36
|
+
noUpdateCheck = true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (allowedPaths.length === 0) {
|
|
41
|
+
process.stderr.write(
|
|
42
|
+
'[provar-mcp] Error: --allowed-paths is required.\n' +
|
|
43
|
+
'Example: npx -y @provartesting/provardx-cli@beta mcp start --allowed-paths /path/to/project\n'
|
|
44
|
+
);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (autoDefects) {
|
|
49
|
+
process.env['PROVAR_AUTO_DEFECTS'] = '1';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Dynamic imports placed after arg validation so early-exit paths need no compiled lib.
|
|
53
|
+
const { validateLicense, LicenseError } = await import('../lib/mcp/licensing/index.js');
|
|
54
|
+
const { checkForUpdate } = await import('../lib/mcp/update/updateChecker.js');
|
|
55
|
+
const { createProvarMcpServer } = await import('../lib/mcp/server.js');
|
|
56
|
+
const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js');
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const result = await validateLicense();
|
|
60
|
+
if (result.offlineGrace) {
|
|
61
|
+
process.stderr.write('[provar-mcp] Warning: license validated from offline cache (last checked > 2h ago).\n');
|
|
62
|
+
}
|
|
63
|
+
} catch (err) {
|
|
64
|
+
if (err instanceof LicenseError) {
|
|
65
|
+
process.stderr.write(`[provar-mcp] Error: ${/** @type {Error} */ (err).message}\n`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const updateResult = await checkForUpdate({ noUpdateCheck, autoUpdate });
|
|
72
|
+
const server = createProvarMcpServer({ allowedPaths, updateResult });
|
|
73
|
+
const transport = new StdioServerTransport();
|
|
74
|
+
await server.connect(transport);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Provar Limited.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* Licensed under the BSD 3-Clause license.
|
|
5
|
+
* For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
8
|
+
import { Messages } from '@provartesting/provardx-plugins-utils';
|
|
9
|
+
import { clearCredentials, readStoredCredentials } from '../../../services/auth/credentials.js';
|
|
10
|
+
import { qualityHubClient, getQualityHubBaseUrl } from '../../../services/qualityHub/client.js';
|
|
11
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
12
|
+
const messages = Messages.loadMessages('@provartesting/provardx-cli', 'sf.provar.auth.clear');
|
|
13
|
+
export default class SfProvarAuthClear extends SfCommand {
|
|
14
|
+
static summary = messages.getMessage('summary');
|
|
15
|
+
static description = messages.getMessage('description');
|
|
16
|
+
static examples = messages.getMessages('examples');
|
|
17
|
+
async run() {
|
|
18
|
+
const stored = readStoredCredentials();
|
|
19
|
+
if (stored) {
|
|
20
|
+
const baseUrl = getQualityHubBaseUrl();
|
|
21
|
+
try {
|
|
22
|
+
await qualityHubClient.revokeKey(stored.api_key, baseUrl);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
this.log(' Note: could not reach Quality Hub to revoke key server-side (offline?).');
|
|
26
|
+
this.log(' The local credentials have been removed — the key may still be valid until it expires.');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
clearCredentials();
|
|
30
|
+
this.log('API key cleared.');
|
|
31
|
+
this.log(' Next validation will use local rules only (structural checks, no quality scoring).');
|
|
32
|
+
this.log(' To reconfigure: sf provar auth login');
|
|
33
|
+
this.log(' For CI/CD: set the PROVAR_API_KEY environment variable.');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=clear.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clear.js","sourceRoot":"","sources":["../../../../src/commands/provar/auth/clear.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAChG,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAEhG,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,6BAA6B,EAAE,sBAAsB,CAAC,CAAC;AAE9F,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,SAAe;IACrD,MAAM,CAAU,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,CAAU,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACjE,MAAM,CAAU,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAE5D,KAAK,CAAC,GAAG;QACd,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;QACvC,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,OAAO,GAAG,oBAAoB,EAAE,CAAC;YACvC,IAAI,CAAC;gBACH,MAAM,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC5D,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,CAAC,GAAG,CAAC,2EAA2E,CAAC,CAAC;gBACtF,IAAI,CAAC,GAAG,CAAC,0FAA0F,CAAC,CAAC;YACvG,CAAC;QACH,CAAC;QAED,gBAAgB,EAAE,CAAC;QACnB,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,sFAAsF,CAAC,CAAC;QACjG,IAAI,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;QACnD,IAAI,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAC;IAC7E,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
export default class SfProvarAuthLogin extends SfCommand<void> {
|
|
3
|
+
static readonly summary: string;
|
|
4
|
+
static readonly description: string;
|
|
5
|
+
static readonly examples: string[];
|
|
6
|
+
static readonly flags: {
|
|
7
|
+
url: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Provar Limited.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* Licensed under the BSD 3-Clause license.
|
|
5
|
+
* For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
/* eslint-disable camelcase */
|
|
8
|
+
import { Flags, SfCommand } from '@salesforce/sf-plugins-core';
|
|
9
|
+
import { Messages } from '@provartesting/provardx-plugins-utils';
|
|
10
|
+
import { writeCredentials } from '../../../services/auth/credentials.js';
|
|
11
|
+
import { loginFlowClient } from '../../../services/auth/loginFlow.js';
|
|
12
|
+
import { qualityHubClient, getQualityHubBaseUrl, QualityHubAuthError, REQUEST_ACCESS_URL, } from '../../../services/qualityHub/client.js';
|
|
13
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
14
|
+
const messages = Messages.loadMessages('@provartesting/provardx-cli', 'sf.provar.auth.login');
|
|
15
|
+
// Production values bundled at auth handoff (2026-04-11).
|
|
16
|
+
// Override via PROVAR_COGNITO_DOMAIN / PROVAR_COGNITO_CLIENT_ID for non-prod environments.
|
|
17
|
+
const DEFAULT_COGNITO_DOMAIN = 'us-east-1xpfwzwmop.auth.us-east-1.amazoncognito.com';
|
|
18
|
+
const DEFAULT_CLIENT_ID = '29cs1a784r4cervmth8ugbkkri';
|
|
19
|
+
export default class SfProvarAuthLogin extends SfCommand {
|
|
20
|
+
static summary = messages.getMessage('summary');
|
|
21
|
+
static description = messages.getMessage('description');
|
|
22
|
+
static examples = messages.getMessages('examples');
|
|
23
|
+
static flags = {
|
|
24
|
+
url: Flags.string({
|
|
25
|
+
summary: messages.getMessage('flags.url.summary'),
|
|
26
|
+
required: false,
|
|
27
|
+
}),
|
|
28
|
+
};
|
|
29
|
+
async run() {
|
|
30
|
+
const { flags } = await this.parse(SfProvarAuthLogin);
|
|
31
|
+
const cognitoDomain = process.env.PROVAR_COGNITO_DOMAIN ?? DEFAULT_COGNITO_DOMAIN;
|
|
32
|
+
const clientId = process.env.PROVAR_COGNITO_CLIENT_ID ?? DEFAULT_CLIENT_ID;
|
|
33
|
+
const baseUrl = flags.url ?? getQualityHubBaseUrl();
|
|
34
|
+
// ── Step 1: Generate PKCE pair, nonce, and state ───────────────────────
|
|
35
|
+
const { verifier, challenge } = loginFlowClient.generatePkce();
|
|
36
|
+
const nonce = loginFlowClient.generateNonce();
|
|
37
|
+
const state = loginFlowClient.generateState();
|
|
38
|
+
// ── Step 2: Find an available registered callback port ──────────────────
|
|
39
|
+
const port = await loginFlowClient.findAvailablePort();
|
|
40
|
+
const redirectUri = `http://localhost:${port}/callback`;
|
|
41
|
+
// ── Step 3: Build the Cognito authorize URL ────────────────────────────
|
|
42
|
+
const authorizeUrl = new URL(`https://${cognitoDomain}/oauth2/authorize`);
|
|
43
|
+
authorizeUrl.searchParams.set('response_type', 'code');
|
|
44
|
+
authorizeUrl.searchParams.set('client_id', clientId);
|
|
45
|
+
authorizeUrl.searchParams.set('redirect_uri', redirectUri);
|
|
46
|
+
authorizeUrl.searchParams.set('code_challenge', challenge);
|
|
47
|
+
authorizeUrl.searchParams.set('code_challenge_method', 'S256');
|
|
48
|
+
authorizeUrl.searchParams.set('scope', 'openid email aws.cognito.signin.user.admin');
|
|
49
|
+
authorizeUrl.searchParams.set('state', state);
|
|
50
|
+
authorizeUrl.searchParams.set('nonce', nonce);
|
|
51
|
+
// ── Step 4: Open browser and wait for callback ──────────────────────────
|
|
52
|
+
this.log('Opening browser for login...');
|
|
53
|
+
this.log(` If the browser did not open, visit:\n ${authorizeUrl.toString()}`);
|
|
54
|
+
loginFlowClient.openBrowser(authorizeUrl.toString());
|
|
55
|
+
this.log('\nWaiting for authentication... (Ctrl-C to cancel)');
|
|
56
|
+
const authCode = await loginFlowClient.listenForCallback(port, state);
|
|
57
|
+
// ── Step 5: Exchange code for Cognito tokens ────────────────────────────
|
|
58
|
+
const tokens = await loginFlowClient.exchangeCodeForTokens({
|
|
59
|
+
code: authCode,
|
|
60
|
+
redirectUri,
|
|
61
|
+
clientId,
|
|
62
|
+
verifier,
|
|
63
|
+
tokenEndpoint: `https://${cognitoDomain}/oauth2/token`,
|
|
64
|
+
});
|
|
65
|
+
// ── Step 6: Exchange Cognito access token for pv_k_ key ─────────────────
|
|
66
|
+
// Cognito tokens are held in memory only — discarded after this call.
|
|
67
|
+
let keyData;
|
|
68
|
+
try {
|
|
69
|
+
keyData = await qualityHubClient.exchangeTokenForKey(tokens.access_token, baseUrl);
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
if (err instanceof QualityHubAuthError) {
|
|
73
|
+
this.error(`No Provar MCP account found for this login.\nRequest access at: ${REQUEST_ACCESS_URL}`, {
|
|
74
|
+
exit: 1,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
throw err;
|
|
78
|
+
}
|
|
79
|
+
// ── Step 7: Persist the pv_k_ key ──────────────────────────────────────
|
|
80
|
+
writeCredentials(keyData.api_key, keyData.prefix, 'cognito', {
|
|
81
|
+
username: keyData.username,
|
|
82
|
+
tier: keyData.tier,
|
|
83
|
+
expires_at: keyData.expires_at,
|
|
84
|
+
});
|
|
85
|
+
this.log(`\nAuthenticated as ${keyData.username} (${keyData.tier} tier)`);
|
|
86
|
+
this.log(`API key stored (prefix: ${keyData.prefix}). Valid until ${keyData.expires_at}.`);
|
|
87
|
+
this.log(" Run 'sf provar auth status' to check at any time.");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../../../src/commands/provar/auth/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Provar Limited.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* Licensed under the BSD 3-Clause license.
|
|
5
|
+
* For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
/* eslint-disable camelcase */
|
|
8
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
9
|
+
import { Messages } from '@provartesting/provardx-plugins-utils';
|
|
10
|
+
import { readStoredCredentials, writeCredentials } from '../../../services/auth/credentials.js';
|
|
11
|
+
import { qualityHubClient, getQualityHubBaseUrl, QualityHubAuthError } from '../../../services/qualityHub/client.js';
|
|
12
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
13
|
+
const messages = Messages.loadMessages('@provartesting/provardx-cli', 'sf.provar.auth.rotate');
|
|
14
|
+
export default class SfProvarAuthRotate extends SfCommand {
|
|
15
|
+
static summary = messages.getMessage('summary');
|
|
16
|
+
static description = messages.getMessage('description');
|
|
17
|
+
static examples = messages.getMessages('examples');
|
|
18
|
+
async run() {
|
|
19
|
+
const stored = readStoredCredentials();
|
|
20
|
+
if (!stored) {
|
|
21
|
+
this.error('No API key stored. Run `sf provar auth login` first.', { exit: 1 });
|
|
22
|
+
}
|
|
23
|
+
const baseUrl = getQualityHubBaseUrl();
|
|
24
|
+
try {
|
|
25
|
+
const keyData = await qualityHubClient.rotateKey(stored.api_key, baseUrl);
|
|
26
|
+
writeCredentials(keyData.api_key, keyData.prefix, 'cognito', {
|
|
27
|
+
username: keyData.username,
|
|
28
|
+
tier: keyData.tier,
|
|
29
|
+
expires_at: keyData.expires_at,
|
|
30
|
+
});
|
|
31
|
+
this.log(`API key rotated (new prefix: ${keyData.prefix}). Valid until ${keyData.expires_at}.`);
|
|
32
|
+
this.log(" Run 'sf provar auth status' to verify.");
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
if (err instanceof QualityHubAuthError) {
|
|
36
|
+
this.error('Current key is invalid or expired — rotation requires a valid key.\nRun `sf provar auth login` to authenticate via browser and get a fresh key.', { exit: 1 });
|
|
37
|
+
}
|
|
38
|
+
throw err;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=rotate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rotate.js","sourceRoot":"","sources":["../../../../src/commands/provar/auth/rotate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8BAA8B;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,uCAAuC,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAChG,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAErH,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,6BAA6B,EAAE,uBAAuB,CAAC,CAAC;AAE/F,MAAM,CAAC,OAAO,OAAO,kBAAmB,SAAQ,SAAe;IACtD,MAAM,CAAU,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,CAAU,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACjE,MAAM,CAAU,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAE5D,KAAK,CAAC,GAAG;QACd,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;QAEvC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,KAAK,CAAC,sDAAsD,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;QAClF,CAAC;QAED,MAAM,OAAO,GAAG,oBAAoB,EAAE,CAAC;QAEvC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC1E,gBAAgB,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE;gBAC3D,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,UAAU,EAAE,OAAO,CAAC,UAAU;aAC/B,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,gCAAgC,OAAO,CAAC,MAAM,kBAAkB,OAAO,CAAC,UAAU,GAAG,CAAC,CAAC;YAChG,IAAI,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;gBACvC,IAAI,CAAC,KAAK,CACR,iJAAiJ,EACjJ,EAAE,IAAI,EAAE,CAAC,EAAE,CACZ,CAAC;YACJ,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Provar Limited.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* Licensed under the BSD 3-Clause license.
|
|
5
|
+
* For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
/* eslint-disable camelcase */
|
|
8
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
9
|
+
import { Messages } from '@provartesting/provardx-plugins-utils';
|
|
10
|
+
import { readStoredCredentials } from '../../../services/auth/credentials.js';
|
|
11
|
+
import { qualityHubClient, getQualityHubBaseUrl, REQUEST_ACCESS_URL } from '../../../services/qualityHub/client.js';
|
|
12
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
13
|
+
const messages = Messages.loadMessages('@provartesting/provardx-cli', 'sf.provar.auth.status');
|
|
14
|
+
export default class SfProvarAuthStatus extends SfCommand {
|
|
15
|
+
static summary = messages.getMessage('summary');
|
|
16
|
+
static description = messages.getMessage('description');
|
|
17
|
+
static examples = messages.getMessages('examples');
|
|
18
|
+
async run() {
|
|
19
|
+
const envKey = process.env.PROVAR_API_KEY?.trim();
|
|
20
|
+
if (envKey) {
|
|
21
|
+
if (!envKey.startsWith('pv_k_')) {
|
|
22
|
+
this.log('Warning: PROVAR_API_KEY is set but invalid (does not start with "pv_k_").');
|
|
23
|
+
this.log(` Value: "${envKey.substring(0, 10)}..." — ignored for API calls.`);
|
|
24
|
+
this.log(' Fix: update PROVAR_API_KEY to a valid pv_k_ key from https://success.provartesting.com');
|
|
25
|
+
this.log('');
|
|
26
|
+
// Fall through to check stored credentials (matches resolveApiKey behaviour)
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
this.log('API key configured');
|
|
30
|
+
this.log(' Source: environment variable (PROVAR_API_KEY)');
|
|
31
|
+
this.log(` Prefix: ${envKey.substring(0, 12)}`);
|
|
32
|
+
this.log('');
|
|
33
|
+
this.log(' Validation mode: Quality Hub API');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const stored = readStoredCredentials();
|
|
38
|
+
if (stored) {
|
|
39
|
+
// Best-effort live check — silent fallback to cached values if offline or unconfigured.
|
|
40
|
+
// Does not run for env var keys (CI environments may not have outbound access).
|
|
41
|
+
let liveValid;
|
|
42
|
+
try {
|
|
43
|
+
const live = await qualityHubClient.fetchKeyStatus(stored.api_key, getQualityHubBaseUrl());
|
|
44
|
+
liveValid = live.valid;
|
|
45
|
+
if (live.username)
|
|
46
|
+
stored.username = live.username;
|
|
47
|
+
if (live.tier)
|
|
48
|
+
stored.tier = live.tier;
|
|
49
|
+
if (live.expires_at)
|
|
50
|
+
stored.expires_at = live.expires_at;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Offline or API not yet configured — use locally cached values
|
|
54
|
+
}
|
|
55
|
+
if (liveValid === false) {
|
|
56
|
+
this.log('API key expired or revoked.');
|
|
57
|
+
this.log(' Source: ~/.provar/credentials.json');
|
|
58
|
+
this.log(` Prefix: ${stored.prefix}`);
|
|
59
|
+
this.log('');
|
|
60
|
+
this.log(' Run: sf provar auth login to refresh your key.');
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
this.log('API key configured');
|
|
64
|
+
this.log(' Source: ~/.provar/credentials.json');
|
|
65
|
+
this.log(` Prefix: ${stored.prefix}`);
|
|
66
|
+
this.log(` Set at: ${stored.set_at}`);
|
|
67
|
+
if (stored.username)
|
|
68
|
+
this.log(` Account: ${stored.username}`);
|
|
69
|
+
if (stored.tier)
|
|
70
|
+
this.log(` Tier: ${stored.tier}`);
|
|
71
|
+
if (stored.expires_at) {
|
|
72
|
+
this.log(` Expires: ${stored.expires_at}`);
|
|
73
|
+
const expiresMs = new Date(stored.expires_at).getTime();
|
|
74
|
+
if (Number.isFinite(expiresMs)) {
|
|
75
|
+
const daysLeft = Math.ceil((expiresMs - Date.now()) / (1000 * 60 * 60 * 24));
|
|
76
|
+
if (daysLeft <= 14 && daysLeft > 0) {
|
|
77
|
+
this.log('');
|
|
78
|
+
this.log(` Warning: API key expires in ${daysLeft} day${daysLeft === 1 ? '' : 's'}.`);
|
|
79
|
+
this.log(" Run 'sf provar auth rotate' now to avoid CI/CD disruption.");
|
|
80
|
+
}
|
|
81
|
+
else if (daysLeft <= 0) {
|
|
82
|
+
this.log('');
|
|
83
|
+
this.log(' Warning: API key has expired. Run: sf provar auth login');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
this.log('');
|
|
88
|
+
this.log(' Warning: API key expiry timestamp is invalid.');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
this.log('');
|
|
92
|
+
this.log(' Validation mode: Quality Hub API');
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
this.log('No API key configured.');
|
|
96
|
+
this.log('');
|
|
97
|
+
this.log('To enable Quality Hub validation (170 rules):');
|
|
98
|
+
this.log(' Run: sf provar auth login');
|
|
99
|
+
this.log('');
|
|
100
|
+
this.log('For CI/CD: set the PROVAR_API_KEY environment variable.');
|
|
101
|
+
this.log('');
|
|
102
|
+
this.log(`No account? Request access at: ${REQUEST_ACCESS_URL}`);
|
|
103
|
+
this.log('');
|
|
104
|
+
this.log('Validation mode: local only (structural rules, no quality scoring)');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../../src/commands/provar/auth/status.ts"],"names":[],"mappings":"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"}
|