From 0eea53b2214e66a175747887ae663c09af99432b Mon Sep 17 00:00:00 2001 From: "Tukue G.Gebregergis" Date: Fri, 10 Apr 2026 13:03:12 +0200 Subject: [PATCH 1/5] Implement platform-product config and governance tagging defaults --- README.md | 15 + bin/app.ts | 13 +- lib/cdk-app-stack.ts | 14 +- lib/platform-config.ts | 55 +++ test/__snapshots__/cdk-app-stack.test.ts.snap | 436 +++++++++++++++--- test/cdk-app-stack.test.ts | 17 + 6 files changed, 467 insertions(+), 83 deletions(-) create mode 100644 lib/platform-config.ts diff --git a/README.md b/README.md index 224c209..105a6c0 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,21 @@ See detailed architecture and workflows in: - `templates/service-catalog/template.yaml` +## Implemented platform product guardrails + +The CDK app now applies two productized guardrails from the platform review recommendations: + +- **Typed environment configuration** via `lib/platform-config.ts` with explicit `dev|stage|prod` validation and fail-fast errors for invalid values. +- **Mandatory governance tags** standardized at stack level and validated in tests for key resources: `environment`, `project`, `owner`, `cost-center`, and `data-classification`. + +Set the environment with either CDK context or environment variable: + +```bash +npm run synth -- -c platformEnv=stage +# or +PLATFORM_ENV=prod npm run synth +``` + ## Code review resolution Review feedback and implemented fixes are tracked in: diff --git a/bin/app.ts b/bin/app.ts index 06b7f4f..f544181 100644 --- a/bin/app.ts +++ b/bin/app.ts @@ -2,15 +2,16 @@ import 'source-map-support/register'; import * as cdk from 'aws-cdk-lib'; import { CdkAppStack } from '../lib/cdk-app-stack'; - -// initialize the CDK app +import { loadPlatformConfig } from '../lib/platform-config'; const app = new cdk.App(); +const platformEnv = app.node.tryGetContext('platformEnv') ?? process.env.PLATFORM_ENV; +const platformConfig = loadPlatformConfig(platformEnv); -// deploy the clouformation stack to the default account and region new CdkAppStack(app, 'CdkAppStack', { - env: { - account: process.env.CDK_DEFAULT_ACCOUNT, - region: process.env.CDK_DEFAULT_REGION + env: { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION, }, + platformConfig, }); diff --git a/lib/cdk-app-stack.ts b/lib/cdk-app-stack.ts index 4bb9580..cda89b0 100644 --- a/lib/cdk-app-stack.ts +++ b/lib/cdk-app-stack.ts @@ -13,9 +13,14 @@ import * as logs from 'aws-cdk-lib/aws-logs'; import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch'; import * as cwActions from 'aws-cdk-lib/aws-cloudwatch-actions'; import * as sns from 'aws-cdk-lib/aws-sns'; +import { PlatformConfig } from './platform-config'; + +export interface CdkAppStackProps extends cdk.StackProps { + readonly platformConfig: PlatformConfig; +} export class CdkAppStack extends cdk.Stack { - constructor(scope: Construct, id: string, props?: cdk.StackProps) { + constructor(scope: Construct, id: string, props: CdkAppStackProps) { super(scope, id, props); const encryptionKey = new kms.Key(this, 'PlatformDataKey', { @@ -274,7 +279,10 @@ export class CdkAppStack extends cdk.Stack { }); // Optional: Add Tags to Resources - cdk.Tags.of(this).add('Environment', 'Development'); - cdk.Tags.of(this).add('Project', 'DemoAPI'); + cdk.Tags.of(this).add('environment', props.platformConfig.environment); + cdk.Tags.of(this).add('project', props.platformConfig.project); + cdk.Tags.of(this).add('owner', props.platformConfig.owner); + cdk.Tags.of(this).add('cost-center', props.platformConfig.costCenter); + cdk.Tags.of(this).add('data-classification', props.platformConfig.dataClassification); } } diff --git a/lib/platform-config.ts b/lib/platform-config.ts new file mode 100644 index 0000000..7245b9b --- /dev/null +++ b/lib/platform-config.ts @@ -0,0 +1,55 @@ +export type PlatformEnvironment = 'dev' | 'stage' | 'prod'; + +export interface PlatformConfig { + readonly environment: PlatformEnvironment; + readonly owner: string; + readonly costCenter: string; + readonly dataClassification: 'public' | 'internal' | 'confidential' | 'restricted'; + readonly project: string; +} + +const CONFIG_BY_ENV: Record> = { + dev: { + owner: 'platform-engineering', + costCenter: 'ENG-PLATFORM', + dataClassification: 'internal', + project: 'DemoAPI', + }, + stage: { + owner: 'platform-engineering', + costCenter: 'ENG-PLATFORM', + dataClassification: 'confidential', + project: 'DemoAPI', + }, + prod: { + owner: 'platform-engineering', + costCenter: 'ENG-PLATFORM', + dataClassification: 'confidential', + project: 'DemoAPI', + }, +}; + +export const resolvePlatformEnvironment = (value?: string): PlatformEnvironment => { + const normalized = value?.trim().toLowerCase(); + + if (!normalized) { + return 'dev'; + } + + if (normalized === 'dev' || normalized === 'stage' || normalized === 'prod') { + return normalized; + } + + throw new Error( + `Invalid platform environment \"${value}\". Allowed values: dev, stage, prod.`, + ); +}; + +export const loadPlatformConfig = (environmentValue?: string): PlatformConfig => { + const environment = resolvePlatformEnvironment(environmentValue); + + return { + environment, + ...CONFIG_BY_ENV[environment], + }; +}; diff --git a/test/__snapshots__/cdk-app-stack.test.ts.snap b/test/__snapshots__/cdk-app-stack.test.ts.snap index 3ae1e1f..c9b06ba 100644 --- a/test/__snapshots__/cdk-app-stack.test.ts.snap +++ b/test/__snapshots__/cdk-app-stack.test.ts.snap @@ -134,11 +134,23 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "RetentionInDays": 731, "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", }, { - "Key": "Project", + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", + }, + { + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -154,15 +166,27 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "InstanceTenancy": "default", "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", }, { "Key": "Name", "Value": "SnapshotStack/AppVpc", }, { - "Key": "Project", + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -173,15 +197,27 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "Properties": { "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", }, { "Key": "Name", "Value": "SnapshotStack/AppVpc", }, { - "Key": "Project", + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -215,15 +251,27 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "Properties": { "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", }, { "Key": "Name", "Value": "SnapshotStack/AppVpc/privateSubnet1", }, { - "Key": "Project", + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -259,15 +307,27 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "Value": "Private", }, { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", }, { "Key": "Name", "Value": "SnapshotStack/AppVpc/privateSubnet1", }, { - "Key": "Project", + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -304,15 +364,27 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "Properties": { "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", }, { "Key": "Name", "Value": "SnapshotStack/AppVpc/privateSubnet2", }, { - "Key": "Project", + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -337,15 +409,27 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "Value": "Private", }, { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", }, { "Key": "Name", "Value": "SnapshotStack/AppVpc/privateSubnet2", }, { - "Key": "Project", + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -375,15 +459,27 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "Domain": "vpc", "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", }, { "Key": "Name", "Value": "SnapshotStack/AppVpc/publicSubnet1", }, { - "Key": "Project", + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -407,15 +503,27 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` }, "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", }, { "Key": "Name", "Value": "SnapshotStack/AppVpc/publicSubnet1", }, { - "Key": "Project", + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -437,15 +545,27 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "Properties": { "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", }, { "Key": "Name", "Value": "SnapshotStack/AppVpc/publicSubnet1", }, { - "Key": "Project", + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -470,15 +590,27 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "Value": "Public", }, { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", }, { "Key": "Name", "Value": "SnapshotStack/AppVpc/publicSubnet1", }, { - "Key": "Project", + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -507,15 +639,27 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "Properties": { "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", }, { "Key": "Name", "Value": "SnapshotStack/AppVpc/publicSubnet2", }, { - "Key": "Project", + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -551,15 +695,27 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "Value": "Public", }, { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", }, { "Key": "Name", "Value": "SnapshotStack/AppVpc/publicSubnet2", }, { - "Key": "Project", + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -592,11 +748,23 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "RetentionInDays": 30, "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", + }, + { + "Key": "owner", + "Value": "platform-engineering", }, { - "Key": "Project", + "Key": "project", "Value": "DemoAPI", }, ], @@ -616,11 +784,23 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "MessageRetentionPeriod": 1209600, "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", + }, + { + "Key": "owner", + "Value": "platform-engineering", }, { - "Key": "Project", + "Key": "project", "Value": "DemoAPI", }, ], @@ -695,11 +875,23 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` }, "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", }, { - "Key": "Project", + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", + }, + { + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -737,11 +929,23 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` }, "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", + }, + { + "Key": "owner", + "Value": "platform-engineering", }, { - "Key": "Project", + "Key": "project", "Value": "DemoAPI", }, ], @@ -801,11 +1005,23 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "Name": "Demo API", "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", + }, + { + "Key": "owner", + "Value": "platform-engineering", }, { - "Key": "Project", + "Key": "project", "Value": "DemoAPI", }, ], @@ -859,11 +1075,23 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` ], "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", }, { - "Key": "Project", + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", + }, + { + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -871,7 +1099,7 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "Type": "AWS::IAM::Role", "UpdateReplacePolicy": "Retain", }, - "RestAPIDeploymentD35A5380dc5fde4fc47fdd1e8c0d8c911c4c286a": { + "RestAPIDeploymentD35A538022916227e2890c9cef2e63fbe89caa4d": { "DependsOn": [ "RestAPIGET232BCD01", "RestAPIitemsGET9E4F800F", @@ -906,7 +1134,7 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "CacheClusterEnabled": true, "CacheClusterSize": "0.5", "DeploymentId": { - "Ref": "RestAPIDeploymentD35A5380dc5fde4fc47fdd1e8c0d8c911c4c286a", + "Ref": "RestAPIDeploymentD35A538022916227e2890c9cef2e63fbe89caa4d", }, "MethodSettings": [ { @@ -923,11 +1151,23 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "StageName": "prod", "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", + }, + { + "Key": "owner", + "Value": "platform-engineering", }, { - "Key": "Project", + "Key": "project", "Value": "DemoAPI", }, ], @@ -1467,11 +1707,23 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "TableName": "DemoTable", "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", + }, + { + "Key": "owner", + "Value": "platform-engineering", }, { - "Key": "Project", + "Key": "project", "Value": "DemoAPI", }, ], @@ -1530,11 +1782,23 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` "Runtime": "nodejs18.x", "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", }, { - "Key": "Project", + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", + }, + { + "Key": "owner", + "Value": "platform-engineering", + }, + { + "Key": "project", "Value": "DemoAPI", }, ], @@ -1581,11 +1845,23 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` ], "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", + }, + { + "Key": "owner", + "Value": "platform-engineering", }, { - "Key": "Project", + "Key": "project", "Value": "DemoAPI", }, ], @@ -1727,11 +2003,23 @@ exports[`CdkAppStack matches synthesized snapshot 1`] = ` ], "Tags": [ { - "Key": "Environment", - "Value": "Development", + "Key": "cost-center", + "Value": "ENG-PLATFORM", + }, + { + "Key": "data-classification", + "Value": "internal", + }, + { + "Key": "environment", + "Value": "dev", + }, + { + "Key": "owner", + "Value": "platform-engineering", }, { - "Key": "Project", + "Key": "project", "Value": "DemoAPI", }, ], diff --git a/test/cdk-app-stack.test.ts b/test/cdk-app-stack.test.ts index 2d28aec..33940da 100644 --- a/test/cdk-app-stack.test.ts +++ b/test/cdk-app-stack.test.ts @@ -1,11 +1,13 @@ import * as cdk from 'aws-cdk-lib'; import { Template } from 'aws-cdk-lib/assertions'; import { CdkAppStack } from '../lib/cdk-app-stack'; +import { loadPlatformConfig } from '../lib/platform-config'; const buildTemplate = (stackName: string): Template => { const app = new cdk.App(); const stack = new CdkAppStack(app, stackName, { env: { account: '111111111111', region: 'us-east-1' }, + platformConfig: loadPlatformConfig('dev'), }); return Template.fromStack(stack); @@ -21,6 +23,21 @@ describe('CdkAppStack', () => { template.resourceCountIs('AWS::KMS::Key', 1); }); + + test('applies required governance tags', () => { + const template = buildTemplate('TaggedStack'); + + template.hasResourceProperties('AWS::DynamoDB::Table', { + Tags: [ + { Key: 'cost-center', Value: 'ENG-PLATFORM' }, + { Key: 'data-classification', Value: 'internal' }, + { Key: 'environment', Value: 'dev' }, + { Key: 'owner', Value: 'platform-engineering' }, + { Key: 'project', Value: 'DemoAPI' }, + ], + }); + }); + test('matches synthesized snapshot', () => { const template = buildTemplate('SnapshotStack'); const templateJson = template.toJSON() as { From 5f1c4dc48eb05eb6227ccdb0cead959f093c6544 Mon Sep 17 00:00:00 2001 From: "Tukue G.Gebregergis" Date: Mon, 13 Apr 2026 10:44:18 +0200 Subject: [PATCH 2/5] Fail fast when platform environment is not explicitly set --- README.md | 2 +- lib/platform-config.ts | 4 +++- test/cdk-app-stack.test.ts | 7 +++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 105a6c0..bc0ee96 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ See detailed architecture and workflows in: The CDK app now applies two productized guardrails from the platform review recommendations: -- **Typed environment configuration** via `lib/platform-config.ts` with explicit `dev|stage|prod` validation and fail-fast errors for invalid values. +- **Typed environment configuration** via `lib/platform-config.ts` with explicit `dev|stage|prod` validation and fail-fast errors for missing or invalid values. - **Mandatory governance tags** standardized at stack level and validated in tests for key resources: `environment`, `project`, `owner`, `cost-center`, and `data-classification`. Set the environment with either CDK context or environment variable: diff --git a/lib/platform-config.ts b/lib/platform-config.ts index 7245b9b..5f75282 100644 --- a/lib/platform-config.ts +++ b/lib/platform-config.ts @@ -33,7 +33,9 @@ export const resolvePlatformEnvironment = (value?: string): PlatformEnvironment const normalized = value?.trim().toLowerCase(); if (!normalized) { - return 'dev'; + throw new Error( + 'Platform environment must be explicitly specified via platformEnv context or PLATFORM_ENV. Allowed values: dev, stage, prod.', + ); } if (normalized === 'dev' || normalized === 'stage' || normalized === 'prod') { diff --git a/test/cdk-app-stack.test.ts b/test/cdk-app-stack.test.ts index 33940da..b452054 100644 --- a/test/cdk-app-stack.test.ts +++ b/test/cdk-app-stack.test.ts @@ -14,6 +14,13 @@ const buildTemplate = (stackName: string): Template => { }; describe('CdkAppStack', () => { + + test('fails fast when environment is not specified', () => { + expect(() => loadPlatformConfig()).toThrow( + 'Platform environment must be explicitly specified via platformEnv context or PLATFORM_ENV. Allowed values: dev, stage, prod.', + ); + }); + test('creates core resources', () => { const template = buildTemplate('TestStack'); From ddcc9a8eca2484e6c6cc285eaa2137ce11db594b Mon Sep 17 00:00:00 2001 From: "Tukue G.Gebregergis" Date: Mon, 13 Apr 2026 10:49:00 +0200 Subject: [PATCH 3/5] Set explicit default platformEnv context for synth --- README.md | 2 ++ cdk.json | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bc0ee96..7e0ec7d 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,8 @@ The CDK app now applies two productized guardrails from the platform review reco Set the environment with either CDK context or environment variable: +Default local context in `cdk.json` is set to `dev` so `npm run synth` works out of the box; override it for stage/prod. + ```bash npm run synth -- -c platformEnv=stage # or diff --git a/cdk.json b/cdk.json index 187cb1b..8d68950 100644 --- a/cdk.json +++ b/cdk.json @@ -48,6 +48,7 @@ "@aws-cdk/aws-redshift:columnId": true, "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true, "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true, - "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true, + "platformEnv": "dev" } } From 7c926c9f5cba2ba7713b60d2861902ef8f3fe687 Mon Sep 17 00:00:00 2001 From: "Tukue G.Gebregergis" Date: Mon, 13 Apr 2026 10:58:42 +0200 Subject: [PATCH 4/5] Require explicit platformEnv by removing implicit default --- README.md | 4 +--- cdk.json | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7e0ec7d..be730e3 100644 --- a/README.md +++ b/README.md @@ -79,9 +79,7 @@ The CDK app now applies two productized guardrails from the platform review reco - **Typed environment configuration** via `lib/platform-config.ts` with explicit `dev|stage|prod` validation and fail-fast errors for missing or invalid values. - **Mandatory governance tags** standardized at stack level and validated in tests for key resources: `environment`, `project`, `owner`, `cost-center`, and `data-classification`. -Set the environment with either CDK context or environment variable: - -Default local context in `cdk.json` is set to `dev` so `npm run synth` works out of the box; override it for stage/prod. +Set the environment explicitly with either CDK context or environment variable: ```bash npm run synth -- -c platformEnv=stage diff --git a/cdk.json b/cdk.json index 8d68950..187cb1b 100644 --- a/cdk.json +++ b/cdk.json @@ -48,7 +48,6 @@ "@aws-cdk/aws-redshift:columnId": true, "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true, "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true, - "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true, - "platformEnv": "dev" + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true } } From 18c681fcbf7c22c106a67c3175aca80f58e520eb Mon Sep 17 00:00:00 2001 From: "Tukue G.Gebregergis" Date: Mon, 13 Apr 2026 11:04:02 +0200 Subject: [PATCH 5/5] Make npm synth provide explicit default platformEnv --- README.md | 7 ++++--- package.json | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index be730e3..2117739 100644 --- a/README.md +++ b/README.md @@ -82,9 +82,10 @@ The CDK app now applies two productized guardrails from the platform review reco Set the environment explicitly with either CDK context or environment variable: ```bash -npm run synth -- -c platformEnv=stage -# or -PLATFORM_ENV=prod npm run synth +npm run synth # defaults to dev when PLATFORM_ENV is unset +PLATFORM_ENV=stage npm run synth +# or, direct CDK command +npm run cdk -- synth -c platformEnv=prod ``` ## Code review resolution diff --git a/package.json b/package.json index 22be7c2..3d606c7 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "cdk": "cdk", "deploy": "cdk deploy", "destroy": "cdk destroy", - "synth": "cdk synth" + "synth": "bash -lc \"cdk synth -c platformEnv=${PLATFORM_ENV:-dev}\"" }, "devDependencies": { "@types/aws-lambda": "^8.10.122",