Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
362b17a
feat(auth): add credentials service with key storage and resolution
mrdailey99 Apr 10, 2026
0ae5443
feat(auth): add set-key, status, and clear commands
mrdailey99 Apr 10, 2026
81d61ff
feat(auth): add Quality Hub API client stub + wire validate tool with…
mrdailey99 Apr 10, 2026
d5549f6
fix(auth): address PR #116 review comments and add auth NUT tests
mrdailey99 Apr 10, 2026
e8d58ad
fix(nuts): correct prefix length assertions in auth NUT tests
mrdailey99 Apr 11, 2026
f67c467
fix(nuts): correct status prefix assertion; always upload NUT artifacts
mrdailey99 Apr 11, 2026
520fd8c
docs(auth): update Phase 2 plan with PKCE decisions from AWS team
mrdailey99 Apr 11, 2026
e08cdaf
docs(auth): add confirmed endpoint paths and revoke/status integration
mrdailey99 Apr 11, 2026
6e1d1ae
feat(auth): implement sf provar auth login with PKCE/Cognito flow (Ph…
mrdailey99 Apr 12, 2026
da8c5c7
fix(auth): send Cognito token in request body for /auth/exchange; bum…
mrdailey99 Apr 12, 2026
788cfcf
fix(auth): remove x-api-key from auth routes; send token in body; bum…
mrdailey99 Apr 12, 2026
755b399
docs: document auth commands and Quality Hub validation modes across …
mrdailey99 Apr 12, 2026
a2fe327
fix(auth): correct Cognito Hosted UI domain
mrdailey99 Apr 12, 2026
50e2519
fix(auth): add OIDC nonce to authorize URL; drop profile scope
mrdailey99 Apr 12, 2026
d09dfe4
fix(auth): switch to /login endpoint; add state param for Cognito Man…
mrdailey99 Apr 12, 2026
6925b19
fix(auth): revert to /oauth2/authorize — state was the missing piece
mrdailey99 Apr 12, 2026
30d450a
fix(auth): use PowerShell Start-Process on Windows to open browser
mrdailey99 Apr 12, 2026
f2c7c6b
fix(auth): add aws.cognito.signin.user.admin scope; improve clear mes…
mrdailey99 Apr 12, 2026
b1a8dfc
docs(auth): explain CI/CD key extraction and 90-day rotation
mrdailey99 Apr 12, 2026
4816dea
feat(auth): implement validateTestCaseViaApi; remove getInfraKey
mrdailey99 Apr 12, 2026
fc2a8a6
chore(auth): remove sf provar auth set-key command
mrdailey99 Apr 12, 2026
0fa223b
fix(test): add eslint-disable camelcase to auth NUT fixtures
mrdailey99 Apr 12, 2026
10a1fc5
feat(auth): add sf provar auth rotate command
mrdailey99 Apr 13, 2026
657c9f9
fix: address PR #116 review comments
mrdailey99 Apr 13, 2026
970cdde
fix(test): update NUT assertion for revised status warning wording
mrdailey99 Apr 13, 2026
e2f6c66
feat(auth): surface request-access URL for users without accounts
mrdailey99 Apr 13, 2026
f4d34c9
Update badge label for Quality Hub API access
mrdailey99 Apr 13, 2026
31a262c
docs: use @beta install tag and add NitroX tools to README
mrdailey99 Apr 13, 2026
eb7178c
docs: add Node 18-24 requirement, warn about Node 25+ incompatibility
mrdailey99 Apr 13, 2026
1ded191
docs: fix MCP setup instructions with correct Claude Code commands
mrdailey99 Apr 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
577 changes: 577 additions & 0 deletions docs/auth-cli-plan.md

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions messages/sf.provar.auth.clear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# summary
Remove the stored Provar API key.

# description
Deletes the API key stored at ~/.provar/credentials.json. After clearing, the
provar.testcase.validate MCP tool falls back to local validation (structural rules only,
no Quality Hub quality scoring).

The PROVAR_API_KEY environment variable is not affected by this command.

# examples
- Clear the stored API key:
<%= config.bin %> <%= command.id %>
19 changes: 19 additions & 0 deletions messages/sf.provar.auth.set-key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# summary
Store a Provar API key for Quality Hub validation.

# description
Saves a Provar API key to ~/.provar/credentials.json so the MCP server can call the
Quality Hub validation API automatically. Keys must start with "pv_k_". The full key
is never echoed — only the prefix is shown after storing.

To get a key, visit https://success.provartesting.com.

For CI/CD environments, set the PROVAR_API_KEY environment variable instead of using
this command.

# flags.key.summary
Provar API key to store. Must start with "pv_k_". The value is stored on disk; the full key is never printed back.

# examples
- Store an API key:
<%= config.bin %> <%= command.id %> --key pv_k_yourkeyhere
11 changes: 11 additions & 0 deletions messages/sf.provar.auth.status.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# summary
Show the current Provar API key configuration status.

# description
Reports where the active API key comes from (environment variable or stored file),
shows the key prefix and when it was set, and states whether validation will use the
Quality Hub API or local rules only. The full key is never printed.

# examples
- Check auth status:
<%= config.bin %> <%= command.id %>
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@
}
}
},
"auth": {
"description": "Commands to manage Provar API key authentication."
},
"automation": {
"description": "Commands to interact with Provar Automation.",
"subtopics": {
Expand Down
27 changes: 27 additions & 0 deletions src/commands/provar/auth/clear.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2024 Provar Limited.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import { SfCommand } from '@salesforce/sf-plugins-core';
import { Messages } from '@provartesting/provardx-plugins-utils';
import { clearCredentials } from '../../../services/auth/credentials.js';

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@provartesting/provardx-cli', 'sf.provar.auth.clear');

export default class SfProvarAuthClear extends SfCommand<void> {
public static readonly summary = messages.getMessage('summary');
public static readonly description = messages.getMessage('description');
public static readonly examples = messages.getMessages('examples');

// eslint-disable-next-line @typescript-eslint/require-await
public async run(): Promise<void> {
clearCredentials();
this.log('API key cleared.');
this.log(' Next validation will use local rules only (structural checks, no quality scoring).');
this.log(' To reconfigure, run: sf provar auth set-key --key <your-key>');
}
}
44 changes: 44 additions & 0 deletions src/commands/provar/auth/set-key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2024 Provar Limited.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import { Flags, SfCommand } from '@salesforce/sf-plugins-core';
import { Messages } from '@provartesting/provardx-plugins-utils';
import { writeCredentials } from '../../../services/auth/credentials.js';

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@provartesting/provardx-cli', 'sf.provar.auth.set-key');

export default class SfProvarAuthSetKey extends SfCommand<void> {
public static readonly summary = messages.getMessage('summary');
public static readonly description = messages.getMessage('description');
public static readonly examples = messages.getMessages('examples');

public static readonly flags = {
key: Flags.string({
summary: messages.getMessage('flags.key.summary'),
required: true,
}),
};

public async run(): Promise<void> {
const { flags } = await this.parse(SfProvarAuthSetKey);
const key = flags.key;

if (!key.startsWith('pv_k_')) {
this.error(
'Invalid API key format. Keys must start with "pv_k_". Get your key from https://success.provartesting.com.',
{ exit: 1 }
);
}

const prefix = key.substring(0, 12);
writeCredentials(key, prefix, 'manual');
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider trimming the provided --key value before validating/storing it (e.g., key.trim()). As-is, accidental whitespace will cause startsWith('pv_k_') checks to fail or can be persisted to disk, leading to confusing auth behavior.

Copilot uses AI. Check for mistakes.

this.log(`API key stored (prefix: ${prefix}).`);
this.log("Run 'sf provar auth status' to verify.");
}
}
57 changes: 57 additions & 0 deletions src/commands/provar/auth/status.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2024 Provar Limited.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.md file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import { SfCommand } from '@salesforce/sf-plugins-core';
import { Messages } from '@provartesting/provardx-plugins-utils';
import { readStoredCredentials } from '../../../services/auth/credentials.js';

Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
const messages = Messages.loadMessages('@provartesting/provardx-cli', 'sf.provar.auth.status');

export default class SfProvarAuthStatus extends SfCommand<void> {
public static readonly summary = messages.getMessage('summary');
public static readonly description = messages.getMessage('description');
public static readonly examples = messages.getMessages('examples');

// eslint-disable-next-line @typescript-eslint/require-await
public async run(): Promise<void> {
const envKey = process.env.PROVAR_API_KEY?.trim();

if (envKey) {
this.log('API key configured');
this.log(' Source: environment variable (PROVAR_API_KEY)');
this.log(` Prefix: ${envKey.substring(0, 12)}`);
this.log('');
this.log(' Validation mode: Quality Hub API');
return;
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The status command treats any non-empty PROVAR_API_KEY as a configured Provar key. If the env var is set to an unexpected value (wrong prefix/typo), status will still report "Validation mode: Quality Hub API". Consider validating the pv_k_ prefix here (or delegating to a shared validator) and reporting an invalid configuration instead.

Copilot uses AI. Check for mistakes.
}

const stored = readStoredCredentials();
if (stored) {
this.log('API key configured');
this.log(' Source: ~/.provar/credentials.json');
this.log(` Prefix: ${stored.prefix}`);
this.log(` Set at: ${stored.set_at}`);
if (stored.username) this.log(` Account: ${stored.username}`);
if (stored.tier) this.log(` Tier: ${stored.tier}`);
if (stored.expires_at) this.log(` Expires: ${stored.expires_at}`);
this.log('');
this.log(' Validation mode: Quality Hub API');
return;
}

this.log('No API key configured.');
this.log('');
this.log('To enable Quality Hub validation (170 rules):');
this.log(' 1. Get your API key from https://success.provartesting.com');
this.log(' 2. Run: sf provar auth set-key --key <your-key>');
this.log('');
this.log('For CI/CD: set the PROVAR_API_KEY environment variable.');
this.log('');
this.log('Validation mode: local only (structural rules, no quality scoring)');
}
}
Loading
Loading