@fjall/components-infrastructure 0.95.0 → 0.99.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 (234) hide show
  1. package/dist/lib/app.d.ts +90 -107
  2. package/dist/lib/app.js +149 -139
  3. package/dist/lib/config/aws/__t17fixture.d.ts +1 -0
  4. package/dist/lib/config/aws/__t17fixture.js +3 -0
  5. package/dist/lib/config/aws/__t17fixtureType.d.ts +2 -0
  6. package/dist/lib/config/aws/__t17fixtureType.js +1 -0
  7. package/dist/lib/config/aws/alarmTopic.js +8 -4
  8. package/dist/lib/config/aws/cloudTrail.js +1 -1
  9. package/dist/lib/config/aws/disasterRecovery.js +11 -16
  10. package/dist/lib/config/aws/ecrDefaultImage.d.ts +0 -1
  11. package/dist/lib/config/aws/ecrDefaultImage.js +13 -23
  12. package/dist/lib/config/aws/identityCenter.d.ts +10 -3
  13. package/dist/lib/config/aws/identityCenter.js +101 -37
  14. package/dist/lib/config/aws/identityCenterGroupMembership.js +8 -2
  15. package/dist/lib/config/aws/identityCenterMembership.d.ts +11 -0
  16. package/dist/lib/config/aws/identityCenterMembership.js +61 -0
  17. package/dist/lib/config/aws/index.d.ts +1 -1
  18. package/dist/lib/config/aws/index.js +1 -1
  19. package/dist/lib/config/aws/ipam.js +6 -11
  20. package/dist/lib/config/aws/oidcConnector.js +5 -1
  21. package/dist/lib/config/aws/scpPreset.js +4 -1
  22. package/dist/lib/patterns/aws/_eslint_test_tmp/leak.d.ts +1 -0
  23. package/dist/lib/patterns/aws/_eslint_test_tmp/leak.js +4 -0
  24. package/dist/lib/patterns/aws/account.js +7 -8
  25. package/dist/lib/patterns/aws/apexDomainPattern.js +10 -10
  26. package/dist/lib/patterns/aws/bastionFactory.d.ts +10 -0
  27. package/dist/lib/patterns/aws/bastionFactory.js +29 -0
  28. package/dist/lib/patterns/aws/buildkite.d.ts +2 -2
  29. package/dist/lib/patterns/aws/buildkite.js +51 -97
  30. package/dist/lib/patterns/aws/cdn.js +1 -1
  31. package/dist/lib/patterns/aws/clickhouseDatabase.d.ts +172 -0
  32. package/dist/lib/patterns/aws/clickhouseDatabase.js +600 -0
  33. package/dist/lib/patterns/aws/compute.d.ts +4 -6
  34. package/dist/lib/patterns/aws/compute.js +7 -13
  35. package/dist/lib/patterns/aws/computeEcs.d.ts +95 -396
  36. package/dist/lib/patterns/aws/computeEcs.js +880 -46
  37. package/dist/lib/patterns/aws/computeEcsTypes.d.ts +889 -0
  38. package/dist/lib/patterns/aws/computeEcsTypes.js +12 -0
  39. package/dist/lib/patterns/aws/computeLambda.d.ts +0 -5
  40. package/dist/lib/patterns/aws/computeLambda.js +1 -2
  41. package/dist/lib/patterns/aws/database.d.ts +50 -8
  42. package/dist/lib/patterns/aws/database.js +183 -27
  43. package/dist/lib/patterns/aws/domain.js +8 -7
  44. package/dist/lib/patterns/aws/index.d.ts +3 -0
  45. package/dist/lib/patterns/aws/index.js +3 -0
  46. package/dist/lib/patterns/aws/interfaces/compute.d.ts +13 -1
  47. package/dist/lib/patterns/aws/interfaces/connector.d.ts +1 -1
  48. package/dist/lib/patterns/aws/interfaces/connector.js +1 -1
  49. package/dist/lib/patterns/aws/interfaces/database.d.ts +187 -8
  50. package/dist/lib/patterns/aws/interfaces/database.js +17 -3
  51. package/dist/lib/patterns/aws/interfaces/index.d.ts +4 -2
  52. package/dist/lib/patterns/aws/interfaces/index.js +4 -2
  53. package/dist/lib/patterns/aws/interfaces/messaging.d.ts +7 -0
  54. package/dist/lib/patterns/aws/interfaces/migrationContributor.d.ts +47 -0
  55. package/dist/lib/patterns/aws/interfaces/migrationContributor.js +9 -0
  56. package/dist/lib/patterns/aws/interfaces/vpcPeer.d.ts +7 -0
  57. package/dist/lib/patterns/aws/interfaces/vpcPeer.js +1 -0
  58. package/dist/lib/patterns/aws/messaging.d.ts +66 -10
  59. package/dist/lib/patterns/aws/messaging.js +115 -20
  60. package/dist/lib/patterns/aws/network.js +16 -7
  61. package/dist/lib/patterns/aws/organisation.d.ts +4 -0
  62. package/dist/lib/patterns/aws/organisation.js +24 -5
  63. package/dist/lib/patterns/aws/storage.d.ts +1 -2
  64. package/dist/lib/patterns/aws/storage.js +3 -2
  65. package/dist/lib/patterns/aws/vpcPeer.d.ts +34 -0
  66. package/dist/lib/patterns/aws/vpcPeer.js +38 -0
  67. package/dist/lib/patterns/aws/vpcPeerAccepter.d.ts +29 -0
  68. package/dist/lib/patterns/aws/vpcPeerAccepter.js +196 -0
  69. package/dist/lib/resources/aws/analytics/clickhouse.js +25 -7
  70. package/dist/lib/resources/aws/analytics/clickhouseAlarms.d.ts +49 -0
  71. package/dist/lib/resources/aws/analytics/clickhouseAlarms.js +140 -0
  72. package/dist/lib/resources/aws/analytics/clickhouseConstants.d.ts +4 -4
  73. package/dist/lib/resources/aws/analytics/clickhouseConstants.js +6 -4
  74. package/dist/lib/resources/aws/analytics/clickhouseTypes.d.ts +12 -0
  75. package/dist/lib/resources/aws/analytics/clickhouseUserData.d.ts +1 -0
  76. package/dist/lib/resources/aws/analytics/clickhouseUserData.js +56 -5
  77. package/dist/lib/resources/aws/analytics/index.d.ts +2 -0
  78. package/dist/lib/resources/aws/analytics/index.js +1 -0
  79. package/dist/lib/resources/aws/base/awsStack.js +4 -2
  80. package/dist/lib/resources/aws/compute/__tmp__/regression-shape.d.ts +2 -0
  81. package/dist/lib/resources/aws/compute/__tmp__/regression-shape.js +11 -0
  82. package/dist/lib/resources/aws/compute/asgInlineLifecycleHook.d.ts +52 -0
  83. package/dist/lib/resources/aws/compute/asgInlineLifecycleHook.js +60 -0
  84. package/dist/lib/resources/aws/compute/blockDeviceVolume.d.ts +8 -0
  85. package/dist/lib/resources/aws/compute/blockDeviceVolume.js +10 -0
  86. package/dist/lib/resources/aws/compute/ec2.d.ts +132 -12
  87. package/dist/lib/resources/aws/compute/ec2.js +163 -23
  88. package/dist/lib/resources/aws/compute/ec2GracefulTerminationHandler.d.ts +41 -0
  89. package/dist/lib/resources/aws/compute/ec2GracefulTerminationHandler.js +194 -0
  90. package/dist/lib/resources/aws/compute/ec2GracefulTerminationLambda.source.cjs +458 -0
  91. package/dist/lib/resources/aws/compute/ecs.d.ts +27 -1
  92. package/dist/lib/resources/aws/compute/ecs.js +42 -2
  93. package/dist/lib/resources/aws/compute/ecsConstants.d.ts +9 -0
  94. package/dist/lib/resources/aws/compute/ecsConstants.js +16 -0
  95. package/dist/lib/resources/aws/compute/ecsImages.js +32 -20
  96. package/dist/lib/resources/aws/compute/ecsLifecycleHookMigration.d.ts +96 -0
  97. package/dist/lib/resources/aws/compute/ecsLifecycleHookMigration.js +113 -0
  98. package/dist/lib/resources/aws/compute/ecsNetworking.d.ts +2 -1
  99. package/dist/lib/resources/aws/compute/ecsNetworking.js +18 -6
  100. package/dist/lib/resources/aws/compute/ecsRemoteConnections.d.ts +38 -0
  101. package/dist/lib/resources/aws/compute/ecsRemoteConnections.js +80 -0
  102. package/dist/lib/resources/aws/compute/ecsServiceFactory.d.ts +13 -4
  103. package/dist/lib/resources/aws/compute/ecsServiceFactory.js +155 -33
  104. package/dist/lib/resources/aws/compute/ecsTaskDefinition.d.ts +31 -1
  105. package/dist/lib/resources/aws/compute/ecsTaskDefinition.js +110 -6
  106. package/dist/lib/resources/aws/compute/ecsTypes.d.ts +180 -13
  107. package/dist/lib/resources/aws/compute/ecsValidation.d.ts +9 -0
  108. package/dist/lib/resources/aws/compute/ecsValidation.js +63 -0
  109. package/dist/lib/resources/aws/compute/index.d.ts +2 -0
  110. package/dist/lib/resources/aws/compute/index.js +2 -0
  111. package/dist/lib/resources/aws/compute/lambda.d.ts +7 -13
  112. package/dist/lib/resources/aws/compute/lambda.js +30 -38
  113. package/dist/lib/resources/aws/compute/lifecycleHookLambda.source.cjs +192 -0
  114. package/dist/lib/resources/aws/compute/persistentDataVolume.d.ts +104 -0
  115. package/dist/lib/resources/aws/compute/persistentDataVolume.js +245 -0
  116. package/dist/lib/resources/aws/compute/persistentDataVolumeLambda.source.cjs +398 -0
  117. package/dist/lib/resources/aws/compute/samApplication.d.ts +15 -0
  118. package/dist/lib/resources/aws/compute/samApplication.js +27 -0
  119. package/dist/lib/resources/aws/database/clickhouseConstants.d.ts +159 -0
  120. package/dist/lib/resources/aws/database/clickhouseConstants.js +181 -0
  121. package/dist/lib/resources/aws/database/clickhouseSchemas.d.ts +71 -0
  122. package/dist/lib/resources/aws/database/clickhouseSchemas.js +157 -0
  123. package/dist/lib/resources/aws/database/clickhouseSecurityGroup.d.ts +14 -0
  124. package/dist/lib/resources/aws/database/clickhouseSecurityGroup.js +23 -0
  125. package/dist/lib/resources/aws/database/clickhouseUserData.d.ts +69 -0
  126. package/dist/lib/resources/aws/database/clickhouseUserData.js +371 -0
  127. package/dist/lib/resources/aws/database/clickhouseXmlRenderer.d.ts +56 -0
  128. package/dist/lib/resources/aws/database/clickhouseXmlRenderer.js +112 -0
  129. package/dist/lib/resources/aws/database/rdsAurora.d.ts +8 -1
  130. package/dist/lib/resources/aws/database/rdsAurora.js +42 -32
  131. package/dist/lib/resources/aws/database/rdsAuroraGlobal.d.ts +15 -2
  132. package/dist/lib/resources/aws/database/rdsAuroraGlobal.js +39 -43
  133. package/dist/lib/resources/aws/database/rdsDefaults.d.ts +6 -0
  134. package/dist/lib/resources/aws/database/rdsDefaults.js +7 -1
  135. package/dist/lib/resources/aws/database/rdsHelpers.d.ts +3 -3
  136. package/dist/lib/resources/aws/database/rdsHelpers.js +1 -0
  137. package/dist/lib/resources/aws/database/rdsInstance.d.ts +8 -1
  138. package/dist/lib/resources/aws/database/rdsInstance.js +51 -34
  139. package/dist/lib/resources/aws/database/rdsProxyOutput.d.ts +1 -1
  140. package/dist/lib/resources/aws/database/rdsProxyOutput.js +1 -1
  141. package/dist/lib/resources/aws/iam/delegationRole.js +12 -5
  142. package/dist/lib/resources/aws/iam/identityCenter/groupMembership.d.ts +9 -0
  143. package/dist/lib/resources/aws/iam/identityCenter/groupMembership.js +12 -0
  144. package/dist/lib/resources/aws/iam/identityCenter/index.d.ts +1 -0
  145. package/dist/lib/resources/aws/iam/identityCenter/index.js +1 -0
  146. package/dist/lib/resources/aws/iam/identityCenter/permissionSet.d.ts +1 -0
  147. package/dist/lib/resources/aws/iam/identityCenter/permissionSet.js +1 -0
  148. package/dist/lib/resources/aws/logging/logGroup.d.ts +0 -8
  149. package/dist/lib/resources/aws/logging/logGroup.js +0 -11
  150. package/dist/lib/resources/aws/messaging/defaultEventBus.d.ts +7 -0
  151. package/dist/lib/resources/aws/messaging/defaultEventBus.js +21 -0
  152. package/dist/lib/resources/aws/messaging/eventBridgeRule.d.ts +96 -0
  153. package/dist/lib/resources/aws/messaging/eventBridgeRule.js +110 -0
  154. package/dist/lib/resources/aws/messaging/eventTargets.d.ts +84 -0
  155. package/dist/lib/resources/aws/messaging/eventTargets.js +152 -0
  156. package/dist/lib/resources/aws/messaging/eventbridge.d.ts +25 -2
  157. package/dist/lib/resources/aws/messaging/eventbridge.js +22 -10
  158. package/dist/lib/resources/aws/messaging/index.d.ts +5 -0
  159. package/dist/lib/resources/aws/messaging/index.js +2 -0
  160. package/dist/lib/resources/aws/messaging/schedule.d.ts +118 -0
  161. package/dist/lib/resources/aws/messaging/schedule.js +64 -0
  162. package/dist/lib/resources/aws/messaging/sns.d.ts +2 -1
  163. package/dist/lib/resources/aws/messaging/sqs.d.ts +2 -1
  164. package/dist/lib/resources/aws/messaging/subscription.d.ts +112 -0
  165. package/dist/lib/resources/aws/messaging/subscription.js +67 -0
  166. package/dist/lib/resources/aws/messaging/utils.d.ts +6 -0
  167. package/dist/lib/resources/aws/messaging/utils.js +10 -0
  168. package/dist/lib/resources/aws/monitoring/clickhouseAlarms.d.ts +60 -0
  169. package/dist/lib/resources/aws/monitoring/clickhouseAlarms.js +139 -0
  170. package/dist/lib/resources/aws/monitoring/index.d.ts +2 -0
  171. package/dist/lib/resources/aws/monitoring/index.js +2 -0
  172. package/dist/lib/resources/aws/monitoring/scheduleAlarms.d.ts +47 -0
  173. package/dist/lib/resources/aws/monitoring/scheduleAlarms.js +106 -0
  174. package/dist/lib/resources/aws/networking/crossAccountDelegationRecord.js +6 -3
  175. package/dist/lib/resources/aws/networking/crossAccountReturnRoutes.d.ts +40 -0
  176. package/dist/lib/resources/aws/networking/crossAccountReturnRoutes.js +158 -0
  177. package/dist/lib/resources/aws/networking/dnsRecord/dnsRecordBase.js +7 -4
  178. package/dist/lib/resources/aws/networking/domainCertificate.d.ts +2 -2
  179. package/dist/lib/resources/aws/networking/domainCertificate.js +6 -3
  180. package/dist/lib/resources/aws/networking/hostedZone.js +6 -4
  181. package/dist/lib/resources/aws/networking/index.d.ts +3 -0
  182. package/dist/lib/resources/aws/networking/index.js +3 -0
  183. package/dist/lib/resources/aws/networking/serviceDiscovery.d.ts +96 -0
  184. package/dist/lib/resources/aws/networking/serviceDiscovery.js +96 -0
  185. package/dist/lib/resources/aws/networking/vpc.d.ts +4 -1
  186. package/dist/lib/resources/aws/networking/vpc.js +10 -3
  187. package/dist/lib/resources/aws/networking/vpcPeeringAccepterRole.d.ts +18 -0
  188. package/dist/lib/resources/aws/networking/vpcPeeringAccepterRole.js +61 -0
  189. package/dist/lib/resources/aws/networking/vpcPeeringConnection.d.ts +49 -0
  190. package/dist/lib/resources/aws/networking/vpcPeeringConnection.js +106 -0
  191. package/dist/lib/resources/aws/organisation/costAllocationTagActivator.d.ts +16 -5
  192. package/dist/lib/resources/aws/organisation/costAllocationTagActivator.js +17 -3
  193. package/dist/lib/resources/aws/organisation/index.d.ts +1 -1
  194. package/dist/lib/resources/aws/organisation/organisationPolicy.d.ts +2 -0
  195. package/dist/lib/resources/aws/organisation/organisationPolicy.js +3 -2
  196. package/dist/lib/resources/aws/secrets/secret.d.ts +7 -0
  197. package/dist/lib/resources/aws/secrets/secret.js +4 -3
  198. package/dist/lib/resources/aws/storage/bucketDeployment.d.ts +16 -0
  199. package/dist/lib/resources/aws/storage/bucketDeployment.js +17 -0
  200. package/dist/lib/resources/aws/storage/ecr.js +5 -5
  201. package/dist/lib/resources/aws/storage/index.d.ts +1 -0
  202. package/dist/lib/resources/aws/storage/index.js +1 -0
  203. package/dist/lib/resources/aws/storage/s3.js +10 -3
  204. package/dist/lib/resources/aws/utilities/customResource.js +18 -9
  205. package/dist/lib/synth_dump.d.ts +1 -0
  206. package/dist/lib/synth_dump.js +42 -0
  207. package/dist/lib/utils/bastionFactory.d.ts +10 -0
  208. package/dist/lib/utils/bastionFactory.js +29 -0
  209. package/dist/lib/utils/capitaliseString.d.ts +1 -1
  210. package/dist/lib/utils/capitaliseString.js +1 -1
  211. package/dist/lib/utils/cdkContext.d.ts +10 -0
  212. package/dist/lib/utils/cdkContext.js +13 -0
  213. package/dist/lib/utils/connections.d.ts +7 -1
  214. package/dist/lib/utils/connections.js +21 -0
  215. package/dist/lib/utils/connector.d.ts +30 -2
  216. package/dist/lib/utils/connector.js +6 -1
  217. package/dist/lib/utils/costAllocationTags.d.ts +15 -0
  218. package/dist/lib/utils/costAllocationTags.js +16 -0
  219. package/dist/lib/utils/databaseTypes.d.ts +14 -0
  220. package/dist/lib/utils/getConfig.d.ts +2 -0
  221. package/dist/lib/utils/getConfig.js +2 -0
  222. package/dist/lib/utils/index.d.ts +4 -0
  223. package/dist/lib/utils/index.js +4 -0
  224. package/dist/lib/utils/manifestWriter.d.ts +6 -89
  225. package/dist/lib/utils/manifestWriter.js +36 -23
  226. package/dist/lib/utils/migrationVersionResolvers.d.ts +2 -0
  227. package/dist/lib/utils/migrationVersionResolvers.js +2 -0
  228. package/dist/lib/utils/orgConfigParser.js +2 -1
  229. package/dist/lib/utils/resolveAlertsTopic.d.ts +14 -0
  230. package/dist/lib/utils/resolveAlertsTopic.js +30 -0
  231. package/dist/lib/utils/validationLogger.js +6 -3
  232. package/dist/lib/utils/vpcPeerInterface.d.ts +22 -0
  233. package/dist/lib/utils/vpcPeerInterface.js +1 -0
  234. package/package.json +22 -18
