Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
3bbc375
feat(project): model payment connector variants
aidandaly24 Aug 26, 2026
0c6a8c3
feat(project): support payment resource mutations
aidandaly24 Aug 26, 2026
2289385
feat(project): add payment credential command
aidandaly24 Aug 26, 2026
4745c99
feat(project): add payment manager and connector commands
aidandaly24 Aug 26, 2026
5cd51aa
feat(project): wire Quick Create into generated CDK
aidandaly24 Aug 26, 2026
741d735
refactor(project): use type aliases for payment connector specs
aidandaly24 Aug 26, 2026
eb233fe
refactor(project): clarify payment connector construction
aidandaly24 Aug 26, 2026
a87e638
refactor(project): expose payment manager removal contract
aidandaly24 Aug 26, 2026
fd6a259
feat(project): add payment manager removal
aidandaly24 Aug 26, 2026
ce66d49
refactor(project): expose payment connector removal contract
aidandaly24 Aug 27, 2026
064bbab
feat(project): add payment connector removal
aidandaly24 Aug 27, 2026
eea2d76
fix(project): reject payment manager environment collisions
aidandaly24 Aug 27, 2026
f694c0d
fix(project): guard quick create for legacy CDK assets
aidandaly24 Aug 27, 2026
5a16682
fix(project): preserve payment connector CDK identities
aidandaly24 Aug 27, 2026
8944f5f
fix(project): collect payment credential values
aidandaly24 Aug 27, 2026
a35f487
fix(project): support compound credential environment entries
aidandaly24 Aug 27, 2026
1bd6d00
fix(project): persist connector-created payment credentials
aidandaly24 Aug 27, 2026
b39cdc4
fix(project): require explicit payment credentials
aidandaly24 Aug 27, 2026
8a7d322
refactor(project): remove compound payment credential mutation
aidandaly24 Aug 27, 2026
1f8bf87
chore: merge refactor into project payments
aidandaly24 Aug 27, 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
34 changes: 28 additions & 6 deletions src/assets/cdk/bin/cdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,14 +146,12 @@ async function main() {

// Extract credentials from deployed state for this target
const targetState = (deployedState as Record<string, unknown>)?.targets as
| Record<string, Record<string, unknown>>
| undefined;
Record<string, Record<string, unknown>> | undefined;
const targetResources = target
? (targetState?.[target.name]?.resources as Record<string, unknown> | undefined)
: undefined;
const credentials = targetResources?.credentials as
| Record<string, { credentialProviderArn: string; clientSecretArn?: string }>
| undefined;
Record<string, { credentialProviderArn: string; clientSecretArn?: string }> | undefined;

// Payment credential provider ARNs live in the same credentials map as identity credentials
const paymentCredentials = credentials;
Expand All @@ -168,7 +166,12 @@ async function main() {
autoPayment?: boolean;
paymentToolAllowlist?: string[];
networkPreferences?: string[];
connectors: { name: string; provider?: string; credentialName: string }[];
connectors: {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This Schema change is already on main, but wasn't done in the fork.

name: string;
provider?: 'CoinbaseCDP' | 'StripePrivy';
provisionMode?: 'MANUAL' | 'QUICK_CREATE';
credentialName?: string;
}[];
}) => ({
name: p.name,
description: p.description,
Expand All @@ -178,6 +181,19 @@ async function main() {
paymentToolAllowlist: p.paymentToolAllowlist,
networkPreferences: p.networkPreferences,
connectors: p.connectors.map(c => {
if (c.provisionMode === 'QUICK_CREATE') {
return {
name: c.name,
provider: 'CoinbaseCDP' as const,
provisionMode: 'QUICK_CREATE' as const,
};
}

if (!c.credentialName) {
throw new Error(
`Manual payment connector "${c.name}" on manager "${p.name}" is missing its credential name.`
);
}
const credentialProviderArn = paymentCredentials?.[c.credentialName]?.credentialProviderArn;
if (!credentialProviderArn) {
// Fail fast with an actionable message rather than passing an empty
Expand All @@ -188,7 +204,13 @@ async function main() {
`Run \`agentcore deploy\` so the credential provider is created first.`
);
}
return { name: c.name, provider: c.provider, credentialProviderArn };
return {
name: c.name,
provider: c.provider ?? ('CoinbaseCDP' as const),
...(c.provisionMode && { provisionMode: c.provisionMode }),
credentialName: c.credentialName,
credentialProviderArn,
};
}),
})
)
Expand Down
61 changes: 47 additions & 14 deletions src/assets/cdk/lib/cdk-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,23 @@ import { Construct } from 'constructs';
*/
export type HarnessConfig = HarnessDeploymentConfig;

