@friggframework/devtools 2.0.0-next.44 → 2.0.0-next.46

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 (212) hide show
  1. package/infrastructure/ARCHITECTURE.md +487 -0
  2. package/infrastructure/HEALTH.md +468 -0
  3. package/infrastructure/README.md +51 -0
  4. package/infrastructure/__tests__/postgres-config.test.js +914 -0
  5. package/infrastructure/__tests__/template-generation.test.js +687 -0
  6. package/infrastructure/create-frigg-infrastructure.js +1 -1
  7. package/infrastructure/docs/POSTGRES-CONFIGURATION.md +630 -0
  8. package/infrastructure/{DEPLOYMENT-INSTRUCTIONS.md → docs/deployment-instructions.md} +3 -3
  9. package/infrastructure/{IAM-POLICY-TEMPLATES.md → docs/iam-policy-templates.md} +9 -10
  10. package/infrastructure/domains/database/aurora-builder.js +809 -0
  11. package/infrastructure/domains/database/aurora-builder.test.js +950 -0
  12. package/infrastructure/domains/database/aurora-discovery.js +87 -0
  13. package/infrastructure/domains/database/aurora-discovery.test.js +188 -0
  14. package/infrastructure/domains/database/aurora-resolver.js +210 -0
  15. package/infrastructure/domains/database/aurora-resolver.test.js +347 -0
  16. package/infrastructure/domains/database/migration-builder.js +633 -0
  17. package/infrastructure/domains/database/migration-builder.test.js +294 -0
  18. package/infrastructure/domains/database/migration-resolver.js +163 -0
  19. package/infrastructure/domains/database/migration-resolver.test.js +337 -0
  20. package/infrastructure/domains/health/application/ports/IPropertyReconciler.js +164 -0
  21. package/infrastructure/domains/health/application/ports/IResourceDetector.js +129 -0
  22. package/infrastructure/domains/health/application/ports/IResourceImporter.js +142 -0
  23. package/infrastructure/domains/health/application/ports/IStackRepository.js +131 -0
  24. package/infrastructure/domains/health/application/ports/index.js +26 -0
  25. package/infrastructure/domains/health/application/use-cases/__tests__/execute-resource-import-use-case.test.js +679 -0
  26. package/infrastructure/domains/health/application/use-cases/__tests__/mismatch-analyzer-method-name.test.js +167 -0
  27. package/infrastructure/domains/health/application/use-cases/__tests__/repair-via-import-use-case.test.js +1130 -0
  28. package/infrastructure/domains/health/application/use-cases/execute-resource-import-use-case.js +221 -0
  29. package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.js +152 -0
  30. package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.test.js +343 -0
  31. package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.js +535 -0
  32. package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.test.js +376 -0
  33. package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.js +213 -0
  34. package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.test.js +441 -0
  35. package/infrastructure/domains/health/docs/ACME-DEV-DRIFT-ANALYSIS.md +267 -0
  36. package/infrastructure/domains/health/docs/BUILD-VS-DEPLOYED-TEMPLATE-ANALYSIS.md +324 -0
  37. package/infrastructure/domains/health/docs/ORPHAN-DETECTION-ANALYSIS.md +386 -0
  38. package/infrastructure/domains/health/docs/SPEC-CLEANUP-COMMAND.md +1419 -0
  39. package/infrastructure/domains/health/docs/TDD-IMPLEMENTATION-SUMMARY.md +391 -0
  40. package/infrastructure/domains/health/docs/TEMPLATE-COMPARISON-IMPLEMENTATION.md +551 -0
  41. package/infrastructure/domains/health/domain/entities/issue.js +299 -0
  42. package/infrastructure/domains/health/domain/entities/issue.test.js +528 -0
  43. package/infrastructure/domains/health/domain/entities/property-mismatch.js +108 -0
  44. package/infrastructure/domains/health/domain/entities/property-mismatch.test.js +275 -0
  45. package/infrastructure/domains/health/domain/entities/resource.js +159 -0
  46. package/infrastructure/domains/health/domain/entities/resource.test.js +432 -0
  47. package/infrastructure/domains/health/domain/entities/stack-health-report.js +306 -0
  48. package/infrastructure/domains/health/domain/entities/stack-health-report.test.js +601 -0
  49. package/infrastructure/domains/health/domain/services/__tests__/health-score-percentage-based.test.js +380 -0
  50. package/infrastructure/domains/health/domain/services/__tests__/import-progress-monitor.test.js +971 -0
  51. package/infrastructure/domains/health/domain/services/__tests__/import-template-generator.test.js +1150 -0
  52. package/infrastructure/domains/health/domain/services/__tests__/logical-id-mapper.test.js +672 -0
  53. package/infrastructure/domains/health/domain/services/__tests__/template-parser.test.js +496 -0
  54. package/infrastructure/domains/health/domain/services/__tests__/update-progress-monitor.test.js +419 -0
  55. package/infrastructure/domains/health/domain/services/health-score-calculator.js +248 -0
  56. package/infrastructure/domains/health/domain/services/health-score-calculator.test.js +504 -0
  57. package/infrastructure/domains/health/domain/services/import-progress-monitor.js +195 -0
  58. package/infrastructure/domains/health/domain/services/import-template-generator.js +435 -0
  59. package/infrastructure/domains/health/domain/services/logical-id-mapper.js +345 -0
  60. package/infrastructure/domains/health/domain/services/mismatch-analyzer.js +234 -0
  61. package/infrastructure/domains/health/domain/services/mismatch-analyzer.test.js +431 -0
  62. package/infrastructure/domains/health/domain/services/property-mutability-config.js +382 -0
  63. package/infrastructure/domains/health/domain/services/template-parser.js +245 -0
  64. package/infrastructure/domains/health/domain/services/update-progress-monitor.js +192 -0
  65. package/infrastructure/domains/health/domain/value-objects/health-score.js +138 -0
  66. package/infrastructure/domains/health/domain/value-objects/health-score.test.js +267 -0
  67. package/infrastructure/domains/health/domain/value-objects/property-mutability.js +161 -0
  68. package/infrastructure/domains/health/domain/value-objects/property-mutability.test.js +198 -0
  69. package/infrastructure/domains/health/domain/value-objects/resource-state.js +167 -0
  70. package/infrastructure/domains/health/domain/value-objects/resource-state.test.js +196 -0
  71. package/infrastructure/domains/health/domain/value-objects/stack-identifier.js +192 -0
  72. package/infrastructure/domains/health/domain/value-objects/stack-identifier.test.js +262 -0
  73. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-cfn-tagged.test.js +312 -0
  74. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-multi-stack.test.js +367 -0
  75. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-relationship-analysis.test.js +432 -0
  76. package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.js +784 -0
  77. package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.test.js +1133 -0
  78. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.js +565 -0
  79. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.test.js +554 -0
  80. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.js +318 -0
  81. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.test.js +398 -0
  82. package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.js +777 -0
  83. package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.test.js +580 -0
  84. package/infrastructure/domains/integration/integration-builder.js +397 -0
  85. package/infrastructure/domains/integration/integration-builder.test.js +593 -0
  86. package/infrastructure/domains/integration/integration-resolver.js +170 -0
  87. package/infrastructure/domains/integration/integration-resolver.test.js +369 -0
  88. package/infrastructure/domains/integration/websocket-builder.js +69 -0
  89. package/infrastructure/domains/integration/websocket-builder.test.js +195 -0
  90. package/infrastructure/domains/networking/vpc-builder.js +1829 -0
  91. package/infrastructure/domains/networking/vpc-builder.test.js +1262 -0
  92. package/infrastructure/domains/networking/vpc-discovery.js +177 -0
  93. package/infrastructure/domains/networking/vpc-discovery.test.js +350 -0
  94. package/infrastructure/domains/networking/vpc-resolver.js +324 -0
  95. package/infrastructure/domains/networking/vpc-resolver.test.js +501 -0
  96. package/infrastructure/domains/parameters/ssm-builder.js +79 -0
  97. package/infrastructure/domains/parameters/ssm-builder.test.js +189 -0
  98. package/infrastructure/domains/parameters/ssm-discovery.js +84 -0
  99. package/infrastructure/domains/parameters/ssm-discovery.test.js +210 -0
  100. package/infrastructure/{iam-generator.js → domains/security/iam-generator.js} +2 -2
  101. package/infrastructure/domains/security/kms-builder.js +366 -0
  102. package/infrastructure/domains/security/kms-builder.test.js +374 -0
  103. package/infrastructure/domains/security/kms-discovery.js +80 -0
  104. package/infrastructure/domains/security/kms-discovery.test.js +177 -0
  105. package/infrastructure/domains/security/kms-resolver.js +96 -0
  106. package/infrastructure/domains/security/kms-resolver.test.js +216 -0
  107. package/infrastructure/domains/shared/base-builder.js +112 -0
  108. package/infrastructure/domains/shared/base-resolver.js +186 -0
  109. package/infrastructure/domains/shared/base-resolver.test.js +305 -0
  110. package/infrastructure/domains/shared/builder-orchestrator.js +212 -0
  111. package/infrastructure/domains/shared/builder-orchestrator.test.js +213 -0
  112. package/infrastructure/domains/shared/cloudformation-discovery-v2.js +334 -0
  113. package/infrastructure/domains/shared/cloudformation-discovery.js +375 -0
  114. package/infrastructure/domains/shared/cloudformation-discovery.test.js +590 -0
  115. package/infrastructure/domains/shared/environment-builder.js +119 -0
  116. package/infrastructure/domains/shared/environment-builder.test.js +247 -0
  117. package/infrastructure/domains/shared/providers/aws-provider-adapter.js +544 -0
  118. package/infrastructure/domains/shared/providers/aws-provider-adapter.test.js +377 -0
  119. package/infrastructure/domains/shared/providers/azure-provider-adapter.stub.js +93 -0
  120. package/infrastructure/domains/shared/providers/cloud-provider-adapter.js +136 -0
  121. package/infrastructure/domains/shared/providers/gcp-provider-adapter.stub.js +82 -0
  122. package/infrastructure/domains/shared/providers/provider-factory.js +108 -0
  123. package/infrastructure/domains/shared/providers/provider-factory.test.js +170 -0
  124. package/infrastructure/domains/shared/resource-discovery.js +192 -0
  125. package/infrastructure/domains/shared/resource-discovery.test.js +552 -0
  126. package/infrastructure/domains/shared/types/app-definition.js +205 -0
  127. package/infrastructure/domains/shared/types/discovery-result.js +106 -0
  128. package/infrastructure/domains/shared/types/discovery-result.test.js +258 -0
  129. package/infrastructure/domains/shared/types/index.js +46 -0
  130. package/infrastructure/domains/shared/types/resource-ownership.js +108 -0
  131. package/infrastructure/domains/shared/types/resource-ownership.test.js +101 -0
  132. package/infrastructure/domains/shared/utilities/base-definition-factory.js +380 -0
  133. package/infrastructure/domains/shared/utilities/base-definition-factory.js.bak +338 -0
  134. package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +248 -0
  135. package/infrastructure/domains/shared/utilities/handler-path-resolver.js +134 -0
  136. package/infrastructure/domains/shared/utilities/handler-path-resolver.test.js +268 -0
  137. package/infrastructure/domains/shared/utilities/prisma-layer-manager.js +55 -0
  138. package/infrastructure/domains/shared/utilities/prisma-layer-manager.test.js +138 -0
  139. package/infrastructure/{env-validator.js → domains/shared/validation/env-validator.js} +2 -1
  140. package/infrastructure/domains/shared/validation/env-validator.test.js +173 -0
  141. package/infrastructure/esbuild.config.js +53 -0
  142. package/infrastructure/infrastructure-composer.js +87 -0
  143. package/infrastructure/{serverless-template.test.js → infrastructure-composer.test.js} +115 -24
  144. package/infrastructure/scripts/build-prisma-layer.js +553 -0
  145. package/infrastructure/scripts/build-prisma-layer.test.js +102 -0
  146. package/infrastructure/{build-time-discovery.js → scripts/build-time-discovery.js} +80 -48
  147. package/infrastructure/{build-time-discovery.test.js → scripts/build-time-discovery.test.js} +5 -4
  148. package/layers/prisma/nodejs/package.json +8 -0
  149. package/management-ui/server/utils/cliIntegration.js +1 -1
  150. package/management-ui/server/utils/environment/awsParameterStore.js +29 -18
  151. package/package.json +11 -11
  152. package/frigg-cli/.eslintrc.js +0 -141
  153. package/frigg-cli/__tests__/unit/commands/build.test.js +0 -251
  154. package/frigg-cli/__tests__/unit/commands/db-setup.test.js +0 -548
  155. package/frigg-cli/__tests__/unit/commands/install.test.js +0 -400
  156. package/frigg-cli/__tests__/unit/commands/ui.test.js +0 -346
  157. package/frigg-cli/__tests__/unit/utils/database-validator.test.js +0 -366
  158. package/frigg-cli/__tests__/unit/utils/error-messages.test.js +0 -304
  159. package/frigg-cli/__tests__/unit/utils/prisma-runner.test.js +0 -486
  160. package/frigg-cli/__tests__/utils/mock-factory.js +0 -270
  161. package/frigg-cli/__tests__/utils/prisma-mock.js +0 -194
  162. package/frigg-cli/__tests__/utils/test-fixtures.js +0 -463
  163. package/frigg-cli/__tests__/utils/test-setup.js +0 -287
  164. package/frigg-cli/build-command/index.js +0 -65
  165. package/frigg-cli/db-setup-command/index.js +0 -193
  166. package/frigg-cli/deploy-command/index.js +0 -175
  167. package/frigg-cli/generate-command/__tests__/generate-command.test.js +0 -301
  168. package/frigg-cli/generate-command/azure-generator.js +0 -43
  169. package/frigg-cli/generate-command/gcp-generator.js +0 -47
  170. package/frigg-cli/generate-command/index.js +0 -332
  171. package/frigg-cli/generate-command/terraform-generator.js +0 -555
  172. package/frigg-cli/generate-iam-command.js +0 -118
  173. package/frigg-cli/index.js +0 -75
  174. package/frigg-cli/index.test.js +0 -158
  175. package/frigg-cli/init-command/backend-first-handler.js +0 -756
  176. package/frigg-cli/init-command/index.js +0 -93
  177. package/frigg-cli/init-command/template-handler.js +0 -143
  178. package/frigg-cli/install-command/backend-js.js +0 -33
  179. package/frigg-cli/install-command/commit-changes.js +0 -16
  180. package/frigg-cli/install-command/environment-variables.js +0 -127
  181. package/frigg-cli/install-command/environment-variables.test.js +0 -136
  182. package/frigg-cli/install-command/index.js +0 -54
  183. package/frigg-cli/install-command/install-package.js +0 -13
  184. package/frigg-cli/install-command/integration-file.js +0 -30
  185. package/frigg-cli/install-command/logger.js +0 -12
  186. package/frigg-cli/install-command/template.js +0 -90
  187. package/frigg-cli/install-command/validate-package.js +0 -75
  188. package/frigg-cli/jest.config.js +0 -124
  189. package/frigg-cli/package.json +0 -54
  190. package/frigg-cli/start-command/index.js +0 -149
  191. package/frigg-cli/start-command/start-command.test.js +0 -297
  192. package/frigg-cli/test/init-command.test.js +0 -180
  193. package/frigg-cli/test/npm-registry.test.js +0 -319
  194. package/frigg-cli/ui-command/index.js +0 -154
  195. package/frigg-cli/utils/app-resolver.js +0 -319
  196. package/frigg-cli/utils/backend-path.js +0 -25
  197. package/frigg-cli/utils/database-validator.js +0 -161
  198. package/frigg-cli/utils/error-messages.js +0 -257
  199. package/frigg-cli/utils/npm-registry.js +0 -167
  200. package/frigg-cli/utils/prisma-runner.js +0 -280
  201. package/frigg-cli/utils/process-manager.js +0 -199
  202. package/frigg-cli/utils/repo-detection.js +0 -405
  203. package/infrastructure/aws-discovery.js +0 -1176
  204. package/infrastructure/aws-discovery.test.js +0 -1220
  205. package/infrastructure/serverless-template.js +0 -2074
  206. /package/infrastructure/{WEBSOCKET-CONFIGURATION.md → docs/WEBSOCKET-CONFIGURATION.md} +0 -0
  207. /package/infrastructure/{GENERATE-IAM-DOCS.md → docs/generate-iam-command.md} +0 -0
  208. /package/infrastructure/{iam-generator.test.js → domains/security/iam-generator.test.js} +0 -0
  209. /package/infrastructure/{frigg-deployment-iam-stack.yaml → domains/security/templates/frigg-deployment-iam-stack.yaml} +0 -0
  210. /package/infrastructure/{iam-policy-basic.json → domains/security/templates/iam-policy-basic.json} +0 -0
  211. /package/infrastructure/{iam-policy-full.json → domains/security/templates/iam-policy-full.json} +0 -0
  212. /package/infrastructure/{run-discovery.js → scripts/run-discovery.js} +0 -0