package/dist/lib/app.js CHANGED
@@ -1,10 +1,13 @@
1
1
  import { App as CdkApp, Aspects, Tags } from "aws-cdk-lib";
2
+ import { maskSensitiveOutput } from "@fjall/util";
2
3
  import { Vpc } from "./resources/aws/networking/vpc.js";
3
- import { CfnOutput } from "aws-cdk-lib";
4
- import { Ec2Instance } from "./resources/aws/compute/ec2.js";
4
+ import { createBastion } from "./patterns/aws/bastionFactory.js";
5
5
  import { AwsStack } from "./resources/index.js";
6
6
  import { EcrFactory } from "./resources/aws/storage/ecr.js";
7
7
  import { NetworkFactory } from "./patterns/aws/network.js";
8
+ import { MessagingFactory } from "./patterns/aws/messaging.js";
9
+ import { Schedule } from "./resources/aws/messaging/schedule.js";
10
+ import { ServiceDiscoveryNamespace } from "./resources/aws/networking/serviceDiscovery.js";
8
11
  import { StandardTagsAspect } from "./utils/standardTagsAspect.js";
9
12
  import { BACKUP_TIER_TAG_KEY, BACKUP_TIER_TAG_MAP } from "./utils/backupTierMapping.js";
10
13
  import { randomBytes } from "crypto";