export interface PaymentConnectorSpec {
export type ManualPaymentConnectorSpec = {
name: string;
provider: 'CoinbaseCDP' | 'StripePrivy';
provisionMode?: 'MANUAL';
credentialName: string;
credentialProviderArn: string;
}
};

export type QuickCreatePaymentConnectorSpec = {
name: string;
provider: 'CoinbaseCDP';
provisionMode: 'QUICK_CREATE';
credentialName?: never;
credentialProviderArn?: never;
};

export type PaymentConnectorSpec = ManualPaymentConnectorSpec | QuickCreatePaymentConnectorSpec;

export interface PaymentSpec {
name: string;
Expand Down Expand Up @@ -64,8 +76,8 @@ export interface AgentCoreStackProps extends StackProps {
paymentSpec?: PaymentSpec[];
}

function toCdkId(name: string): string {
return name.replace(/_/g, '');
function paymentConnectorCdkId(managerName: string, connectorName: string): string {
return `PaymentM${managerName.length}${managerName}C${connectorName.length}${connectorName}`;
}

/**
Expand Down Expand Up @@ -127,7 +139,7 @@ export class AgentCoreStack extends Stack {
// Create payment infrastructure via CFN constructs
if (paymentSpec && paymentSpec.length > 0) {
for (const payment of paymentSpec) {
const mgrId = toCdkId(payment.name);
const mgrId = payment.name;
const manager = new AgentCorePaymentManager(this, `Payment${mgrId}`, {
projectName: spec.name,
name: payment.name,
Expand Down Expand Up @@ -202,14 +214,27 @@ export class AgentCoreStack extends Stack {

// Create connectors for this manager
for (const connector of payment.connectors) {
const connId = toCdkId(connector.name);
const conn = new AgentCorePaymentConnector(this, `Payment${mgrId}${connId}`, {
projectName: spec.name,
paymentManager: manager,
connectorName: connector.name,
connectorType: connector.provider,
credentialProviderArn: connector.credentialProviderArn,
});
const connectorCdkId = paymentConnectorCdkId(payment.name, connector.name);
let conn: AgentCorePaymentConnector;
if (connector.provisionMode === 'QUICK_CREATE') {
conn = new AgentCorePaymentConnector(this, connectorCdkId, {
projectName: spec.name,
paymentManager: manager,
connector,
});
} else {
conn = new AgentCorePaymentConnector(this, connectorCdkId, {
projectName: spec.name,
paymentManager: manager,
connector: {
name: connector.name,
provider: connector.provider,
provisionMode: connector.provisionMode,
credentialName: connector.credentialName,
},
credentialProviderArn: connector.credentialProviderArn,
});
}

// Wire first connector's ID as env var (eligible agents only)
if (connector === payment.connectors[0]) {
Expand All @@ -219,9 +244,17 @@ export class AgentCoreStack extends Stack {
}
}

new CfnOutput(this, `Payment${mgrId}${connId}ConnectorId`, {
new CfnOutput(this, `${connectorCdkId}ConnectorId`, {
value: conn.paymentConnectorId,
});
if (connector.provisionMode === 'QUICK_CREATE') {
new CfnOutput(this, `${connectorCdkId}ConnectorStatus`, {
value: conn.paymentConnectorStatus,
});
new CfnOutput(this, `${connectorCdkId}AuthorizationUrl`, {
value: conn.authorizationUrl,
});
}
}

// CFN Outputs for post-deploy state parsing
Expand Down
7 changes: 6 additions & 1 deletion src/assets/cdk/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
{
"name": "agentcore-cdk-app",
"version": "0.1.0",
"agentcoreProject": {
"capabilities": [
"payment-connector-quick-create"
]
},
"bin": {
"cdk": "dist/bin/cdk.js"
},
Expand All @@ -23,7 +28,7 @@
"typescript": "~5.9.3"
},
"dependencies": {
"@aws/agentcore-cdk": "0.1.0-alpha.45",
"@aws/agentcore-cdk": "0.1.0-alpha.49",
"aws-cdk-lib": "~2.266.0",
"constructs": "~10.7.0"
}
Expand Down
139 changes: 138 additions & 1 deletion src/assets/cdk/test/cdk.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
import * as cdk from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import { Match, Template } from 'aws-cdk-lib/assertions';
import { AgentCoreStack } from '../lib/cdk-stack';

const testConfigDir = join(process.cwd(), 'agentcore');

beforeAll(() => {
mkdirSync(testConfigDir, { recursive: true });
writeFileSync(join(testConfigDir, 'agentcore.json'), '{}');
});

afterAll(() => {
rmSync(testConfigDir, { recursive: true, force: true });
});

test('AgentCoreStack synthesizes with empty spec', () => {
const app = new cdk.App();
const stack = new AgentCoreStack(app, 'TestStack', {
Expand Down Expand Up @@ -29,3 +42,127 @@ test('AgentCoreStack synthesizes with empty spec', () => {
Description: 'Name of the CloudFormation Stack',
});
});

test('AgentCoreStack synthesizes manual and Quick Create payment connectors', () => {
const app = new cdk.App();
const stack = new AgentCoreStack(app, 'TestStack', {
spec: {
name: 'testproject',
version: 1,
managedBy: 'CDK' as const,
runtimes: [],
memories: [],
credentials: [],
evaluators: [],
onlineEvalConfigs: [],
configBundles: [],
policyEngines: [],
payments: [],
agentCoreGateways: [],
mcpRuntimeTools: [],
unassignedTargets: [],
datasets: [],
knowledgeBases: [],
},
paymentSpec: [
{
name: 'Payments',
authorizerType: 'AWS_IAM',
connectors: [
{
name: 'Manual',
provider: 'CoinbaseCDP',
credentialName: 'coinbase',
credentialProviderArn:
'arn:aws:bedrock-agentcore:us-east-1:123456789012:token-vault/default/paymentcredentialprovider/coinbase',
},
{
name: 'Quick',
provider: 'CoinbaseCDP',
provisionMode: 'QUICK_CREATE',
},
],
},
],
});
const template = Template.fromStack(stack);

template.resourceCountIs('AWS::BedrockAgentCore::PaymentConnector', 2);
template.hasResourceProperties('AWS::BedrockAgentCore::PaymentConnector', {
ConnectorName: 'Manual',
ProvisionMode: Match.absent(),
});
template.hasResourceProperties('AWS::BedrockAgentCore::PaymentConnector', {
ConnectorName: 'Quick',
ConnectorType: 'CoinbaseCDP',
ProvisionMode: 'QUICK_CREATE',
CredentialProviderConfigurations: [],
});
template.hasOutput('PaymentM8PaymentsC5QuickAuthorizationUrl', {});
});

test('AgentCoreStack preserves complete payment connector identities', () => {
const app = new cdk.App();
const stack = new AgentCoreStack(app, 'TestStack', {
spec: {
name: 'testproject',
version: 1,
managedBy: 'CDK' as const,
runtimes: [],
memories: [],
credentials: [],
evaluators: [],
onlineEvalConfigs: [],
configBundles: [],
policyEngines: [],
payments: [],
agentCoreGateways: [],
mcpRuntimeTools: [],
unassignedTargets: [],
datasets: [],
knowledgeBases: [],
},
paymentSpec: [
{
name: 'Payments',
authorizerType: 'AWS_IAM',
connectors: [
{
name: 'foo_bar',
provider: 'CoinbaseCDP',
provisionMode: 'QUICK_CREATE',
},
{
name: 'foobar',
provider: 'CoinbaseCDP',
provisionMode: 'QUICK_CREATE',
},
],
},
{
name: 'A',
authorizerType: 'AWS_IAM',
connectors: [
{
name: 'BC',
provider: 'CoinbaseCDP',
provisionMode: 'QUICK_CREATE',
},
],
},
{
name: 'AB',
authorizerType: 'AWS_IAM',
connectors: [
{
name: 'C',
provider: 'CoinbaseCDP',
provisionMode: 'QUICK_CREATE',
},
],
},
],
});

Template.fromStack(stack).resourceCountIs('AWS::BedrockAgentCore::PaymentConnector', 4);
});
Loading
Loading