@@ -0,0 +1,221 @@
1
+ /**
2
+ * ExecuteResourceImportUseCase - Execute CloudFormation Resource Import
3
+ *
4
+ * Application Layer - Use Case
5
+ *
6
+ * Business logic for executing CloudFormation import operations for orphaned resources.
7
+ * Orchestrates the complete import workflow including template generation, change set
8
+ * creation, execution monitoring, and verification.
9
+ *
10
+ * Responsibilities:
11
+ * - Generate import template from resources and build template
12
+ * - Create and execute CloudFormation import change set
13
+ * - Monitor import progress with resource-level updates
14
+ * - Verify imported resources are present in stack
15
+ * - Report detailed progress and results
16
+ *
17
+ * Based on: SPEC-IMPORT-EXECUTION.md (lines 712-867)
18
+ */
19
+
20
+ class ExecuteResourceImportUseCase {
21
+ /**
22
+ * Create use case with required dependencies
23
+ *
24
+ * @param {Object} params
25
+ * @param {Object} params.importTemplateGenerator - Generates import templates
26
+ * @param {Object} params.importProgressMonitor - Monitors import operations
27
+ * @param {Object} params.cloudFormationRepository - CloudFormation operations
28
+ * @param {Object} params.stackRepository - Stack template operations
29
+ */
30
+ constructor({ importTemplateGenerator, importProgressMonitor, cloudFormationRepository, stackRepository }) {
31
+ if (!importTemplateGenerator) {
32
+ throw new Error('importTemplateGenerator is required');
33
+ }
34
+ if (!importProgressMonitor) {
35
+ throw new Error('importProgressMonitor is required');
36
+ }
37
+ if (!cloudFormationRepository) {
38
+ throw new Error('cloudFormationRepository is required');
39
+ }
40
+ if (!stackRepository) {
41
+ throw new Error('stackRepository is required');
42
+ }
43
+
44
+ this.templateGenerator = importTemplateGenerator;
45
+ this.progressMonitor = importProgressMonitor;
46
+ this.cfRepo = cloudFormationRepository;
47
+ this.stackRepo = stackRepository;
48
+ }
49
+
50
+ /**
51
+ * Execute complete CloudFormation import workflow
52
+ *
53
+ * Orchestrates the full import process:
54
+ * 1. Generate import template
55
+ * 2. Create CloudFormation change set
56
+ * 3. Wait for change set to be ready
57
+ * 4. Execute change set
58
+ * 5. Monitor import progress
59
+ * 6. Verify imported resources
60
+ *
61
+ * @param {Object} params
62
+ * @param {Object} params.stackIdentifier - Stack name and region
63
+ * @param {Array<Object>} params.resourcesToImport - Resources to import
64
+ * @param {string} params.buildTemplatePath - Path to build template
65
+ * @param {Function} [params.onProgress] - Progress callback
66
+ * @returns {Promise<Object>} Import result with verification details
67
+ */
68
+ async execute({ stackIdentifier, resourcesToImport, buildTemplatePath, onProgress }) {
69
+ try {
70
+ // Step 1: Generate import template
71
+ if (onProgress) {
72
+ onProgress({ step: 'generate_template', status: 'in_progress' });
73
+ }
74
+
75
+ const { template, resourceIdentifiers } = await this.templateGenerator.generateImportTemplate({
76
+ resourcesToImport,
77
+ buildTemplatePath,
78
+ stackIdentifier,
79
+ });
80
+
81
+ if (onProgress) {
82
+ onProgress({ step: 'generate_template', status: 'complete' });
83
+ }
84
+
85
+ // Step 2: Create CloudFormation change set
86
+ if (onProgress) {
87
+ onProgress({ step: 'create_change_set', status: 'in_progress' });
88
+ }
89
+
90
+ const changeSetName = `import-orphaned-resources-${Date.now()}`;
91
+ const changeSet = await this.cfRepo.createChangeSet({
92
+ stackIdentifier,
93
+ changeSetName,
94
+ changeSetType: 'IMPORT',
95
+ template,
96
+ resourcesToImport: resourceIdentifiers,
97
+ });
98
+
99
+ if (onProgress) {
100
+ onProgress({
101
+ step: 'create_change_set',
102
+ status: 'complete',
103
+ changeSetName,
104
+ changeSetId: changeSet.Id,
105
+ });
106
+ }
107
+
108
+ // Step 3: Wait for change set to be ready
109
+ if (onProgress) {
110
+ onProgress({ step: 'wait_change_set', status: 'in_progress' });
111
+ }
112
+
113
+ await this.cfRepo.waitForChangeSet({ stackIdentifier, changeSetName });
114
+
115
+ if (onProgress) {
116
+ onProgress({ step: 'wait_change_set', status: 'complete' });
117
+ }
118
+
119
+ // Step 4: Execute change set
120
+ if (onProgress) {
121
+ onProgress({ step: 'execute_import', status: 'in_progress' });
122
+ }
123
+
124
+ await this.cfRepo.executeChangeSet({ stackIdentifier, changeSetName });
125
+
126
+ // Step 5: Monitor import progress
127
+ const resourceLogicalIds = resourcesToImport.map((r) => r.logicalId);
128
+ const importResult = await this.progressMonitor.monitorImport({
129
+ stackIdentifier,
130
+ resourceLogicalIds,
131
+ onProgress: (progress) => {
132
+ if (onProgress) {
133
+ onProgress({
134
+ step: 'execute_import',
135
+ status: 'in_progress',
136
+ resourceProgress: progress,
137
+ });
138
+ }
139
+ },
140
+ });
141
+
142
+ if (onProgress) {
143
+ onProgress({ step: 'execute_import', status: 'complete' });
144
+ }
145
+
146
+ // Step 6: Verify imported resources
147
+ if (onProgress) {
148
+ onProgress({ step: 'verify', status: 'in_progress' });
149
+ }
150
+
151
+ const verification = await this._verifyImportedResources({
152
+ stackIdentifier,
153
+ resourceLogicalIds,
154
+ });
155
+
156
+ if (onProgress) {
157
+ onProgress({ step: 'verify', status: 'complete' });
158
+ }
159
+
160
+ // Return success result with verification details
161
+ return {
162
+ success: true,
163
+ importedCount: importResult.importedCount,
164
+ failedCount: importResult.failedCount,
165
+ changeSetName,
166
+ stackStatus: verification.stackStatus,
167
+ verifiedResources: verification.resources,
168
+ };
169
+ } catch (error) {
170
+ // Return error with step information
171
+ return {
172
+ success: false,
173
+ error: error.message,
174
+ step: error.step || 'unknown',
175
+ };
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Verify that imported resources are present in the CloudFormation stack
181
+ *
182
+ * Checks that each logical ID corresponds to an actual resource in the stack
183
+ * and retrieves physical IDs and resource types for verification.
184
+ *
185
+ * @param {Object} params
186
+ * @param {Object} params.stackIdentifier - Stack name and region
187
+ * @param {Array<string>} params.resourceLogicalIds - Logical IDs to verify
188
+ * @returns {Promise<Object>} Verification result with resource details
189
+ * @private
190
+ */
191
+ async _verifyImportedResources({ stackIdentifier, resourceLogicalIds }) {
192
+ // Get all resources from the stack
193
+ const stackResources = await this.cfRepo.getStackResources(stackIdentifier);
194
+
195
+ // Map each logical ID to its verification status
196
+ const verifiedResources = resourceLogicalIds.map((logicalId) => {
197
+ const resource = stackResources.find((r) => r.LogicalResourceId === logicalId);
198
+
199
+ return {
200
+ logicalId,
201
+ verified: !!resource,
202
+ physicalId: resource?.PhysicalResourceId,
203
+ resourceType: resource?.ResourceType,
204
+ };
205
+ });
206
+
207
+ // Check if all resources were verified
208
+ const allVerified = verifiedResources.every((r) => r.verified);
209
+
210
+ // Get current stack status
211
+ const stackStatus = await this.cfRepo.getStackStatus(stackIdentifier);
212
+
213
+ return {
214
+ allVerified,
215
+ resources: verifiedResources,
216
+ stackStatus,
217
+ };
218
+ }
219
+ }
220
+
221
+ module.exports = ExecuteResourceImportUseCase;
@@ -0,0 +1,152 @@
1
+ /**
2
+ * ReconcilePropertiesUseCase - Reconcile Property Drift
3
+ *
4
+ * Application Layer - Use Case
5
+ *
6
+ * Business logic for the "frigg repair --reconcile" command. Orchestrates property
7
+ * drift reconciliation to fix mutable property mismatches between CloudFormation
8
+ * template and actual cloud resources.
9
+ *
10
+ * Responsibilities:
11
+ * - Validate properties can be reconciled
12
+ * - Preview reconciliation impact
13
+ * - Execute reconciliation (template mode or resource mode)
14
+ * - Handle batch reconciliations
15
+ * - Skip immutable properties
16
+ */
17
+
18
+ class ReconcilePropertiesUseCase {
19
+ /**
20
+ * Create use case with required dependencies
21
+ *
22
+ * @param {Object} params
23
+ * @param {IPropertyReconciler} params.propertyReconciler - Property reconciliation operations
24
+ */
25
+ constructor({ propertyReconciler }) {
26
+ if (!propertyReconciler) {
27
+ throw new Error('propertyReconciler is required');
28
+ }
29
+
30
+ this.propertyReconciler = propertyReconciler;
31
+ }
32
+
33
+ /**
34
+ * Reconcile a single property mismatch
35
+ *
36
+ * @param {Object} params
37
+ * @param {StackIdentifier} params.stackIdentifier - Stack identifier
38
+ * @param {string} params.logicalId - Logical resource ID
39
+ * @param {PropertyMismatch} params.mismatch - Property mismatch to reconcile
40
+ * @param {string} [params.mode='template'] - Reconciliation mode
41
+ * @returns {Promise<Object>} Reconciliation result
42
+ */
43
+ async reconcileSingleProperty({ stackIdentifier, logicalId, mismatch, mode = 'template' }) {
44
+ // 1. Check if property can be reconciled
45
+ const canReconcile = await this.propertyReconciler.canReconcile(mismatch);
46
+
47
+ if (!canReconcile) {
48
+ throw new Error(
49
+ `Property ${mismatch.propertyPath} cannot be reconciled automatically (immutable property requires replacement)`
50
+ );
51
+ }
52
+
53
+ // 2. Execute reconciliation
54
+ const result = await this.propertyReconciler.reconcileProperty({
55
+ stackIdentifier,
56
+ logicalId,
57
+ mismatch,
58
+ mode,
59
+ });
60
+
61
+ return result;
62
+ }
63
+
64
+ /**
65
+ * Reconcile multiple property mismatches for a resource
66
+ *
67
+ * @param {Object} params
68
+ * @param {StackIdentifier} params.stackIdentifier - Stack identifier
69
+ * @param {string} params.logicalId - Logical resource ID
70
+ * @param {string} [params.physicalId] - Physical resource ID (required for resource mode)
71
+ * @param {string} [params.resourceType] - Resource type (required for resource mode)
72
+ * @param {PropertyMismatch[]} params.mismatches - Property mismatches to reconcile
73
+ * @param {string} [params.mode='template'] - Reconciliation mode
74
+ * @returns {Promise<Object>} Batch reconciliation result
75
+ */
76
+ async reconcileMultipleProperties({
77
+ stackIdentifier,
78
+ logicalId,
79
+ physicalId,
80
+ resourceType,
81
+ mismatches,
82
+ mode = 'template',
83
+ }) {
84
+ // 1. Filter out immutable properties (cannot be reconciled)
85
+ const reconcilableProperties = [];
86
+ const skippedProperties = [];
87
+
88
+ for (const mismatch of mismatches) {
89
+ const canReconcile = await this.propertyReconciler.canReconcile(mismatch);
90
+
91
+ if (canReconcile) {
92
+ reconcilableProperties.push(mismatch);
93
+ } else {
94
+ skippedProperties.push(mismatch);
95
+ }
96
+ }
97
+
98
+ // 2. If no properties can be reconciled, return early
99
+ if (reconcilableProperties.length === 0) {
100
+ return {
101
+ reconciledCount: 0,
102
+ failedCount: 0,
103
+ skippedCount: skippedProperties.length,
104
+ reconcilableCount: 0,
105
+ message: `All ${mismatches.length} property mismatch(es) require resource replacement (immutable)`,
106
+ results: [],
107
+ };
108
+ }
109
+
110
+ // 3. Reconcile the reconcilable properties
111
+ const batchResult = await this.propertyReconciler.reconcileMultipleProperties({
112
+ stackIdentifier,
113
+ logicalId,
114
+ physicalId,
115
+ resourceType,
116
+ mismatches: reconcilableProperties,
117
+ mode,
118
+ });
119
+
120
+ // 4. Return combined result
121
+ return {
122
+ reconciledCount: batchResult.reconciledCount,
123
+ failedCount: batchResult.failedCount,
124
+ skippedCount: skippedProperties.length,
125
+ reconcilableCount: reconcilableProperties.length,
126
+ message: batchResult.message,
127
+ results: batchResult.results,
128
+ skippedProperties: skippedProperties.length > 0 ? skippedProperties : undefined,
129
+ };
130
+ }
131
+
132
+ /**
133
+ * Preview reconciliation without applying changes
134
+ *
135
+ * @param {Object} params
136
+ * @param {StackIdentifier} params.stackIdentifier - Stack identifier
137
+ * @param {string} params.logicalId - Logical resource ID
138
+ * @param {PropertyMismatch} params.mismatch - Property mismatch to preview
139
+ * @param {string} [params.mode='template'] - Reconciliation mode
140
+ * @returns {Promise<Object>} Preview result
141
+ */
142
+ async previewReconciliation({ stackIdentifier, logicalId, mismatch, mode = 'template' }) {
143
+ return await this.propertyReconciler.previewReconciliation({
144
+ stackIdentifier,
145
+ logicalId,
146
+ mismatch,
147
+ mode,
148
+ });
149
+ }
150
+ }
151
+
152
+ module.exports = ReconcilePropertiesUseCase;