@@ -14,8 +17,7 @@ import { FJALL_AUDIT_CONFIG } from "./config/audit.js";
14
17
  import { FjallLogger } from "./utils/validationLogger.js";
15
18
  import { getManifestCollector, writeManifest } from "./utils/manifestWriter.js";
16
19
  import { toPascalCase, toKebab } from "./utils/capitaliseString.js";
17
- const COST_ALLOCATION_ENVIRONMENT_TAG = "fjall:costAllocation:environment";
18
- const COST_ALLOCATION_SERVICE_TAG = "fjall:costAllocation:service";
20
+ import { COST_ALLOCATION_TAGS } from "./utils/costAllocationTags.js";
19
21
  /**
20
22
  * The basic corner-stone of all Fjall-hosted applications.
21
23
  * This class is a singleton and should be used to create and manage
@@ -30,6 +32,9 @@ export class App extends CdkApp {
30
32
  vpc;
31
33
  additionalVpcs = new Map();
32
34
  defaultEcr;
35
+ defaultEventBus;
36
+ eventBusOverride;
37
+ defaultNamespace;
33
38
  defaultAuditRole;
34
39
  auditRoleExternalId;
35
40
  bastion;
@@ -61,49 +66,20 @@ export class App extends CdkApp {
61
66
  if (options?.tunnel) {
62
67
  this.initialiseTunnel(options.tunnel);
63
68
  }
69
+ if (options?.eventBus !== undefined) {
70
+ this.eventBusOverride = options.eventBus;
71
+ }
64
72
  }
65
- /**
66
- * Apply backup tier tag to all resources in the app.
67
- * Maps tier names to AWS Backup plan tag values.
68
- */
69
73
  applyBackupTag(tier) {
70
74
  this.globalTags[BACKUP_TIER_TAG_KEY] = BACKUP_TIER_TAG_MAP[tier];
71
75
  }
