cdk-cost-analyzer 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/.cdk-cost-analyzer-cache/metadata.json +12 -0
  2. package/.gitlab-ci.yml +214 -0
  3. package/.husky/pre-commit +12 -0
  4. package/.kiro/hooks/accessibility-audit.kiro.hook +18 -0
  5. package/.kiro/hooks/api-schema-validation.kiro.hook +21 -0
  6. package/.kiro/hooks/auto-test-on-save.kiro.hook +19 -0
  7. package/.kiro/hooks/cdk-synth-on-change.kiro.hook +20 -0
  8. package/.kiro/hooks/code-coverage-check.kiro.hook +14 -0
  9. package/.kiro/hooks/commit-message-helper.kiro.hook +14 -0
  10. package/.kiro/hooks/dependency-update-check.kiro.hook +14 -0
  11. package/.kiro/hooks/env-file-validation.kiro.hook +18 -0
  12. package/.kiro/hooks/lint-and-format-on-save.kiro.hook +21 -0
  13. package/.kiro/hooks/mcp-config-validation.kiro.hook +17 -0
  14. package/.kiro/hooks/mcp-server-test.kiro.hook +14 -0
  15. package/.kiro/hooks/performance-analysis.kiro.hook +14 -0
  16. package/.kiro/hooks/readme-spell-check.kiro.hook +14 -0
  17. package/.kiro/hooks/security-scan-on-dependency-change.kiro.hook +21 -0
  18. package/.kiro/hooks/translation-update.kiro.hook +18 -0
  19. package/.kiro/hooks/update-documentation.kiro.hook +18 -0
  20. package/.kiro/settings/mcp.json +20 -0
  21. package/.kiro/specs/cdk-cost-analyzer/design.md +620 -0
  22. package/.kiro/specs/cdk-cost-analyzer/requirements.md +183 -0
  23. package/.kiro/specs/cdk-cost-analyzer/tasks.md +357 -0
  24. package/.kiro/specs/github-actions-ci/design.md +281 -0
  25. package/.kiro/specs/github-actions-ci/requirements.md +86 -0
  26. package/.kiro/specs/github-actions-ci/tasks.md +115 -0
  27. package/.kiro/specs/nlb-calculator-test-coverage/design.md +190 -0
  28. package/.kiro/specs/nlb-calculator-test-coverage/requirements.md +84 -0
  29. package/.kiro/specs/nlb-calculator-test-coverage/tasks.md +150 -0
  30. package/.kiro/specs/production-readiness/design.md +1213 -0
  31. package/.kiro/specs/production-readiness/requirements.md +312 -0
  32. package/.kiro/specs/production-readiness/tasks.md +269 -0
  33. package/.kiro/specs/repository-cleanup/design.md +283 -0
  34. package/.kiro/specs/repository-cleanup/requirements.md +74 -0
  35. package/.kiro/specs/repository-cleanup/tasks.md +64 -0
  36. package/.kiro/steering/aws-cli-best-practices.md +41 -0
  37. package/.kiro/steering/cdk-best-practices.md +49 -0
  38. package/.kiro/steering/development-standards.md +54 -0
  39. package/.kiro/steering/docker-best-practices.md +34 -0
  40. package/.kiro/steering/documentation-style.md +151 -0
  41. package/.kiro/steering/git-best-practices.md +37 -0
  42. package/.kiro/steering/mcp-best-practices.md +95 -0
  43. package/.kiro/steering/python-best-practices.md +48 -0
  44. package/.kiro/steering/react-best-practices.md +44 -0
  45. package/.kiro/steering/security-best-practices.md +41 -0
  46. package/.kiro/steering/testing-best-practices.md +59 -0
  47. package/.kiro/steering/typescript-best-practices.md +40 -0
  48. package/CHANGELOG.md +49 -0
  49. package/CONTRIBUTING.md +258 -0
  50. package/LICENSE +19 -0
  51. package/README.md +480 -0
  52. package/SECURITY.md +117 -0
  53. package/dist/api/index.d.ts +11 -0
  54. package/dist/api/index.js +65 -0
  55. package/dist/api/types.d.ts +15 -0
  56. package/dist/api/types.js +3 -0
  57. package/dist/cli/index.d.ts +2 -0
  58. package/dist/cli/index.js +262 -0
  59. package/dist/config/ConfigManager.d.ts +40 -0
  60. package/dist/config/ConfigManager.js +238 -0
  61. package/dist/config/index.d.ts +2 -0
  62. package/dist/config/index.js +19 -0
  63. package/dist/config/types.d.ts +72 -0
  64. package/dist/config/types.js +15 -0
  65. package/dist/diff/DiffEngine.d.ts +7 -0
  66. package/dist/diff/DiffEngine.js +73 -0
  67. package/dist/diff/index.d.ts +2 -0
  68. package/dist/diff/index.js +21 -0
  69. package/dist/diff/types.d.ts +20 -0
  70. package/dist/diff/types.js +3 -0
  71. package/dist/integrations/GitLabIntegration.d.ts +7 -0
  72. package/dist/integrations/GitLabIntegration.js +45 -0
  73. package/dist/integrations/index.d.ts +2 -0
  74. package/dist/integrations/index.js +21 -0
  75. package/dist/integrations/types.d.ts +11 -0
  76. package/dist/integrations/types.js +13 -0
  77. package/dist/parser/TemplateParser.d.ts +8 -0
  78. package/dist/parser/TemplateParser.js +75 -0
  79. package/dist/parser/index.d.ts +2 -0
  80. package/dist/parser/index.js +22 -0
  81. package/dist/parser/types.d.ts +30 -0
  82. package/dist/parser/types.js +3 -0
  83. package/dist/pipeline/PipelineOrchestrator.d.ts +23 -0
  84. package/dist/pipeline/PipelineOrchestrator.js +191 -0
  85. package/dist/pipeline/index.d.ts +2 -0
  86. package/dist/pipeline/index.js +19 -0
  87. package/dist/pipeline/types.d.ts +41 -0
  88. package/dist/pipeline/types.js +13 -0
  89. package/dist/pricing/CacheManager.d.ts +75 -0
  90. package/dist/pricing/CacheManager.js +195 -0
  91. package/dist/pricing/PricingClient.d.ts +17 -0
  92. package/dist/pricing/PricingClient.js +122 -0
  93. package/dist/pricing/PricingService.d.ts +16 -0
  94. package/dist/pricing/PricingService.js +149 -0
  95. package/dist/pricing/calculators/ALBCalculator.d.ts +16 -0
  96. package/dist/pricing/calculators/ALBCalculator.js +163 -0
  97. package/dist/pricing/calculators/APIGatewayCalculator.d.ts +10 -0
  98. package/dist/pricing/calculators/APIGatewayCalculator.js +177 -0
  99. package/dist/pricing/calculators/CloudFrontCalculator.d.ts +59 -0
  100. package/dist/pricing/calculators/CloudFrontCalculator.js +151 -0
  101. package/dist/pricing/calculators/DynamoDBCalculator.d.ts +9 -0
  102. package/dist/pricing/calculators/DynamoDBCalculator.js +146 -0
  103. package/dist/pricing/calculators/EC2Calculator.d.ts +7 -0
  104. package/dist/pricing/calculators/EC2Calculator.js +80 -0
  105. package/dist/pricing/calculators/ECSCalculator.d.ts +9 -0
  106. package/dist/pricing/calculators/ECSCalculator.js +116 -0
  107. package/dist/pricing/calculators/ElastiCacheCalculator.d.ts +8 -0
  108. package/dist/pricing/calculators/ElastiCacheCalculator.js +106 -0
  109. package/dist/pricing/calculators/LambdaCalculator.d.ts +13 -0
  110. package/dist/pricing/calculators/LambdaCalculator.js +111 -0
  111. package/dist/pricing/calculators/NLBCalculator.d.ts +16 -0
  112. package/dist/pricing/calculators/NLBCalculator.js +138 -0
  113. package/dist/pricing/calculators/NatGatewayCalculator.d.ts +12 -0
  114. package/dist/pricing/calculators/NatGatewayCalculator.js +116 -0
  115. package/dist/pricing/calculators/RDSCalculator.d.ts +9 -0
  116. package/dist/pricing/calculators/RDSCalculator.js +103 -0
  117. package/dist/pricing/calculators/S3Calculator.d.ts +8 -0
  118. package/dist/pricing/calculators/S3Calculator.js +68 -0
  119. package/dist/pricing/calculators/VPCEndpointCalculator.d.ts +12 -0
  120. package/dist/pricing/calculators/VPCEndpointCalculator.js +129 -0
  121. package/dist/pricing/index.d.ts +10 -0
  122. package/dist/pricing/index.js +37 -0
  123. package/dist/pricing/types.d.ts +53 -0
  124. package/dist/pricing/types.js +22 -0
  125. package/dist/releasetag.txt +1 -0
  126. package/dist/reporter/Reporter.d.ts +18 -0
  127. package/dist/reporter/Reporter.js +412 -0
  128. package/dist/reporter/index.d.ts +2 -0
  129. package/dist/reporter/index.js +21 -0
  130. package/dist/reporter/types.d.ts +72 -0
  131. package/dist/reporter/types.js +3 -0
  132. package/dist/synthesis/SynthesisOrchestrator.d.ts +26 -0
  133. package/dist/synthesis/SynthesisOrchestrator.js +243 -0
  134. package/dist/synthesis/index.d.ts +2 -0
  135. package/dist/synthesis/index.js +19 -0
  136. package/dist/synthesis/types.d.ts +17 -0
  137. package/dist/synthesis/types.js +13 -0
  138. package/dist/threshold/ThresholdEnforcer.d.ts +29 -0
  139. package/dist/threshold/ThresholdEnforcer.js +143 -0
  140. package/dist/threshold/index.d.ts +2 -0
  141. package/dist/threshold/index.js +19 -0
  142. package/dist/threshold/types.d.ts +15 -0
  143. package/dist/threshold/types.js +17 -0
  144. package/docs/CALCULATORS.md +820 -0
  145. package/docs/CI_CD.md +608 -0
  146. package/docs/CONFIGURATION.md +407 -0
  147. package/docs/DEVELOPMENT.md +387 -0
  148. package/docs/RELEASE.md +223 -0
  149. package/docs/TROUBLESHOOTING.md +847 -0
  150. package/examples/.cdk-cost-analyzer.yml +85 -0
  151. package/examples/.gitlab-ci.yml +125 -0
  152. package/examples/api-usage.js +26 -0
  153. package/examples/complex/base.json +16 -0
  154. package/examples/complex/target.json +29 -0
  155. package/examples/monorepo/.gitlab-ci.yml +251 -0
  156. package/examples/monorepo/README.md +341 -0
  157. package/examples/monorepo/package.json +27 -0
  158. package/examples/monorepo/packages/backend-infra/.cdk-cost-analyzer.yml +34 -0
  159. package/examples/monorepo/packages/backend-infra/bin/app.ts +16 -0
  160. package/examples/monorepo/packages/backend-infra/cdk.json +7 -0
  161. package/examples/monorepo/packages/backend-infra/lib/backend-stack.ts +128 -0
  162. package/examples/monorepo/packages/backend-infra/package.json +30 -0
  163. package/examples/monorepo/packages/backend-infra/tsconfig.json +11 -0
  164. package/examples/monorepo/packages/data-infra/.cdk-cost-analyzer.yml +38 -0
  165. package/examples/monorepo/packages/data-infra/bin/app.ts +16 -0
  166. package/examples/monorepo/packages/data-infra/cdk.json +7 -0
  167. package/examples/monorepo/packages/data-infra/lib/data-stack.ts +121 -0
  168. package/examples/monorepo/packages/data-infra/package.json +30 -0
  169. package/examples/monorepo/packages/data-infra/tsconfig.json +11 -0
  170. package/examples/monorepo/packages/frontend-infra/.cdk-cost-analyzer.yml +31 -0
  171. package/examples/monorepo/packages/frontend-infra/bin/app.ts +16 -0
  172. package/examples/monorepo/packages/frontend-infra/cdk.json +7 -0
  173. package/examples/monorepo/packages/frontend-infra/lib/frontend-stack.ts +60 -0
  174. package/examples/monorepo/packages/frontend-infra/package.json +30 -0
  175. package/examples/monorepo/packages/frontend-infra/tsconfig.json +11 -0
  176. package/examples/monorepo/tsconfig.json +35 -0
  177. package/examples/multi-stack/.cdk-cost-analyzer.yml +72 -0
  178. package/examples/multi-stack/.gitlab-ci.yml +184 -0
  179. package/examples/multi-stack/README.md +279 -0
  180. package/examples/multi-stack/bin/app.ts +36 -0
  181. package/examples/multi-stack/cdk.json +72 -0
  182. package/examples/multi-stack/lib/compute-stack.ts +128 -0
  183. package/examples/multi-stack/lib/networking-stack.ts +69 -0
  184. package/examples/multi-stack/lib/storage-stack.ts +141 -0
  185. package/examples/multi-stack/package-lock.json +4437 -0
  186. package/examples/multi-stack/package.json +42 -0
  187. package/examples/multi-stack/tsconfig.json +34 -0
  188. package/examples/simple/base.json +8 -0
  189. package/examples/simple/target.json +14 -0
  190. package/examples/single-stack/.NVP +0 -0
  191. package/examples/single-stack/.cdk-cost-analyzer.yml +52 -0
  192. package/examples/single-stack/.gitlab-ci.yml +126 -0
  193. package/examples/single-stack/README.md +184 -0
  194. package/examples/single-stack/UeK +0 -0
  195. package/examples/single-stack/bin/app.ts +16 -0
  196. package/examples/single-stack/cdk.json +72 -0
  197. package/examples/single-stack/lib/infrastructure-stack.ts +119 -0
  198. package/examples/single-stack/package-lock.json +4443 -0
  199. package/examples/single-stack/package.json +38 -0
  200. package/examples/single-stack/tsconfig.json +34 -0
  201. package/package.json +139 -0
  202. package/test-cdk-project/README-COMPUTE.md +141 -0
  203. package/test-cdk-project/README.md +95 -0
  204. package/test-cdk-project/app-with-compute.js +102 -0
  205. package/test-cdk-project/app.js +81 -0
  206. package/test-cdk-project/cdk-compute.json +3 -0
  207. package/test-cdk-project/cdk.context.json +7 -0
  208. package/test-cdk-project/cdk.json +3 -0
  209. package/test-cdk-project/cdk.out/TestStack.assets.json +21 -0
  210. package/test-cdk-project/cdk.out/TestStack.template.json +115 -0
  211. package/test-cdk-project/cdk.out/cdk.out +1 -0
  212. package/test-cdk-project/cdk.out/manifest.json +503 -0
  213. package/test-cdk-project/cdk.out/tree.json +1 -0
  214. package/test-cdk-project/cdk.out.base/TestStack.assets.json +21 -0
  215. package/test-cdk-project/cdk.out.base/TestStack.template.json +115 -0
  216. package/test-cdk-project/cdk.out.base/cdk.out +1 -0
  217. package/test-cdk-project/cdk.out.base/manifest.json +503 -0
  218. package/test-cdk-project/cdk.out.base/tree.json +1 -0
  219. package/test-cdk-project/cdk.out.target/TestStack.assets.json +21 -0
  220. package/test-cdk-project/cdk.out.target/TestStack.template.json +183 -0
  221. package/test-cdk-project/cdk.out.target/cdk.out +1 -0
  222. package/test-cdk-project/cdk.out.target/manifest.json +521 -0
  223. package/test-cdk-project/cdk.out.target/tree.json +1 -0
  224. package/test-cdk-project/package-lock.json +422 -0
  225. package/test-cdk-project/package.json +17 -0
  226. package/tools/workflows/README.md +102 -0
  227. package/tools/workflows/validate-workflows.js +109 -0
  228. package/tools/workflows/workflow-utils.ts +181 -0
