Skip to content

Commit 352fb18

Browse files
feat(cdk): thread ABCA_STACK_NAME and ABCA_COMPONENT to every SDK surface
Component labels: 'api' (task-api commonEnv), 'webhook' (webhookEnv + slack/linear/github-screenshot integrations), 'orchestr' (orchestrator, reconcilers, pending-upload cleanup, fanout + approval-metrics stream consumers). Agent compute (AgentCore runtime env, ECS container env) gets ABCA_STACK_NAME only — agent/src/ua.py hardcodes its label. approval-metrics-publisher previously had no environment block; one is added. Template assertions verify each surface's label (#319 acceptance criterion). Task 5 of PR #338 plan. Part of #319 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 8773744 commit 352fb18

14 files changed

Lines changed: 97 additions & 5 deletions

cdk/src/constructs/approval-metrics-publisher-consumer.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919

2020
import * as path from 'path';
21-
import { Duration, RemovalPolicy } from 'aws-cdk-lib';
21+
import { Duration, RemovalPolicy, Stack } from 'aws-cdk-lib';
2222
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
2323
import { FilterCriteria, FilterRule, StartingPosition, Architecture, Runtime } from 'aws-cdk-lib/aws-lambda';
2424
import { DynamoEventSource, SqsDlq } from 'aws-cdk-lib/aws-lambda-event-sources';
@@ -123,6 +123,11 @@ export class ApprovalMetricsPublisherConsumer extends Construct {
123123
timeout: Duration.minutes(1),
124124
memorySize: 256,
125125
logGroup,
126+
// Outbound SDK User-Agent solution tracking (#319).
127+
environment: {
128+
ABCA_STACK_NAME: Stack.of(this).stackName,
129+
ABCA_COMPONENT: 'orchestr',
130+
},
126131
bundling: {
127132
externalModules: ['@aws-sdk/*'],
128133
},

cdk/src/constructs/concurrency-reconciler.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919

2020
import * as path from 'path';
21-
import { Duration } from 'aws-cdk-lib';
21+
import { Duration, Stack } from 'aws-cdk-lib';
2222
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
2323
import * as events from 'aws-cdk-lib/aws-events';
2424
import * as targets from 'aws-cdk-lib/aws-events-targets';
@@ -71,6 +71,8 @@ export class ConcurrencyReconciler extends Construct {
7171
environment: {
7272
TASK_TABLE_NAME: props.taskTable.tableName,
7373
USER_CONCURRENCY_TABLE_NAME: props.userConcurrencyTable.tableName,
74+
ABCA_STACK_NAME: Stack.of(this).stackName,
75+
ABCA_COMPONENT: 'orchestr',
7476
},
7577
bundling: {
7678
externalModules: ['@aws-sdk/*'],

cdk/src/constructs/ecs-agent-cluster.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ export class EcsAgentCluster extends Construct {
123123
}),
124124
environment: {
125125
CLAUDE_CODE_USE_BEDROCK: '1',
126+
// Outbound SDK User-Agent solution tracking (#319); component label
127+
// ('agent') is hardcoded in agent/src/ua.py.
128+
ABCA_STACK_NAME: Stack.of(this).stackName,
126129
TASK_TABLE_NAME: props.taskTable.tableName,
127130
TASK_EVENTS_TABLE_NAME: props.taskEventsTable.tableName,
128131
USER_CONCURRENCY_TABLE_NAME: props.userConcurrencyTable.tableName,

cdk/src/constructs/fanout-consumer.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919

2020
import * as path from 'path';
21-
import { Duration, RemovalPolicy } from 'aws-cdk-lib';
21+
import { Duration, RemovalPolicy, Stack } from 'aws-cdk-lib';
2222
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
2323
import * as iam from 'aws-cdk-lib/aws-iam';
2424
import { StartingPosition, Architecture, Runtime } from 'aws-cdk-lib/aws-lambda';
@@ -159,6 +159,10 @@ export class FanOutConsumer extends Construct {
159159
},
160160
});
161161

162+
// Outbound SDK User-Agent solution tracking (#319).
163+
this.fn.addEnvironment('ABCA_STACK_NAME', Stack.of(this).stackName);
164+
this.fn.addEnvironment('ABCA_COMPONENT', 'orchestr');
165+
162166
// GitHub dispatcher plumbing. Each grant/env var is guarded so the
163167
// fan-out plane still deploys cleanly in a dev environment that
164168
// hasn't onboarded the RepoTable or a platform GitHub token yet —

cdk/src/constructs/github-screenshot-integration.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ export class GitHubScreenshotIntegration extends Construct {
114114

115115
const removalPolicy = props.removalPolicy ?? RemovalPolicy.DESTROY;
116116

117+
// Outbound SDK User-Agent solution tracking (#319), spread into every
118+
// handler environment in this construct.
119+
const abcaEnv: Record<string, string> = {
120+
ABCA_STACK_NAME: Stack.of(this).stackName,
121+
ABCA_COMPONENT: 'webhook',
122+
};
123+
117124
// --- Screenshot bucket (private; served via CloudFront with OAC) ---
118125
this.screenshotBucket = new ScreenshotBucket(this, 'ScreenshotBucket', {
119126
removalPolicy,
@@ -157,6 +164,7 @@ export class GitHubScreenshotIntegration extends Construct {
157164
timeout: Duration.seconds(120),
158165
memorySize: 512,
159166
environment: {
167+
...abcaEnv,
160168
SCREENSHOT_BUCKET_NAME: this.screenshotBucket.bucket.bucketName,
161169
SCREENSHOT_PUBLIC_HOST: this.screenshotBucket.distribution.domainName,
162170
GITHUB_TOKEN_SECRET_ARN: props.githubTokenSecret.secretArn,
@@ -226,6 +234,7 @@ export class GitHubScreenshotIntegration extends Construct {
226234
architecture: Architecture.ARM_64,
227235
timeout: Duration.seconds(10),
228236
environment: {
237+
...abcaEnv,
229238
GITHUB_WEBHOOK_SECRET_ARN: this.webhookSecret.secretArn,
230239
GITHUB_WEBHOOK_DEDUP_TABLE_NAME: this.webhookDedupTable.tableName,
231240
GITHUB_WEBHOOK_PROCESSOR_FUNCTION_NAME: this.webhookProcessorFn.functionName,

cdk/src/constructs/linear-integration.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,13 @@ export class LinearIntegration extends Construct {
144144
};
145145

146146
// --- Task creation environment (matches TaskApi / SlackIntegration pattern) ---
147+
// Outbound SDK User-Agent solution tracking (#319), spread into every
148+
// handler environment in this construct.
149+
const abcaEnv: Record<string, string> = {
150+
ABCA_STACK_NAME: Stack.of(this).stackName,
151+
ABCA_COMPONENT: 'webhook',
152+
};
153+
147154
const createTaskEnv: Record<string, string> = {
148155
TASK_TABLE_NAME: props.taskTable.tableName,
149156
TASK_EVENTS_TABLE_NAME: props.taskEventsTable.tableName,
@@ -190,6 +197,7 @@ export class LinearIntegration extends Construct {
190197
// 30s deadline on cold starts.
191198
memorySize: 512,
192199
environment: {
200+
...abcaEnv,
193201
...createTaskEnv,
194202
LINEAR_PROJECT_MAPPING_TABLE_NAME: this.projectMappingTable.tableName,
195203
LINEAR_USER_MAPPING_TABLE_NAME: this.userMappingTable.tableName,
@@ -248,6 +256,7 @@ export class LinearIntegration extends Construct {
248256
architecture: Architecture.ARM_64,
249257
timeout: Duration.seconds(10),
250258
environment: {
259+
...abcaEnv,
251260
LINEAR_WEBHOOK_SECRET_ARN: this.webhookSecret.secretArn,
252261
LINEAR_WEBHOOK_DEDUP_TABLE_NAME: this.webhookDedupTable.tableName,
253262
LINEAR_WEBHOOK_PROCESSOR_FUNCTION_NAME: webhookProcessorFn.functionName,
@@ -287,6 +296,7 @@ export class LinearIntegration extends Construct {
287296
architecture: Architecture.ARM_64,
288297
timeout: Duration.seconds(10),
289298
environment: {
299+
...abcaEnv,
290300
LINEAR_USER_MAPPING_TABLE_NAME: this.userMappingTable.tableName,
291301
},
292302
bundling: commonBundling,

cdk/src/constructs/pending-upload-cleanup.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919

2020
import * as path from 'path';
21-
import { Duration } from 'aws-cdk-lib';
21+
import { Duration, Stack } from 'aws-cdk-lib';
2222
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
2323
import * as events from 'aws-cdk-lib/aws-events';
2424
import * as targets from 'aws-cdk-lib/aws-events-targets';
@@ -93,6 +93,8 @@ export class PendingUploadCleanup extends Construct {
9393
ATTACHMENTS_BUCKET_NAME: props.attachmentsBucket.bucketName,
9494
PENDING_UPLOAD_TIMEOUT_SECONDS: String(timeoutSeconds),
9595
TASK_RETENTION_DAYS: String(retentionDays),
96+
ABCA_STACK_NAME: Stack.of(this).stackName,
97+
ABCA_COMPONENT: 'orchestr',
9698
},
9799
bundling: {
98100
externalModules: ['@aws-sdk/*'],

cdk/src/constructs/slack-integration.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,13 @@ export class SlackIntegration extends Construct {
157157
authorizationType: apigw.AuthorizationType.NONE,
158158
};
159159

160+
// Outbound SDK User-Agent solution tracking (#319), spread into every
161+
// handler environment in this construct.
162+
const abcaEnv: Record<string, string> = {
163+
ABCA_STACK_NAME: Stack.of(this).stackName,
164+
ABCA_COMPONENT: 'webhook',
165+
};
166+
160167
// --- Task creation environment (matches TaskApi createTaskEnv pattern) ---
161168
const createTaskEnv: Record<string, string> = {
162169
TASK_TABLE_NAME: props.taskTable.tableName,
@@ -186,6 +193,7 @@ export class SlackIntegration extends Construct {
186193
architecture: Architecture.ARM_64,
187194
timeout: Duration.seconds(15),
188195
environment: {
196+
...abcaEnv,
189197
SLACK_INSTALLATION_TABLE_NAME: this.installationTable.tableName,
190198
SLACK_CLIENT_ID_SECRET_ARN: this.clientIdSecret.secretArn,
191199
SLACK_CLIENT_SECRET_ARN: this.clientSecret.secretArn,
@@ -218,6 +226,7 @@ export class SlackIntegration extends Construct {
218226
architecture: Architecture.ARM_64,
219227
timeout: Duration.seconds(10),
220228
environment: {
229+
...abcaEnv,
221230
SLACK_INSTALLATION_TABLE_NAME: this.installationTable.tableName,
222231
SLACK_SIGNING_SECRET_ARN: this.signingSecret.secretArn,
223232
},
@@ -250,6 +259,7 @@ export class SlackIntegration extends Construct {
250259
timeout: Duration.seconds(30),
251260
memorySize: 512,
252261
environment: {
262+
...abcaEnv,
253263
...createTaskEnv,
254264
SLACK_USER_MAPPING_TABLE_NAME: this.userMappingTable.tableName,
255265
SLACK_INSTALLATION_TABLE_NAME: this.installationTable.tableName,
@@ -295,6 +305,7 @@ export class SlackIntegration extends Construct {
295305
architecture: Architecture.ARM_64,
296306
timeout: Duration.seconds(10),
297307
environment: {
308+
...abcaEnv,
298309
SLACK_SIGNING_SECRET_ARN: this.signingSecret.secretArn,
299310
TASK_TABLE_NAME: props.taskTable.tableName,
300311
SLACK_USER_MAPPING_TABLE_NAME: this.userMappingTable.tableName,
@@ -314,6 +325,7 @@ export class SlackIntegration extends Construct {
314325
architecture: Architecture.ARM_64,
315326
timeout: Duration.seconds(3),
316327
environment: {
328+
...abcaEnv,
317329
SLACK_SIGNING_SECRET_ARN: this.signingSecret.secretArn,
318330
SLACK_COMMAND_PROCESSOR_FUNCTION_NAME: commandProcessorFn.functionName,
319331
},
@@ -333,6 +345,7 @@ export class SlackIntegration extends Construct {
333345
architecture: Architecture.ARM_64,
334346
timeout: Duration.seconds(10),
335347
environment: {
348+
...abcaEnv,
336349
SLACK_USER_MAPPING_TABLE_NAME: this.userMappingTable.tableName,
337350
},
338351
bundling: commonBundling,

cdk/src/constructs/stranded-task-reconciler.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919

2020
import * as path from 'path';
21-
import { Duration } from 'aws-cdk-lib';
21+
import { Duration, Stack } from 'aws-cdk-lib';
2222
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
2323
import * as events from 'aws-cdk-lib/aws-events';
2424
import * as targets from 'aws-cdk-lib/aws-events-targets';
@@ -111,6 +111,8 @@ export class StrandedTaskReconciler extends Construct {
111111
STRANDED_TIMEOUT_SECONDS: String(strandedTimeout),
112112
APPROVAL_STRANDED_TIMEOUT_SECONDS: String(approvalStrandedTimeout),
113113
TASK_RETENTION_DAYS: String(retentionDays),
114+
ABCA_STACK_NAME: Stack.of(this).stackName,
115+
ABCA_COMPONENT: 'orchestr',
114116
},
115117
bundling: {
116118
externalModules: ['@aws-sdk/*'],

cdk/src/constructs/task-api.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,9 @@ export class TaskApi extends Construct {
443443
TASK_TABLE_NAME: props.taskTable.tableName,
444444
TASK_EVENTS_TABLE_NAME: props.taskEventsTable.tableName,
445445
TASK_RETENTION_DAYS: String(props.taskRetentionDays ?? 90),
446+
// Outbound SDK User-Agent solution tracking (#319) — see handlers/shared/ua.ts
447+
ABCA_STACK_NAME: Stack.of(this).stackName,
448+
ABCA_COMPONENT: 'api',
446449
};
447450
// The Node.js Lambda runtime ships an AWS SDK, but its pinned version
448451
// lags current. `@aws-sdk/client-bedrock-agentcore` in particular has
@@ -931,6 +934,8 @@ export class TaskApi extends Construct {
931934
const webhookEnv: Record<string, string> = {
932935
WEBHOOK_TABLE_NAME: props.webhookTable.tableName,
933936
WEBHOOK_RETENTION_DAYS: String(props.webhookRetentionDays ?? 30),
937+
ABCA_STACK_NAME: Stack.of(this).stackName,
938+
ABCA_COMPONENT: 'webhook',
934939
};
935940

936941
// --- Webhook management Lambdas (Cognito-authenticated) ---

0 commit comments

Comments
 (0)