72
- /**
73
- * Initialise the tunnel bastion in the network stack.
74
- * Creates a minimal EC2 instance for SSM port forwarding to databases.
75
- */
76
76
  initialiseTunnel(config) {
77
77
  if (this.networkDisabled || !this.vpc) {
78
78
  throw new Error("Tunnel requires a network. Configure network before enabling tunnel.");
79
79
  }
80
- const instanceType = typeof config === "object" && config.instanceType
81
- ? config.instanceType
82
- : "t4g.micro";
83
- const networkStack = this.getDefaultNetworkStack();
84
- const bastionId = `${this.stackPrefix}Bastion`;
85
- this.bastion = new Ec2Instance(networkStack.getStack(), bastionId, {
86
- serviceName: `${this.stackPrefix}Bastion`,
87
- instanceType,
88
- vpc: this.vpc,
89
- enableSSH: false,
90
- minCapacity: 1,
91
- maxCapacity: 1
92
- });
93
- networkStack.addConstruct(this.bastion);
94
- const outputPrefix = toPascalCase(this.name);
95
- new CfnOutput(networkStack.getStack(), `${outputPrefix}BastionInstanceId`, {
96
- value: this.bastion.getAutoScalingGroup().autoScalingGroupName,
97
- description: "Bastion ASG name for SSM tunnel discovery"
98
- });
99
- new CfnOutput(networkStack.getStack(), `${outputPrefix}BastionSecurityGroupId`, {
100
- value: this.bastion.asgSecurityGroup.securityGroupId,
101
- description: "Bastion security group ID"
102
- });
80
+ const { bastion } = createBastion(this.getDefaultNetworkStack(), this.name, this.stackPrefix, this.vpc, config);
81
+ this.bastion = bastion;
103
82
  }