@@ -0,0 +1,620 @@
1
+ # Design Document
2
+
3
+ ## Overview
4
+
5
+ The CDK Cost Analyzer is a TypeScript package that compares CloudFormation templates and calculates AWS resource cost differences. The system parses template JSON/YAML, identifies resource changes, queries AWS Pricing API for current costs, and generates formatted cost reports.
6
+
7
+ The Phase 1 MVP architecture focuses on simplicity and core functionality, with a modular design that allows Phase 2 enhancements to be added incrementally.
8
+
9
+ ## Architecture
10
+
11
+ ### High-Level Architecture
12
+
13
+ ```
14
+ ┌─────────────────┐
15
+ │ CLI / API │ Entry points
16
+ └────────┬────────┘
17
+
18
+ ┌────────▼────────┐
19
+ │ Cost Analyzer │ Main orchestration
20
+ └────────┬────────┘
21
+
22
+ ┌────┴────┬──────────┬──────────┐
23
+ │ │ │ │
24
+ ┌───▼───┐ ┌──▼──┐ ┌────▼────┐ ┌──▼──────┐
25
+ │Parser │ │Diff │ │Pricing │ │Reporter │
26
+ │ │ │ │ │Service │ │ │
27
+ └───────┘ └─────┘ └─────────┘ └─────────┘
28
+
29
+ ┌────▼────┐
30
+ │AWS API │
31
+ └─────────┘
32
+ ```
33
+
34
+ ### Component Responsibilities
35
+
36
+ 1. **CLI**: Command-line interface for terminal usage
37
+ 2. **API**: Programmatic interface for code integration
38
+ 3. **Cost Analyzer**: Orchestrates the analysis workflow
39
+ 4. **Parser**: Parses CloudFormation templates (JSON/YAML)
40
+ 5. **Diff Engine**: Identifies added, removed, and modified resources
41
+ 6. **Pricing Service**: Fetches AWS pricing data and calculates costs
42
+ 7. **Reporter**: Formats and outputs cost reports
43
+
44
+ ## Components and Interfaces
45
+
46
+ ### 1. Template Parser
47
+
48
+ **Purpose**: Parse CloudFormation templates from JSON or YAML format
49
+
50
+ **Interface**:
51
+ ```typescript
52
+ interface TemplateParser {
53
+ parse(content: string): CloudFormationTemplate;
54
+ }
55
+
56
+ interface CloudFormationTemplate {
57
+ Resources: Record<string, Resource>;
58
+ Metadata?: Record<string, unknown>;
59
+ }
60
+
61
+ interface Resource {
62
+ Type: string;
63
+ Properties: Record<string, unknown>;
64
+ }
65
+ ```
66
+
67
+ **Implementation Notes**:
68
+ - Support both JSON and YAML formats
69
+ - Use existing libraries (js-yaml for YAML parsing)
70
+ - Validate template structure
71
+ - Extract resource definitions
72
+
73
+ ### 2. Diff Engine
74
+
75
+ **Purpose**: Compare two templates and identify resource changes
76
+
77
+ **Interface**:
78
+ ```typescript
79
+ interface DiffEngine {
80
+ diff(base: CloudFormationTemplate, target: CloudFormationTemplate): ResourceDiff;
81
+ }
82
+
83
+ interface ResourceDiff {
84
+ added: Resource[];
85
+ removed: Resource[];
86
+ modified: ModifiedResource[];
87
+ }
88
+
89
+ interface ModifiedResource {
90
+ logicalId: string;
91
+ type: string;
92
+ oldProperties: Record<string, unknown>;
93
+ newProperties: Record<string, unknown>;
94
+ }
95
+ ```
96
+
97
+ **Implementation Notes**:
98
+ - Compare resources by logical ID
99
+ - Identify added resources (in target, not in base)
100
+ - Identify removed resources (in base, not in target)
101
+ - Identify modified resources (in both, but properties differ)
102
+ - Deep comparison of resource properties
103
+
104
+ ### 3. Pricing Service
105
+
106
+ **Purpose**: Fetch AWS pricing data and calculate resource costs
107
+
108
+ **Interface**:
109
+ ```typescript
110
+ interface PricingService {
111
+ getResourceCost(resource: Resource, region: string): Promise<MonthlyCost>;
112
+ getCostDelta(diff: ResourceDiff, region: string): Promise<CostDelta>;
113
+ }
114
+
115
+ interface MonthlyCost {
116
+ amount: number;
117
+ currency: string;
118
+ confidence: 'high' | 'medium' | 'low' | 'unknown';
119
+ assumptions: string[];
120
+ }
121
+
122
+ interface CostDelta {
123
+ totalDelta: number;
124
+ addedCosts: ResourceCost[];
125
+ removedCosts: ResourceCost[];
126
+ modifiedCosts: ModifiedResourceCost[];
127
+ }
128
+
129
+ interface ResourceCost {
130
+ logicalId: string;
131
+ type: string;
132
+ monthlyCost: MonthlyCost;
133
+ }
134
+
135
+ interface ModifiedResourceCost extends ResourceCost {
136
+ oldMonthlyCost: MonthlyCost;
137
+ newMonthlyCost: MonthlyCost;
138
+ costDelta: number;
139
+ }
140
+ ```
141
+
142
+ **Implementation Notes**:
143
+ - Use AWS SDK Pricing API client
144
+ - Implement resource-specific cost calculators for EC2, S3, Lambda, RDS
145
+ - Cache pricing data to reduce API calls
146
+ - Handle pricing API failures with retries
147
+ - Return confidence levels based on data availability
148
+ - Document assumptions for usage-based pricing
149
+
150
+ ### 4. Resource Cost Calculators
151
+
152
+ **Purpose**: Calculate costs for specific AWS resource types
153
+
154
+ **Interface**:
155
+ ```typescript
156
+ interface ResourceCostCalculator {
157
+ supports(resourceType: string): boolean;
158
+ calculateCost(resource: Resource, region: string, pricingData: PricingData): MonthlyCost;
159
+ }
160
+ ```
161
+
162
+ **Implementations**:
163
+ - **EC2Calculator**: Calculate costs based on instance type, region
164
+ - **S3Calculator**: Estimate storage costs with default assumptions (e.g., 100GB)
165
+ - **LambdaCalculator**: Estimate based on memory and default invocations (e.g., 1M/month)
166
+ - **RDSCalculator**: Calculate based on instance class, engine, storage
167
+
168
+ ### 5. Reporter
169
+
170
+ **Purpose**: Format cost analysis results for output
171
+
172
+ **Interface**:
173
+ ```typescript
174
+ interface Reporter {
175
+ generateReport(costDelta: CostDelta, format: ReportFormat): string;
176
+ }
177
+
178
+ type ReportFormat = 'text' | 'json' | 'markdown';
179
+ ```
180
+
181
+ **Implementation Notes**:
182
+ - Text format: Human-readable console output
183
+ - JSON format: Structured data for programmatic use
184
+ - Markdown format: For documentation and MR comments (Phase 2)
185
+ - Include summary section with total delta
186
+ - Group resources by category (added/removed/modified)
187
+ - Sort by cost impact (highest first)
188
+ - Format currency with proper symbols and decimals
189
+
190
+ ### 6. CLI Interface
191
+
192
+ **Purpose**: Provide command-line access to cost analysis
193
+
194
+ **Interface**:
195
+ ```bash
196
+ cdk-cost-analyzer <base-template> <target-template> [options]
197
+
198
+ Options:
199
+ --region <region> AWS region (default: eu-central-1)
200
+ --format <format> Output format: text|json|markdown (default: text)
201
+ --help Show help
202
+ --version Show version
203
+ ```
204
+
205
+ **Implementation Notes**:
206
+ - Use commander or yargs for CLI parsing
207
+ - Read template files from filesystem
208
+ - Output to stdout
209
+ - Exit with code 0 on success, non-zero on error
210
+ - Display errors to stderr
211
+
212
+ ### 7. Programmatic API
213
+
214
+ **Purpose**: Provide TypeScript/JavaScript API for integration
215
+
216
+ **Interface**:
217
+ ```typescript
218
+ export async function analyzeCosts(options: AnalyzeOptions): Promise<CostAnalysisResult>;
219
+
220
+ interface AnalyzeOptions {
221
+ baseTemplate: string; // Template content or file path
222
+ targetTemplate: string; // Template content or file path
223
+ region?: string; // Default: 'eu-central-1'
224
+ }
225
+
226
+ interface CostAnalysisResult {
227
+ totalDelta: number;
228
+ currency: string;
229
+ addedResources: ResourceCost[];
230
+ removedResources: ResourceCost[];
231
+ modifiedResources: ModifiedResourceCost[];
232
+ summary: string;
233
+ }
234
+ ```
235
+
236
+ ## Data Models
237
+
238
+ ### CloudFormation Template Structure
239
+
240
+ ```typescript
241
+ interface CloudFormationTemplate {
242
+ AWSTemplateFormatVersion?: string;
243
+ Description?: string;
244
+ Metadata?: Record<string, unknown>;
245
+ Parameters?: Record<string, Parameter>;
246
+ Resources: Record<string, Resource>;
247
+ Outputs?: Record<string, Output>;
248
+ }
249
+
250
+ interface Resource {
251
+ Type: string; // e.g., "AWS::EC2::Instance"
252
+ Properties: Record<string, unknown>;
253
+ DependsOn?: string | string[];
254
+ Metadata?: Record<string, unknown>;
255
+ }
256
+ ```
257
+
258
+ ### Pricing Data Structure
259
+
260
+ ```typescript
261
+ interface PricingData {
262
+ serviceCode: string;
263
+ region: string;
264
+ products: PricingProduct[];
265
+ }
266
+
267
+ interface PricingProduct {
268
+ sku: string;
269
+ productFamily: string;
270
+ attributes: Record<string, string>;
271
+ pricing: {
272
+ onDemand?: {
273
+ pricePerUnit: number;
274
+ unit: string;
275
+ };
276
+ };
277
+ }
278
+ ```
279
+
280
+ ### Cost Calculation Assumptions
281
+
282
+ For resources with usage-based pricing, the following default assumptions are used:
283
+
284
+ - **S3 Buckets**: 100 GB standard storage, 10,000 GET requests/month
285
+ - **Lambda Functions**: 1 million invocations/month, average 1-second duration
286
+ - **RDS Instances**: 100 GB storage, single-AZ deployment
287
+ - **EC2 Instances**: 730 hours/month (full month), on-demand pricing
288
+
289
+ These assumptions can be documented in the cost report and made configurable in Phase 2.
290
+
291
+ ## Correct
292
+ ness Properties
293
+
294
+ *A property is a characteristic or behavior that should hold true across all valid executions of a system—essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.*
295
+
296
+ Property 1: Template parsing succeeds for valid templates
297
+ *For any* valid CloudFormation template (JSON or YAML), the parser should successfully parse it without throwing errors and return a structured template object.
298
+ **Validates: Requirements 1.1**
299
+
300
+ Property 2: Diff engine correctly categorizes resources
301
+ *For any* pair of CloudFormation templates with known differences, the diff engine should correctly identify all added resources (in target but not base), removed resources (in base but not target), and modified resources (in both with different properties).
302
+ **Validates: Requirements 1.2**
303
+
304
+ Property 3: Cost calculation produces valid results
305
+ *For any* supported resource type, the cost calculator should return a non-negative cost value with a valid currency code and confidence level.
306
+ **Validates: Requirements 1.3**
307
+
308
+ Property 4: Total cost delta equals sum of individual costs
309
+ *For any* cost analysis result, the total cost delta should equal the sum of all added resource costs minus the sum of all removed resource costs plus the sum of all modified resource cost deltas.
310
+ **Validates: Requirements 1.4**
311
+
312
+ Property 5: Resources appear in exactly one category
313
+ *For any* cost report, each resource should appear in exactly one category (added, removed, or modified), and all resources from the diff should appear in the report.
314
+ **Validates: Requirements 1.5**
315
+
316
+ Property 6: EC2 costs vary by instance type and region
317
+ *For any* two EC2 instances with different instance types or regions, their calculated costs should differ (unless they happen to have identical pricing).
318
+ **Validates: Requirements 2.1**
319
+
320
+ Property 7: S3 buckets receive cost estimates
321
+ *For any* S3 bucket resource, the cost calculator should return a cost estimate greater than zero based on default storage assumptions.
322
+ **Validates: Requirements 2.2**
323
+
324
+ Property 8: Lambda costs scale with memory configuration
325
+ *For any* two Lambda functions where one has higher memory allocation than the other, the higher memory function should have equal or higher estimated cost.
326
+ **Validates: Requirements 2.3**
327
+
328
+ Property 9: RDS costs are calculated for all engine types
329
+ *For any* RDS instance resource with a valid engine type, the cost calculator should return a cost estimate greater than zero.
330
+ **Validates: Requirements 2.4**
331
+
332
+ Property 10: Unsupported resources don't cause failures
333
+ *For any* template containing unsupported resource types, the analysis should complete successfully, marking unsupported resources as having unknown costs without throwing errors.
334
+ **Validates: Requirements 2.5**
335
+
336
+ Property 11: CLI accepts valid template file paths
337
+ *For any* valid file paths pointing to CloudFormation templates, the CLI should accept them as arguments and proceed with analysis.
338
+ **Validates: Requirements 3.2**
339
+
340
+ Property 12: CLI region flag overrides default
341
+ *For any* valid AWS region provided via the --region flag, the analysis should use that region instead of the default eu-central-1.
342
+ **Validates: Requirements 3.3**
343
+
344
+ Property 13: Successful analysis outputs to stdout
345
+ *For any* successful cost analysis via CLI, the formatted report should be written to stdout and the process should exit with code 0.
346
+ **Validates: Requirements 3.4**
347
+
348
+ Property 14: Invalid inputs cause non-zero exit
349
+ *For any* invalid template file (missing, malformed, or unreadable), the CLI should exit with a non-zero status code and write an error message to stderr.
350
+ **Validates: Requirements 3.5**
351
+
352
+ Property 15: API returns structured results
353
+ *For any* successful analysis via the programmatic API, the return value should be an object containing totalDelta, currency, addedResources, removedResources, modifiedResources, and summary fields.
354
+ **Validates: Requirements 4.3**
355
+
356
+ Property 16: API throws errors for invalid inputs
357
+ *For any* invalid input (malformed templates, invalid region), the API should throw a descriptive error rather than returning undefined or crashing.
358
+ **Validates: Requirements 4.4**
359
+
360
+ Property 17: Pricing queries include region filter
361
+ *For any* cost calculation, the AWS Pricing API queries should include the specified region as a filter parameter.
362
+ **Validates: Requirements 5.2**
363
+
364
+ Property 18: Failed pricing calls trigger retries
365
+ *For any* transient pricing API failure, the system should retry the request up to 3 times with exponential backoff before giving up.
366
+ **Validates: Requirements 5.3**
367
+
368
+ Property 19: Cache is used when API fails
369
+ *For any* pricing API failure where cached data exists for the requested resource and region, the system should use the cached data instead of marking the cost as unknown.
370
+ **Validates: Requirements 5.4**
371
+
372
+ Property 20: Unavailable pricing results in unknown cost
373
+ *For any* resource where pricing data cannot be retrieved (API fails and no cache exists), the resource should be marked with confidence level 'unknown' and cost calculation should continue.
374
+ **Validates: Requirements 5.5**
375
+
376
+ Property 21: Reports contain all required resource fields
377
+ *For any* resource listed in a cost report, the entry should include the resource's logical ID, type, and estimated monthly cost.
378
+ **Validates: Requirements 6.2**
379
+
380
+ Property 22: Currency values are consistently formatted
381
+ *For any* cost value displayed in a report, it should be formatted with exactly two decimal places and include the appropriate currency symbol.
382
+ **Validates: Requirements 6.3**
383
+
384
+ Property 23: Positive deltas have plus sign prefix
385
+ *For any* cost delta greater than zero in a report, the formatted value should include a plus sign (+) prefix.
386
+ **Validates: Requirements 6.4**
387
+
388
+ Property 24: Negative deltas have minus sign prefix
389
+ *For any* cost delta less than zero in a report, the formatted value should include a minus sign (-) prefix.
390
+ **Validates: Requirements 6.5**
391
+
392
+ ## Error Handling
393
+
394
+ ### Error Categories
395
+
396
+ 1. **Input Errors**
397
+ - Invalid template syntax (JSON/YAML parsing errors)
398
+ - Missing required template fields
399
+ - Invalid file paths
400
+ - Invalid region codes
401
+
402
+ 2. **API Errors**
403
+ - AWS Pricing API failures
404
+ - Network timeouts
405
+ - Authentication errors
406
+ - Rate limiting
407
+
408
+ 3. **Calculation Errors**
409
+ - Unsupported resource types
410
+ - Missing pricing data
411
+ - Invalid resource configurations
412
+
413
+ ### Error Handling Strategy
414
+
415
+ **Input Errors**: Fail fast with clear error messages
416
+ - Validate inputs early in the process
417
+ - Provide specific error messages indicating what's wrong
418
+ - Exit with non-zero status code (CLI) or throw typed exceptions (API)
419
+
420
+ **API Errors**: Retry with fallback
421
+ - Implement exponential backoff for transient failures
422
+ - Fall back to cached pricing data when available
423
+ - Continue analysis with "unknown" costs if pricing unavailable
424
+ - Log warnings for partial failures
425
+
426
+ **Calculation Errors**: Graceful degradation
427
+ - Mark unsupported resources as "unknown" cost
428
+ - Continue processing other resources
429
+ - Include warnings in the report
430
+ - Document assumptions and limitations
431
+
432
+ ### Error Types
433
+
434
+ ```typescript
435
+ class TemplateParseError extends Error {
436
+ constructor(message: string, public templatePath?: string) {
437
+ super(message);
438
+ this.name = 'TemplateParseError';
439
+ }
440
+ }
441
+
442
+ class PricingAPIError extends Error {
443
+ constructor(message: string, public retryable: boolean = true) {
444
+ super(message);
445
+ this.name = 'PricingAPIError';
446
+ }
447
+ }
448
+
449
+ class UnsupportedResourceError extends Error {
450
+ constructor(public resourceType: string) {
451
+ super(`Resource type ${resourceType} is not supported`);
452
+ this.name = 'UnsupportedResourceError';
453
+ }
454
+ }
455
+ ```
456
+
457
+ ## Testing Strategy
458
+
459
+ ### Unit Testing
460
+
461
+ Unit tests will verify specific behaviors and edge cases:
462
+
463
+ **Template Parser Tests**:
464
+ - Parse valid JSON templates
465
+ - Parse valid YAML templates
466
+ - Handle malformed JSON/YAML
467
+ - Handle missing Resources section
468
+ - Handle empty templates
469
+
470
+ **Diff Engine Tests**:
471
+ - Identify added resources
472
+ - Identify removed resources
473
+ - Identify modified resources
474
+ - Handle identical templates (no changes)
475
+ - Handle completely different templates
476
+
477
+ **Cost Calculator Tests**:
478
+ - Calculate EC2 costs for specific instance types
479
+ - Calculate S3 costs with default assumptions
480
+ - Calculate Lambda costs with different memory settings
481
+ - Calculate RDS costs for different engines
482
+ - Handle unsupported resource types
483
+
484
+ **Reporter Tests**:
485
+ - Format text reports correctly
486
+ - Format JSON reports correctly
487
+ - Format currency values
488
+ - Format positive/negative deltas
489
+ - Sort resources by cost impact
490
+
491
+ **CLI Tests**:
492
+ - Parse command-line arguments
493
+ - Handle missing files
494
+ - Handle invalid regions
495
+ - Exit with correct status codes
496
+ - Output to stdout/stderr appropriately
497
+
498
+ ### Property-Based Testing
499
+
500
+ Property-based tests will verify universal properties across many inputs using a PBT library (fast-check for TypeScript):
501
+
502
+ **Template Parsing Properties**:
503
+ - Property 1: Template parsing succeeds for valid templates (Requirements 1.1)
504
+ - Property 10: Unsupported resources don't cause failures (Requirements 2.5)
505
+
506
+ **Diff Engine Properties**:
507
+ - Property 2: Diff engine correctly categorizes resources (Requirements 1.2)
508
+ - Property 5: Resources appear in exactly one category (Requirements 1.5)
509
+
510
+ **Cost Calculation Properties**:
511
+ - Property 3: Cost calculation produces valid results (Requirements 1.3)
512
+ - Property 4: Total cost delta equals sum of individual costs (Requirements 1.4)
513
+ - Property 6: EC2 costs vary by instance type and region (Requirements 2.1)
514
+ - Property 8: Lambda costs scale with memory configuration (Requirements 2.3)
515
+
516
+ **API Properties**:
517
+ - Property 15: API returns structured results (Requirements 4.3)
518
+ - Property 16: API throws errors for invalid inputs (Requirements 4.4)
519
+
520
+ **Pricing Service Properties**:
521
+ - Property 17: Pricing queries include region filter (Requirements 5.2)
522
+ - Property 18: Failed pricing calls trigger retries (Requirements 5.3)
523
+ - Property 19: Cache is used when API fails (Requirements 5.4)
524
+ - Property 20: Unavailable pricing results in unknown cost (Requirements 5.5)
525
+
526
+ **Reporter Properties**:
527
+ - Property 21: Reports contain all required resource fields (Requirements 6.2)
528
+ - Property 22: Currency values are consistently formatted (Requirements 6.3)
529
+ - Property 23: Positive deltas have plus sign prefix (Requirements 6.4)
530
+ - Property 24: Negative deltas have minus sign prefix (Requirements 6.5)
531
+
532
+ **Testing Configuration**:
533
+ - Each property-based test will run a minimum of 100 iterations
534
+ - Each test will be tagged with a comment referencing the design document property
535
+ - Tag format: `// Feature: cdk-cost-analyzer, Property {number}: {property_text}`
536
+
537
+ ### Integration Testing
538
+
539
+ Integration tests will verify end-to-end workflows:
540
+
541
+ - Complete CLI workflow with real template files
542
+ - Complete API workflow with programmatic calls
543
+ - AWS Pricing API integration (with mocked responses)
544
+ - Error handling across component boundaries
545
+
546
+ ### Test Data
547
+
548
+ **Sample Templates**:
549
+ - Minimal valid template (single resource)
550
+ - Complex template (multiple resource types)
551
+ - Template with EC2 instances
552
+ - Template with S3 buckets
553
+ - Template with Lambda functions
554
+ - Template with RDS instances
555
+ - Template with unsupported resources
556
+ - Malformed templates (invalid JSON/YAML)
557
+
558
+ **Pricing Data**:
559
+ - Mock pricing responses for each supported resource type
560
+ - Mock pricing responses for different regions
561
+ - Mock error responses for API failures
562
+
563
+ ## Dependencies
564
+
565
+ ### Production Dependencies
566
+
567
+ - **aws-sdk** (v3): AWS Pricing API client
568
+ - **js-yaml**: YAML template parsing
569
+ - **commander**: CLI argument parsing
570
+
571
+ ### Development Dependencies
572
+
573
+ - **typescript**: TypeScript compiler
574
+ - **fast-check**: Property-based testing library
575
+ - **vitest**: Unit testing framework
576
+ - **@types/node**: Node.js type definitions
577
+ - **@types/js-yaml**: js-yaml type definitions
578
+
579
+ ### Dependency Justification
580
+
581
+ - **aws-sdk**: Required for AWS Pricing API integration
582
+ - **js-yaml**: Standard library for YAML parsing, widely used and maintained
583
+ - **commander**: Popular CLI framework with good TypeScript support
584
+ - **fast-check**: Leading property-based testing library for TypeScript
585
+ - **vitest**: Fast, modern testing framework with excellent TypeScript support
586
+
587
+ ## Implementation Notes
588
+
589
+ ### Phase 1 Scope
590
+
591
+ The MVP implementation will focus on:
592
+ 1. Core template parsing and diffing
593
+ 2. Basic cost calculation for EC2, S3, Lambda, RDS
594
+ 3. Simple CLI and programmatic API
595
+ 4. Text and JSON report formats
596
+ 5. AWS Pricing API integration with retry logic
597
+
598
+ ### Phase 2 Considerations
599
+
600
+ The design supports future enhancements:
601
+ - GitLab integration can be added as a separate module
602
+ - Additional resource calculators can be registered
603
+ - Markdown report format for MR comments
604
+ - CDK synthesis can be added before parsing
605
+ - Historical tracking can use the existing data structures
606
+
607
+ ### Performance Considerations
608
+
609
+ - Pricing data caching to reduce API calls
610
+ - Lazy loading of AWS SDK to improve startup time
611
+ - Parallel pricing queries for multiple resources
612
+ - Efficient template parsing with streaming for large files
613
+
614
+ ### Security Considerations
615
+
616
+ - No AWS credentials stored in code
617
+ - Use AWS SDK default credential chain
618
+ - Validate all user inputs (file paths, regions)
619
+ - Sanitize template content before parsing
620
+ - Rate limiting for AWS API calls