Skip to content

Commit b71f385

Browse files
committed
refactor(cli): unify identity/credential naming to 'credential'
The CLI command was 'add identity', the config key was 'credentials', and the resource types were ApiKeyCredentialProvider / OAuthCredentialProvider. Three different names for the same concept. This unifies everything under 'credential' — CLI commands, resource type, labels, validation, and docs. The old 'identity' command name is preserved as a hidden alias for backward compatibility. Constraint: Must maintain backward compat for existing scripts using 'agentcore add identity' Rejected: Keep 'identity' as primary | 'credential' is already the config term and more precise Confidence: high Scope-risk: moderate
1 parent 6b1cf79 commit b71f385

19 files changed

Lines changed: 76 additions & 70 deletions

src/cli/commands/add/__tests__/add-identity.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { tmpdir } from 'node:os';
55
import { join } from 'node:path';
66
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
77

8-
describe('add identity command', () => {
8+
describe('add credential command', () => {
99
let testDir: string;
1010
let projectDir: string;
1111

@@ -28,27 +28,27 @@ describe('add identity command', () => {
2828

2929
describe('validation', () => {
3030
it('requires name flag', async () => {
31-
const result = await runCLI(['add', 'identity', '--json'], projectDir);
31+
const result = await runCLI(['add', 'credential', '--json'], projectDir);
3232
expect(result.exitCode).toBe(1);
3333
const json = JSON.parse(result.stdout);
3434
expect(json.success).toBe(false);
3535
expect(json.error.includes('--name'), `Error: ${json.error}`).toBeTruthy();
3636
});
3737

3838
it('requires api-key flag', async () => {
39-
const result = await runCLI(['add', 'identity', '--name', 'test', '--json'], projectDir);
39+
const result = await runCLI(['add', 'credential', '--name', 'test', '--json'], projectDir);
4040
expect(result.exitCode).toBe(1);
4141
const json = JSON.parse(result.stdout);
4242
expect(json.success).toBe(false);
4343
expect(json.error.includes('--api-key'), `Error: ${json.error}`).toBeTruthy();
4444
});
4545
});
4646

47-
describe('identity creation', () => {
47+
describe('credential creation', () => {
4848
it('creates credential as top-level resource', async () => {
4949
const identityName = `id${Date.now()}`;
5050
const result = await runCLI(
51-
['add', 'identity', '--name', identityName, '--api-key', 'test-key-123', '--json'],
51+
['add', 'credential', '--name', identityName, '--api-key', 'test-key-123', '--json'],
5252
projectDir
5353
);
5454

@@ -65,13 +65,13 @@ describe('add identity command', () => {
6565
});
6666
});
6767

68-
describe('oauth identity creation', () => {
68+
describe('oauth credential creation', () => {
6969
it('creates OAuth credential with discovery URL and scopes', async () => {
7070
const identityName = `oauth-${Date.now()}`;
7171
const result = await runCLI(
7272
[
7373
'add',
74-
'identity',
74+
'credential',
7575
'--type',
7676
'oauth',
7777
'--name',

src/cli/commands/add/__tests__/validate.test.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import type {
22
AddAgentOptions,
3+
AddCredentialOptions,
34
AddGatewayOptions,
45
AddGatewayTargetOptions,
5-
AddIdentityOptions,
66
AddMemoryOptions,
77
} from '../types.js';
88
import {
99
validateAddAgentOptions,
10+
validateAddCredentialOptions,
1011
validateAddGatewayOptions,
1112
validateAddGatewayTargetOptions,
12-
validateAddIdentityOptions,
1313
validateAddMemoryOptions,
1414
} from '../validate.js';
1515
import { existsSync, readFileSync } from 'fs';
@@ -75,7 +75,7 @@ const validMemoryOptions: AddMemoryOptions = {
7575
strategies: 'SEMANTIC,SUMMARIZATION',
7676
};
7777

78-
const validIdentityOptions: AddIdentityOptions = {
78+
const validCredentialOptions: AddCredentialOptions = {
7979
name: 'test-identity',
8080
apiKey: 'test-key',
8181
};
@@ -996,25 +996,25 @@ describe('validate', () => {
996996
});
997997
});
998998

999-
describe('validateAddIdentityOptions', () => {
999+
describe('validateAddCredentialOptions', () => {
10001000
// AC23: Required fields validated
10011001
it('returns error for missing required fields', () => {
1002-
const requiredFields: { field: keyof AddIdentityOptions; error: string }[] = [
1002+
const requiredFields: { field: keyof AddCredentialOptions; error: string }[] = [
10031003
{ field: 'name', error: '--name is required' },
10041004
{ field: 'apiKey', error: '--api-key is required' },
10051005
];
10061006

10071007
for (const { field, error } of requiredFields) {
1008-
const opts = { ...validIdentityOptions, [field]: undefined };
1009-
const result = validateAddIdentityOptions(opts);
1008+
const opts = { ...validCredentialOptions, [field]: undefined };
1009+
const result = validateAddCredentialOptions(opts);
10101010
expect(result.valid, `Should fail for missing ${String(field)}`).toBe(false);
10111011
expect(result.error).toBe(error);
10121012
}
10131013
});
10141014

10151015
// AC25: Valid options pass
10161016
it('passes for valid options', () => {
1017-
expect(validateAddIdentityOptions(validIdentityOptions)).toEqual({ valid: true });
1017+
expect(validateAddCredentialOptions(validCredentialOptions)).toEqual({ valid: true });
10181018
});
10191019
});
10201020

@@ -1193,9 +1193,9 @@ describe('validate', () => {
11931193
});
11941194
});
11951195

1196-
describe('validateAddIdentityOptions OAuth', () => {
1196+
describe('validateAddCredentialOptions OAuth', () => {
11971197
it('passes for valid OAuth identity', () => {
1198-
const result = validateAddIdentityOptions({
1198+
const result = validateAddCredentialOptions({
11991199
name: 'my-oauth',
12001200
type: 'oauth',
12011201
discoveryUrl: 'https://auth.example.com/.well-known/openid-configuration',
@@ -1206,7 +1206,7 @@ describe('validate', () => {
12061206
});
12071207

12081208
it('returns error for OAuth without discovery-url', () => {
1209-
const result = validateAddIdentityOptions({
1209+
const result = validateAddCredentialOptions({
12101210
name: 'my-oauth',
12111211
type: 'oauth',
12121212
clientId: 'client123',
@@ -1217,7 +1217,7 @@ describe('validate', () => {
12171217
});
12181218

12191219
it('returns error for OAuth without client-id', () => {
1220-
const result = validateAddIdentityOptions({
1220+
const result = validateAddCredentialOptions({
12211221
name: 'my-oauth',
12221222
type: 'oauth',
12231223
discoveryUrl: 'https://auth.example.com',
@@ -1228,7 +1228,7 @@ describe('validate', () => {
12281228
});
12291229

12301230
it('returns error for OAuth without client-secret', () => {
1231-
const result = validateAddIdentityOptions({
1231+
const result = validateAddCredentialOptions({
12321232
name: 'my-oauth',
12331233
type: 'oauth',
12341234
discoveryUrl: 'https://auth.example.com',
@@ -1239,7 +1239,7 @@ describe('validate', () => {
12391239
});
12401240

12411241
it('still requires api-key for default type', () => {
1242-
const result = validateAddIdentityOptions({ name: 'my-key' });
1242+
const result = validateAddCredentialOptions({ name: 'my-key' });
12431243
expect(result.valid).toBe(false);
12441244
expect(result.error).toContain('--api-key');
12451245
});

src/cli/commands/add/command.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export function registerAdd(program: Command): Command {
3333
);
3434
});
3535

36-
// Subcommands (agent, memory, identity, gateway, gateway-target) are registered
36+
// Subcommands (agent, memory, credential, gateway, gateway-target) are registered
3737
// via primitive.registerCommands() in cli.ts
3838

3939
return addCmd;

src/cli/commands/add/types.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ export interface AddMemoryResult {
118118
error?: string;
119119
}
120120

121-
// Identity types (v2: credential, no owner/user concept)
122-
export interface AddIdentityOptions {
121+
// Credential types (v2: credential, no owner/user concept)
122+
export interface AddCredentialOptions {
123123
name?: string;
124124
type?: 'api-key' | 'oauth';
125125
apiKey?: string;
@@ -130,7 +130,10 @@ export interface AddIdentityOptions {
130130
json?: boolean;
131131
}
132132

133-
export interface AddIdentityResult {
133+
/** @deprecated Use AddCredentialOptions */
134+
export type AddIdentityOptions = AddCredentialOptions;
135+
136+
export interface AddCredentialResult {
134137
success: boolean;
135138
credentialName?: string;
136139
error?: string;

src/cli/commands/add/validate.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ import { validateVpcOptions } from '../shared/vpc-utils';
1919
import { validateJwtAuthorizerOptions } from './auth-options';
2020
import type {
2121
AddAgentOptions,
22+
AddCredentialOptions,
2223
AddGatewayOptions,
2324
AddGatewayTargetOptions,
24-
AddIdentityOptions,
2525
AddMemoryOptions,
2626
} from './types';
2727
import { existsSync, readFileSync } from 'fs';
@@ -50,7 +50,7 @@ async function validateCredentialExists(credentialName: string): Promise<Validat
5050
if (availableCredentials.length === 0) {
5151
return {
5252
valid: false,
53-
error: `Credential "${credentialName}" not found. No credentials are configured. Add credentials using 'agentcore add identity'.`,
53+
error: `Credential "${credentialName}" not found. No credentials are configured. Add credentials using 'agentcore add credential'.`,
5454
};
5555
}
5656
return {
@@ -680,8 +680,8 @@ export function validateAddMemoryOptions(options: AddMemoryOptions): ValidationR
680680
return { valid: true };
681681
}
682682

683-
// Identity validation (v2: credential resource, no owner)
684-
export function validateAddIdentityOptions(options: AddIdentityOptions): ValidationResult {
683+
// Credential validation (v2: credential resource, no owner)
684+
export function validateAddCredentialOptions(options: AddCredentialOptions): ValidationResult {
685685
if (!options.name) {
686686
return { valid: false, error: '--name is required' };
687687
}

src/cli/commands/remove/__tests__/remove-identity.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { tmpdir } from 'node:os';
55
import { join } from 'node:path';
66
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
77

8-
describe('remove identity command', () => {
8+
describe('remove credential command', () => {
99
let testDir: string;
1010
let projectDir: string;
1111
const identityName = 'TestIdentity';
@@ -24,7 +24,7 @@ describe('remove identity command', () => {
2424

2525
// Add identity as top-level credential
2626
result = await runCLI(
27-
['add', 'identity', '--name', identityName, '--api-key', 'test-key-123', '--json'],
27+
['add', 'credential', '--name', identityName, '--api-key', 'test-key-123', '--json'],
2828
projectDir
2929
);
3030
if (result.exitCode !== 0) {
@@ -38,15 +38,15 @@ describe('remove identity command', () => {
3838

3939
describe('validation', () => {
4040
it('requires name flag', async () => {
41-
const result = await runCLI(['remove', 'identity', '--json'], projectDir);
41+
const result = await runCLI(['remove', 'credential', '--json'], projectDir);
4242
expect(result.exitCode).toBe(1);
4343
const json = JSON.parse(result.stdout);
4444
expect(json.success).toBe(false);
4545
expect(json.error.includes('--name'), `Error: ${json.error}`).toBeTruthy();
4646
});
4747

4848
it('rejects non-existent identity', async () => {
49-
const result = await runCLI(['remove', 'identity', '--name', 'nonexistent', '--json'], projectDir);
49+
const result = await runCLI(['remove', 'credential', '--name', 'nonexistent', '--json'], projectDir);
5050
expect(result.exitCode).toBe(1);
5151
const json = JSON.parse(result.stdout);
5252
expect(json.success).toBe(false);
@@ -58,9 +58,9 @@ describe('remove identity command', () => {
5858
it('removes credential without dependents', async () => {
5959
// Add a temp credential to remove
6060
const tempId = `tempId${Date.now()}`;
61-
await runCLI(['add', 'identity', '--name', tempId, '--api-key', 'temp-key', '--json'], projectDir);
61+
await runCLI(['add', 'credential', '--name', tempId, '--api-key', 'temp-key', '--json'], projectDir);
6262

63-
const result = await runCLI(['remove', 'identity', '--name', tempId, '--json'], projectDir);
63+
const result = await runCLI(['remove', 'credential', '--name', tempId, '--json'], projectDir);
6464
expect(result.exitCode, `stdout: ${result.stdout}`).toBe(0);
6565
const json = JSON.parse(result.stdout);
6666
expect(json.success).toBe(true);
@@ -72,7 +72,7 @@ describe('remove identity command', () => {
7272
});
7373

7474
it('removes the setup credential', async () => {
75-
const result = await runCLI(['remove', 'identity', '--name', identityName, '--json'], projectDir);
75+
const result = await runCLI(['remove', 'credential', '--name', identityName, '--json'], projectDir);
7676
expect(result.exitCode, `stdout: ${result.stdout}`).toBe(0);
7777
const json = JSON.parse(result.stdout);
7878
expect(json.success).toBe(true);

src/cli/commands/remove/__tests__/validate.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ describe('validateRemoveOptions', () => {
2121
});
2222

2323
it('returns valid with no json and no name', () => {
24-
expect(validateRemoveOptions({ resourceType: 'identity' })).toEqual({ valid: true });
24+
expect(validateRemoveOptions({ resourceType: 'credential' })).toEqual({ valid: true });
2525
});
2626
});
2727

src/cli/commands/remove/command.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export const registerRemove = (program: Command): Command => {
9595
}
9696
});
9797

98-
// Resource subcommands (agent, memory, identity, gateway, mcp-tool) are registered
98+
// Resource subcommands (agent, memory, credential, gateway, mcp-tool) are registered
9999
// via primitive.registerCommands() in cli.ts
100100

101101
// Catch-all for TUI fallback when no subcommand is specified.

src/cli/commands/remove/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ export type ResourceType =
33
| 'gateway'
44
| 'gateway-target'
55
| 'memory'
6-
| 'identity'
6+
| 'credential'
77
| 'evaluator'
88
| 'online-eval'
99
| 'policy-engine'

src/cli/logging/remove-logger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export interface RemoveLoggerOptions {
1010
resourceType:
1111
| 'agent'
1212
| 'memory'
13-
| 'identity'
13+
| 'credential'
1414
| 'gateway'
1515
| 'gateway-target'
1616
| 'evaluator'

0 commit comments

Comments
 (0)