104
- /**
105
- * Initialise the network (VPC) for this application.
106
- */
107
83
  initialiseNetwork(config) {
108
84
  const networkStack = this.getDefaultNetworkStack();
109
85
  if ("useExisting" in config) {
@@ -117,45 +93,12 @@ export class App extends CdkApp {
117
93
  this.vpc = network.getVpc();
118
94
  }
119
95
  }
120
- /**
121
- * Get the application name.
122
- * @returns {string} The application name
123
- */
124
96
  getName() {
125
97
  return this.name;
126
98
  }
127
- /**
128
- * Get/Create a basic Fjall Application with standard tags applied.
129
- *
130
- * @param name Application name
131
- * @param options Configuration options including network settings
132
- * @returns {App}
133
- *
134
- * @example
135
- * // Create app with new VPC
136
- * const app = App.getApp(appName, {
137
- * network: { maxAzs: 2, natGateways: false }
138
- * });
139
- *
140
- * @example
141
- * // Create app using existing VPC
142
- * const app = App.getApp(appName, {
143
- * network: { useExisting: "vpc-12345678" }
144
- * });
145
- *
146
- * @example
147
- * // Create app without network (S3-only apps)
148
- * const app = App.getApp(appName, { network: false });
149
- */
150
99
  static getApp(name, options) {
151
100
  return App.getInstance(name, options);
152
101
  }
153
- /**
154
- * Get/Create the singleton instance of the App
155
- * @param name Application name
156
- * @param options Configuration options including network settings
157
- * @returns {App}
158
- */
159
102
  static getInstance(name, options) {
160
103
  // Despite supporting multiple stacks you can still only ever
161
104
  // have a single Application per CDK deployment
@@ -195,16 +138,31 @@ export class App extends CdkApp {
195
138
  if (options?.tunnel && !App.instance.bastion) {
196
139
  App.instance.initialiseTunnel(options.tunnel);
197
140
  }
141
+ if (options?.eventBus !== undefined) {
142
+ if (App.instance.eventBusOverride === undefined &&
143
+ App.instance.defaultEventBus === undefined) {
144
+ App.instance.eventBusOverride = options.eventBus;
145
+ }
146
+ else {
147
+ const reason = App.instance.defaultEventBus !== undefined
148
+ ? "bus was already materialised via getEventBus()"
149
+ : "override was already set on a prior App.getApp() call";
150
+ FjallLogger.warn(`App.getApp() eventBus override ignored: ${reason}. ` +
151
+ `Pass eventBus options to the first App.getApp() call.`);
152
+ }
153
+ }
198
154
  }
199
155
  return App.instance;
200
156
  }
157
+ static resetForTesting() {
158
+ App.instance = null;
159
+ }
201
160
  /**
202
161
  * Retrieve a stack by key. If the stack does not exist, it will be created.
203
162
  * Dependencies are only applied the first time a stack is created.
204
163
  *
205
164
  * @param key - The key of the stack
206
165
  * @param dependencies - The stack(s) that this stack depends on
207
- * @returns {AwsStack}
208
166
  */
209
167
  getStack(key, dependencies) {
210
168
  // Apply the aspect once before creating the first stack
@@ -223,29 +181,24 @@ export class App extends CdkApp {
223
181
  *
224
182
  * Only depends on Network. Database dependency is added automatically
225
183
  * by CDK when compute resources reference database resources.
226
- *
227
- * @returns {AwsStack}
228
184
  */
229
185
  getDefaultComputeStack() {
230
186
  return this.getStack(`${this.stackPrefix}Compute`, this.getDefaultNetworkStack());
231
187
  }
232
188
  /**
233
189
  * Retrieve default network stack - named as `${this.name}Network`
234
- * @returns {AwsStack}
235
190
  */
236
191
  getDefaultNetworkStack() {
237
192
  return this.getStack(`${this.stackPrefix}Network`);
238
193
  }
239
194
  /**
240
195
  * Retrieve default database stack - named as `${this.name}Database`
241
- * @returns {AwsStack}
242
196
  */
243
197
  getDefaultDatabaseStack() {
244
198
  return this.getStack(`${this.stackPrefix}Database`, this.getDefaultNetworkStack());
245
199
  }
246
200
  /**
247
201
  * Retrieve default storage stack - named as `${this.name}Storage`
248
- * @returns {AwsStack}
249
202
  */
250
203
  getDefaultStorageStack() {
251
204
  return this.getStack(`${this.stackPrefix}Storage`, this.getDefaultNetworkStack());
@@ -255,8 +208,6 @@ export class App extends CdkApp {
255
208
  *
256
209
  * Depends on Network. Compute/Storage dependencies are added automatically
257
210
  * by CDK when CDN resources reference ALB or S3 bucket resources.
258
- *
259
- * @returns {AwsStack}
260
211
  */
261
212
  getDefaultCdnStack() {
262
213
  return this.getStack(`${this.stackPrefix}Cdn`, this.getDefaultNetworkStack());
@@ -267,8 +218,6 @@ export class App extends CdkApp {
267
218
  * Used for SQS queues, SNS topics, and EventBridge event buses.
268
219
  * Depends on Network only. These are regional services that don't
269
220
  * require VPC, but we maintain consistent stack dependency patterns.
270
- *
271
- * @returns {AwsStack}
272
221
  */
273
222
  getDefaultMessagingStack() {
274
223
  return this.getStack(`${this.stackPrefix}Messaging`, this.getDefaultNetworkStack());
@@ -280,7 +229,6 @@ export class App extends CdkApp {
280
229
  * Network must be configured via App.getApp() options or app.addNetwork().
281
230
  *
282
231
  * @param name - Optional name of the VPC to retrieve. If not provided, returns the default VPC.
283
- * @returns {IVpc} The configured VPC
284
232
  * @throws {Error} If network is disabled, not configured, or named VPC not found
285
233
  */
286
234
  getVpc(name) {
@@ -304,11 +252,6 @@ export class App extends CdkApp {
304
252
  }
305
253
  return this.vpc;
306
254
  }
307
- /**
308
- * Get the names of all available VPCs.
309
- *
310
- * @returns {string[]} Array of VPC names. Includes "default" if the default VPC is configured.
311
- */
312
255
  getVpcNames() {
313
256
  const names = [];
314
257
  if (this.vpc) {
@@ -317,10 +260,6 @@ export class App extends CdkApp {
317
260
  names.push(...this.additionalVpcs.keys());
318
261
  return names;
319
262
  }
320
- /**
321
- * Retrieve the default application container registry. If the registry does not exist
322
- * it will be created.
323
- */
324
263
  getDefaultContainerRegistry() {
325
264
  if (!this.defaultEcr) {
326
265
  const networkStack = this.getDefaultNetworkStack();
@@ -332,6 +271,67 @@ export class App extends CdkApp {
332
271
  }
333
272
  return this.defaultEcr;
334
273
  }
274
+ /**
275
+ * Lazy getter for the per-app default custom EventBridge bus (D2).
276
+ *
277
+ * Buses are recreatable in non-prod; the env-resolved default keeps prod
278
+ * history. The override (`App.getApp({ eventBus: { name?, removalPolicy? } })`)
279
+ * is consulted first; absent override falls back to the app name and the
280
+ * `env({ default: "DESTROY", production: "RETAIN" })` resolution per D17.
281
+ * NODE_ENV is not consulted — it is not set during CDK synth in Fjall's
282
+ * deployment paths.
283
+ */
284
+ getEventBus() {
285
+ if (this.defaultEventBus) {
286
+ return this.defaultEventBus;
287
+ }
288
+ const eventBusName = this.eventBusOverride?.name ?? this.getName();
289
+ const removalPolicy = this.eventBusOverride?.removalPolicy;
290
+ const bus = this.addMessaging(MessagingFactory.build(`${this.stackPrefix}EventBus`, {
291
+ type: "eventBus",
292
+ eventBusName,
293
+ appName: this.name,
294
+ removalPolicy
295
+ }));
296
+ this.defaultEventBus = bus;
297
+ return bus;
298
+ }
299
+ /**
300
+ * Lazy getter for the per-app Cloud Map private DNS namespace (D7 + D29 of
301
+ * the ClickHouse Database Factory promotion design).
302
+ *
303
+ * The namespace is constructed in the network stack on first call and
304
+ * reused thereafter — `app.getNamespace() === app.getNamespace()`. Default
305
+ * name is `${toKebab(appName)}.local` per the implementation-defined
306
+ * derivation rule; v1 has no override config option (D29). Returns the
307
+ * `IPrivateDnsNamespace` interface per D18(a), never the concrete class.
308
+ */
309
+ getNamespace() {
310
+ return this.ensureNamespace().getNamespace();
311
+ }
312
+ /**
313
+ * Register a Cloud Map service against the per-app namespace. Lazily creates
314
+ * the namespace on first call (same construct as `getNamespace()`) and
315
+ * delegates to the `ServiceDiscoveryNamespace` wrapper's `registerService`
316
+ * — keeping both halves of Cloud Map (namespace + services) routed through
317
+ * the wrapper layer per § Wrapper Routing Discipline.
318
+ */
319
+ registerService(props) {
320
+ return this.ensureNamespace().registerService(props);
321
+ }
322
+ ensureNamespace() {
323
+ if (this.defaultNamespace) {
324
+ return this.defaultNamespace;
325
+ }
326
+ const networkStack = this.getDefaultNetworkStack();
327
+ const namespace = new ServiceDiscoveryNamespace(networkStack.getStack(), `${this.stackPrefix}Namespace`, {
328
+ vpc: this.getVpc(),
329
+ name: `${toKebab(this.name)}.local`
330
+ });
331
+ networkStack.addConstruct(namespace);
332
+ this.defaultNamespace = namespace;
333
+ return namespace;
334
+ }
335
335
  /**
336
336
  * Create a cross-account audit role in the Network stack that allows
337
337
  * the Fjall platform to use CloudQuery for comprehensive AWS resource auditing.
@@ -341,7 +341,6 @@ export class App extends CdkApp {
341
341
  *
342
342
  * @param webappAccountId - Optional AWS account ID of the Fjall webapp. Defaults to configured platform account.
343
343
  * @param externalId - Optional external ID for additional security. If not provided, a unique ID will be generated.
344
- * @returns {Role} The created audit role
345
344
  */
346
345
  createAuditRole(webappAccountId, externalId) {
347
346
  if (!this.defaultAuditRole) {
@@ -361,17 +360,9 @@ export class App extends CdkApp {
361
360
  }
362
361
  return this.defaultAuditRole;
363
362
  }
364
- /**
365
- * Get the external ID used for the audit role
366
- * @returns {string | undefined} The external ID if audit role has been created
367
- */
368
363
  getAuditRoleExternalId() {
369
364
  return this.auditRoleExternalId;
370
365
  }
371
- /**
372
- * Generate a unique external ID for audit role
373
- * Format: fjall-audit-{appName}-{timestamp}
374
- */
375
366
  generateAuditExternalId() {
376
367
  const uniqueId = randomBytes(8).toString("hex");
377
368
  return `fjall-audit-${toKebab(this.name)}-${uniqueId}`;
@@ -406,9 +397,6 @@ export class App extends CdkApp {
406
397
  computeStack.addConstruct(construct);
407
398
  return construct;
408
399
  }
409
- /**
410
- * Manually add a resource to the default compute stack.
411
- */
412
400
  addComputeResource(resource) {
413
401
  const computeStack = this.getDefaultComputeStack();
414
402
  computeStack.addConstruct(resource);
@@ -443,9 +431,6 @@ export class App extends CdkApp {
443
431
  }
444
432
  return databaseConstruct;
445
433
  }
446
- /**
447
- * Type guard for IConnectable — checks if a construct has a connections property.
448
- */
449
434
  isConnectable(construct) {
450
435
  return (typeof construct === "object" &&
451
436
  construct !== null &&
@@ -509,6 +494,32 @@ export class App extends CdkApp {
509
494
  cdnStack.addConstruct(cdn);
510
495
  return cdn;
511
496
  }
497
+ /**
498
+ * Peer this app's VPC with a remote app's VPC.
499
+ *
500
+ * Creates the peering connection plus routes on both sides. The remote app
501
+ * must have deployed a `VpcPeerAccepter` first. Note: `app.getVpc(peerAppName)`
502
+ * does NOT return the peer's VPC — callers wanting the remote handle must use
503
+ * the returned `VpcPeer` instance.
504
+ */
505
+ addVpcPeer(fn) {
506
+ const networkStack = this.getDefaultNetworkStack();
507
+ const peer = fn(this, networkStack.getStack());
508
+ networkStack.addConstruct(peer);
509
+ return peer;
510
+ }
511
+ /**
512
+ * Accept VPC peering requests from remote apps.
513
+ *
514
+ * Creates an IAM role for cross-account peering acceptance and return-route
515
+ * management, and publishes VPC metadata to SSM for discovery.
516
+ */
517
+ addVpcPeerAccepter(fn) {
518
+ const networkStack = this.getDefaultNetworkStack();
519
+ const accepter = fn(this, networkStack.getStack());
520
+ networkStack.addConstruct(accepter);
521
+ return accepter;
522
+ }
512
523
  /**
513
524
  * Add a messaging resource to the default queue stack using the factory pattern.
514
525
  *
@@ -540,6 +551,32 @@ export class App extends CdkApp {
540
551
  messagingStack.addConstruct(messaging);
541
552
  return messaging;
542
553
  }
554
+ /**
555
+ * Register an EventBridge schedule against a Fjall wrapper target.
556
+ *
557
+ * Defaults to the messaging stack; set `props.stackPlacement = "compute"`
558
+ * when the schedule's target lives in the compute stack and cross-stack
559
+ * output churn is undesired. `applicationId` is threaded automatically
560
+ * from `app.getName()` for alarm webhook routing per D13.
561
+ *
562
+ * @example
563
+ * app.addSchedule("MetricsCollection", {
564
+ * schedule: "rate(5 minutes)",
565
+ * target: notificationsQueue
566
+ * });
567
+ */
568
+ addSchedule(id, props) {
569
+ const stack = props.stackPlacement === "compute"
570
+ ? this.getDefaultComputeStack()
571
+ : this.getDefaultMessagingStack();
572
+ const schedule = new Schedule(stack.getStack(), id, {
573
+ ...props,
574
+ applicationId: this.getName(),
575
+ appName: props.appName ?? this.getName()
576
+ });
577
+ stack.addConstruct(schedule);
578
+ return schedule;
579
+ }
543
580
  /**
544
581
  * Add a high-level infrastructure pattern to the application.
545
582
  *
@@ -580,7 +617,6 @@ export class App extends CdkApp {
580
617
  * Additional VPCs can be retrieved by name using app.getVpc(name).
581
618
  *
582
619
  * @param fn - Factory function that creates the Network construct
583
- * @returns {Network} The created Network construct
584
620
  *
585
621
  * @example
586
622
  * const isolatedVpc = app.addNetwork(
@@ -596,33 +632,19 @@ export class App extends CdkApp {
596
632
  networkStack.addConstruct(network);
597
633
  return network;
598
634
  }
599
- /**
600
- * Manually add a resource to the default database stack.
601
- */
602
635
  addDatabaseResource(resource) {
603
636
  const databaseStack = this.getDefaultDatabaseStack();
604
637
  databaseStack.addConstruct(resource);
605
638
  }
606
- /**
607
- * Manually add a resource to the default storage stack.
608
- */
609
639
  addStorageResource(resource) {
610
640
  const storageStack = this.getDefaultStorageStack();
611
641
  storageStack.addConstruct(resource);
612
642
  }
613
- /**
614
- * Initialise standard tags
615
- */
616
643
  initialiseStandardTags() {
617
644
  const config = getConfig();
618
- this.globalTags = {
619
- [COST_ALLOCATION_ENVIRONMENT_TAG]: config.environment,
620
- [COST_ALLOCATION_SERVICE_TAG]: this.name
621
- };
645
+ this.globalTags[COST_ALLOCATION_TAGS.ENVIRONMENT] = config.environment;
646
+ this.globalTags[COST_ALLOCATION_TAGS.SERVICE] = this.name;
622
647
  }
623
- /**
624
- * Apply all tags using CDK's native Tags.of().add() API
625
- */
626
648
  applyTagsAspect() {
627
649
  if (!this.aspectApplied && Object.keys(this.globalTags).length > 0) {
628
650
  // Apply standard tags using Tags.of(this).add()
@@ -641,7 +663,7 @@ export class App extends CdkApp {
641
663
  * @example
642
664
  * app.addTags({
643
665
  * "fjall:costAllocation:owner": "platform-team",
644
- * "fjall:costAllocation:cost-center": "CC-123",
666
+ * "fjall:costAllocation:cost-centre": "CC-123",
645
667
  * "team:slack-channel": "#platform-alerts"
646
668
  * });
647
669
  */
@@ -656,11 +678,7 @@ export class App extends CdkApp {
656
678
  }
657
679
  return this;
658
680
  }
659
- /**
660
- * Export resource inventory collected during synthesis
661
- * Call this after app.synth() to get complete resource inventory
662
- * @returns {ResourceInventory} Complete inventory of all resources in the app
663
- */
681
+ /** Call after app.synth() — inventory is not available before synthesis. */
664
682
  exportResourceInventory() {
665
683
  if (!this.resourceInventory) {
666
684
  throw new Error("Resource inventory not available. Ensure a ResourceInventoryAspect has been added before calling exportResourceInventory().");
@@ -671,16 +689,9 @@ export class App extends CdkApp {
671
689
  appName: this.name
672
690
  };
673
691
  }
674
- /**
675
- * Get the manifest collector for registering services and patterns.
676
- * Used by ComputeFactory and PatternFactory to register their configurations.
677
- */
678
692
  getManifestCollector() {
679
693
  return this.manifestCollector;
680
694
  }
681
- /**
682
- * Override synth to automatically export resource inventory and manifest
683
- */
684
695
  synth(options) {
685
696
  // Call parent synth first
686
697
  const assembly = super.synth(options);
@@ -689,9 +700,8 @@ export class App extends CdkApp {
689
700
  writeManifest(assembly, this.manifestCollector);
690
701
  }
691
702
  catch (error) {
692
- // Don't fail synth if manifest export fails
693
- const errorMessage = error instanceof Error ? error.message : String(error);
694
- FjallLogger.warn(`Failed to export Fjall manifest: ${errorMessage}`);
703
+ const maskedMessage = maskSensitiveOutput(error instanceof Error ? error.message : String(error));
704
+ FjallLogger.warn(`Failed to export Fjall manifest: ${maskedMessage}`);
695
705
  }
696
706
  return assembly;
697
707
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import { Rule } from "aws-cdk-lib/aws-events";
2
+ import { LambdaFunction } from "aws-cdk-lib/aws-events-targets";
3
+ console.log(Rule, LambdaFunction);
@@ -0,0 +1,2 @@
1
+ import { type IRule } from "aws-cdk-lib/aws-events";
2
+ export type T = IRule;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,18 +1,22 @@
1
1
  import { CfnOutput } from "aws-cdk-lib";
2
- import * as sns from "aws-cdk-lib/aws-sns";
3
2
  import { Construct } from "constructs";
3
+ import { SNSTopic } from "../../resources/aws/messaging/sns.js";
4
4
  export class SharedAlarmTopic extends Construct {
5
5
  topic;
6
6
  topicArn;
7
7
  constructor(scope, id) {
8
8
  super(scope, id);
9
- const topic = new sns.Topic(this, "AlarmNotifications", {
9
+ const wrapped = new SNSTopic(this, "AlarmNotifications", {
10
10
  displayName: "Fjall CloudWatch Alarm Notifications"
11
11
  });
12
- this.topic = topic;
12
+ this.topic = wrapped.getTopic();
13
+ // SharedAlarmTopicArn is a well-known cross-stack export consumed via
14
+ // Fn.importValue (see resolveAlertsTopic + its tests). Do not delete
15
+ // thinking it duplicates the wrapper's AlarmNotificationsTopicArn —
16
+ // the wrapper's auto-output has no exportName and cannot be imported.
13
17
  this.topicArn = new CfnOutput(this, "SharedAlarmTopicArn", {
14
18
  key: "SharedAlarmTopicArn",
15
- value: topic.topicArn,
19
+ value: wrapped.getTopicArn(),
16
20
  exportName: "SharedAlarmTopicArn"
17
21
  });
18
22
  }
@@ -3,7 +3,7 @@ import { Trail } from "../../resources/aws/logging/cloudTrail.js";
3
3
  export class ManagementEventsTrail extends Construct {
4
4
  constructor(scope, id, props) {
5
5
  super(scope, id);
6
- new Trail(this, "managementEventsTrail", {
6
+ new Trail(this, "ManagementEventsTrail", {
7
7
  bucketName: `cloudtrail-management-events-${props.accountId}-${props.region}`,
8
8
  trailName: "managementEvents",
9
9
  isMultiRegionTrail: true
@@ -2,10 +2,10 @@ import { CfnOutput, Duration, RemovalPolicy } from "aws-cdk-lib";
2
2
  import { Construct } from "constructs";
3
3
  import { BackupVault, BackupPlan } from "../../resources/aws/backup/index.js";
4
4
  import { BackupPlanRule, BackupVault as Vault } from "aws-cdk-lib/aws-backup";
5
- import * as events from "aws-cdk-lib/aws-events";
5
+ import { cronSchedule } from "../../resources/aws/messaging/index.js";
6
6
  import { AccountPrincipal, Effect, PolicyStatement } from "aws-cdk-lib/aws-iam";
7
- import App from "../../app.js";
8
- import { parseOrgConfig } from "../../utils/orgConfigParser.js";
7
+ import { getConfig } from "../../utils/getConfig.js";
8
+ import { toPascalCase } from "../../utils/capitaliseString.js";
9
9
  // Backup retention constants (in days)
10
10
  const RETENTION_PERIODS = {
11
11
  STANDARD: 90,
@@ -34,16 +34,11 @@ export class DisasterRecovery extends Construct {
34
34
  customBackupPlans;
35
35
  constructor(scope, id, props) {
36
36
  super(scope, id);
37
- // Read org config from CDK context
38
- const app = App.getInstance();
39
- const orgConfigRaw = app.node.tryGetContext("orgConfig");
40
- const orgConfig = parseOrgConfig(typeof orgConfigRaw === "string" ? orgConfigRaw : undefined);
41
- const providerAccounts = orgConfig.providerAccounts;
42
- // Determine if this is a compliance account
37
+ const config = getConfig();
38
+ const providerAccounts = config.providerAccounts;
43
39
  const account = providerAccounts.find((pa) => pa.id === props.accountId);
44
40
  const isComplianceAccount = account?.environment === "compliance";
45
- // Get DR configuration
46
- const disasterRecoveryRegion = orgConfig.disasterRecoveryRegion;
41
+ const disasterRecoveryRegion = config.disasterRecoveryRegion;
47
42
  // Look up compliance account for cross-account replication
48
43
  // Skip if the compliance account (prevent self-replication)
49
44
  const disasterRecoveryAccount = isComplianceAccount
@@ -110,7 +105,7 @@ export class DisasterRecovery extends Construct {
110
105
  // Create custom backup plans if provided
111
106
  if (props.customBackupPlans && props.customBackupPlans.length > 0) {
112
107
  this.customBackupPlans = props.customBackupPlans.map((config) => {
113
- return new BackupPlan(this, `CustomBackupPlan-${config.planName}`, {
108
+ return new BackupPlan(this, `CustomBackupPlan${toPascalCase(config.planName)}`, {
114
109
  planName: config.planName,
115
110
  rules: config.rules,
116
111
  tagValue: config.tagValue,
@@ -143,7 +138,7 @@ export class DisasterRecovery extends Construct {
143
138
  return [
144
139
  new BackupPlanRule({
145
140
  ruleName: `${planName}Daily`,
146
- scheduleExpression: events.Schedule.cron({ hour: "2", minute: "0" }), // 2 AM daily
141
+ scheduleExpression: cronSchedule({ hour: "2", minute: "0" }), // 2 AM daily
147
142
  deleteAfter: Duration.days(RETENTION_PERIODS.STANDARD),
148
143
  startWindow: BACKUP_WINDOWS.START,
149
144
  completionWindow: BACKUP_WINDOWS.COMPLETION
@@ -155,7 +150,7 @@ export class DisasterRecovery extends Construct {
155
150
  return [
156
151
  new BackupPlanRule({
157
152
  ruleName: `${planName}Daily`,
158
- scheduleExpression: events.Schedule.cron({ hour: "2", minute: "0" }), // 2 AM daily
153
+ scheduleExpression: cronSchedule({ hour: "2", minute: "0" }), // 2 AM daily
159
154
  deleteAfter: Duration.days(RETENTION_PERIODS.ENTERPRISE_CONTINUOUS),
160
155
  enableContinuousBackup: true,
161
156
  startWindow: BACKUP_WINDOWS.START,
@@ -171,7 +166,7 @@ export class DisasterRecovery extends Construct {
171
166
  // Continuous backup (35-day max PITR window)
172
167
  new BackupPlanRule({
173
168
  ruleName: `${planName}Continuous`,
174
- scheduleExpression: events.Schedule.cron({ hour: "2", minute: "0" }), // Daily for continuous backup
169
+ scheduleExpression: cronSchedule({ hour: "2", minute: "0" }), // Daily for continuous backup
175
170
  deleteAfter: Duration.days(RETENTION_PERIODS.ENTERPRISE_CONTINUOUS),
176
171
  enableContinuousBackup: true,
177
172
  startWindow: BACKUP_WINDOWS.START,
@@ -181,7 +176,7 @@ export class DisasterRecovery extends Construct {
181
176
  // Hourly snapshots for long-term compliance (7 years)
182
177
  new BackupPlanRule({
183
178
  ruleName: `${planName}HourlyCompliance`,
184
- scheduleExpression: events.Schedule.cron({ minute: "0" }), // Every hour
179
+ scheduleExpression: cronSchedule({ minute: "0" }), // Every hour
185
180
  deleteAfter: Duration.days(RETENTION_PERIODS.ENTERPRISE_COMPLIANCE),
186
181
  moveToColdStorageAfter: Duration.days(RETENTION_PERIODS.COLD_STORAGE_ONE_YEAR),
187
182
  startWindow: BACKUP_WINDOWS.START,
@@ -3,7 +3,6 @@ import { type StackProps } from "aws-cdk-lib";
3
3
  interface EcrDefaultImageProps extends StackProps {
4
4
  region: string;
5
5
  accountId: string;
6
- eventBusArn: string;
7
6
  }
8
7
  export declare class EcrDefaultImage extends Construct {
9
8
  constructor(scope: Construct, id: string, props: EcrDefaultImageProps);