@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
@@ -1,21 +1,37 @@
1
- import { SQSQueue } from "../../resources/aws/messaging/sqs.js";
1
+ import { EventBus as CdkEventBus } from "aws-cdk-lib/aws-events";
2
+ import { SQSQueue, SQS_LIMITS } from "../../resources/aws/messaging/sqs.js";
2
3
  import { SNSTopic } from "../../resources/aws/messaging/sns.js";
3
4
  import { EventBridgeBus } from "../../resources/aws/messaging/eventbridge.js";
5
+ import { Subscription } from "../../resources/aws/messaging/subscription.js";
4
6
  import { FjallLogger } from "../../utils/validationLogger.js";
5
7
  /**
6
8
  * Validates SQS props and logs warnings for misconfigured options.
7
9
  */
8
10
  function validateSQSProps(props) {
9
- // Validate visibility timeout range (0-43200 seconds = 12 hours)
10
11
  if (props.visibilityTimeout !== undefined &&
11
- (props.visibilityTimeout < 0 || props.visibilityTimeout > 43200)) {
12
- throw new Error("visibilityTimeout must be between 0 and 43200 seconds (12 hours)");
12
+ (props.visibilityTimeout < SQS_LIMITS.VISIBILITY_TIMEOUT.MIN_SECONDS ||
13
+ props.visibilityTimeout > SQS_LIMITS.VISIBILITY_TIMEOUT.MAX_SECONDS)) {
14
+ throw new Error(`visibilityTimeout must be between ${SQS_LIMITS.VISIBILITY_TIMEOUT.MIN_SECONDS} and ${SQS_LIMITS.VISIBILITY_TIMEOUT.MAX_SECONDS} seconds (12 hours)`);
13
15
  }
14
- // Validate message retention period (60-1209600 seconds = 1 minute to 14 days)
15
16
  if (props.messageRetentionPeriod !== undefined &&
16
- (props.messageRetentionPeriod < 60 ||
17
- props.messageRetentionPeriod > 1209600)) {
18
- throw new Error("messageRetentionPeriod must be between 60 and 1209600 seconds (1 minute to 14 days)");
17
+ (props.messageRetentionPeriod < SQS_LIMITS.MESSAGE_RETENTION.MIN_SECONDS ||
18
+ props.messageRetentionPeriod > SQS_LIMITS.MESSAGE_RETENTION.MAX_SECONDS)) {
19
+ throw new Error(`messageRetentionPeriod must be between ${SQS_LIMITS.MESSAGE_RETENTION.MIN_SECONDS} and ${SQS_LIMITS.MESSAGE_RETENTION.MAX_SECONDS} seconds (1 minute to 14 days)`);
20
+ }
21
+ if (props.deliveryDelay !== undefined &&
22
+ (props.deliveryDelay < SQS_LIMITS.DELAY.MIN_SECONDS ||
23
+ props.deliveryDelay > SQS_LIMITS.DELAY.MAX_SECONDS)) {
24
+ throw new Error(`deliveryDelay must be between ${SQS_LIMITS.DELAY.MIN_SECONDS} and ${SQS_LIMITS.DELAY.MAX_SECONDS} seconds (15 minutes)`);
25
+ }
26
+ if (props.receiveMessageWaitTime !== undefined &&
27
+ (props.receiveMessageWaitTime < SQS_LIMITS.RECEIVE_WAIT_TIME.MIN_SECONDS ||
28
+ props.receiveMessageWaitTime > SQS_LIMITS.RECEIVE_WAIT_TIME.MAX_SECONDS)) {
29
+ throw new Error(`receiveMessageWaitTime must be between ${SQS_LIMITS.RECEIVE_WAIT_TIME.MIN_SECONDS} and ${SQS_LIMITS.RECEIVE_WAIT_TIME.MAX_SECONDS} seconds (long-poll cap)`);
30
+ }
31
+ if (props.maxMessageSize !== undefined &&
32
+ (props.maxMessageSize < SQS_LIMITS.MESSAGE_SIZE.MIN_BYTES ||
33
+ props.maxMessageSize > SQS_LIMITS.MESSAGE_SIZE.MAX_BYTES)) {
34
+ throw new Error(`maxMessageSize must be between ${SQS_LIMITS.MESSAGE_SIZE.MIN_BYTES} and ${SQS_LIMITS.MESSAGE_SIZE.MAX_BYTES} bytes (256 KB)`);
19
35
  }
20
36
  // Warn about FIFO-specific options on standard queues
21
37
  if (props.queueType !== "fifo") {
@@ -58,6 +74,7 @@ export class QueueMessaging extends SQSQueue {
58
74
  /** The connector type for unified connection processing. */
59
75
  connectorType = "queue";
60
76
  constructor(scope, id, props) {
77
+ validateSQSProps(props);
61
78
  const queueProps = {
62
79
  queueType: props.queueType,
63
80
  visibilityTimeout: props.visibilityTimeout,
@@ -120,14 +137,8 @@ export class TopicMessaging extends SNSTopic {
120
137
  /** Type discriminator for runtime type narrowing. */
121
138
  messagingType = "topic";
122
139
  constructor(scope, id, props) {
123
- const topicProps = {
124
- topicName: props.topicName,
125
- displayName: props.displayName,
126
- fifo: props.fifo,
127
- contentBasedDeduplication: props.contentBasedDeduplication,
128
- removalPolicy: props.removalPolicy
129
- };
130
- super(scope, id, topicProps);
140
+ validateTopicProps(props);
141
+ super(scope, id, props);
131
142
  }
132
143
  /**
133
144
  * Grant publish permissions to the grantee.
@@ -151,12 +162,33 @@ export class TopicMessaging extends SNSTopic {
151
162
  export class EventBusMessaging extends EventBridgeBus {
152
163
  /** Type discriminator for runtime type narrowing. */
153
164
  messagingType = "eventBus";
165
+ /**
166
+ * Application name threaded into Subscription default descriptions when the
167
+ * caller does not supply one. Captured at construction so `subscribe(...)`
168
+ * has the same naming context as `App.addSchedule(...)`.
169
+ */
170
+ #appName;
171
+ /**
172
+ * Brand distinguishing app buses from the AWS-managed account+region default
173
+ * bus. Used by `subscribe(...)` to refuse `aws.*` source patterns on app
174
+ * buses (silent-no-op trap — AWS service events only fire on the default
175
+ * bus). Set by `fromAwsServiceBus(...)`; defaults to `false` for buses
176
+ * created via the regular constructor path or `fromEventBusArn(...)`.
177
+ */
178
+ #isAwsServiceBus;
154
179
  constructor(scope, id, props) {
155
180
  const eventBusProps = {
156
181
  eventBusName: props.eventBusName,
157
- removalPolicy: props.removalPolicy
182
+ appName: props.appName,
183
+ description: props.description,
184
+ removalPolicy: props.removalPolicy,
185
+ importedBus: props.importedBus
158
186
  };
159
187
  super(scope, id, eventBusProps);
188
+ if (props.appName !== undefined) {
189
+ this.#appName = props.appName;
190
+ }
191
+ this.#isAwsServiceBus = props.awsServiceBus === true;
160
192
  }
161
193
  /**
162
194
  * Grant put events permissions to the grantee.
@@ -165,6 +197,70 @@ export class EventBusMessaging extends EventBridgeBus {
165
197
  grantPutEventsTo(grantee) {
166
198
  return this.getEventBus().grantPutEventsTo(grantee);
167
199
  }
200
+ /**
201
+ * Add a pub/sub subscription scoped to this bus. Threads the bus's
202
+ * `IEventBus` and the captured `appName` into the Subscription so the
203
+ * synthesised rule attaches to this bus (not the default AWS bus) and the
204
+ * default description picks up the bus's app context.
205
+ *
206
+ * Refuses `aws.*` source patterns when the wrapper is an app bus rather
207
+ * than the AWS-managed default bus. AWS service events fire only on the
208
+ * account+region default bus; subscribing them on a custom app bus
209
+ * synthesises and deploys cleanly but never invokes the target. Use
210
+ * `EventBusMessaging.fromAwsServiceBus(...)` to import the default bus
211
+ * for AWS service event traffic.
212
+ */
213
+ subscribe(id, props) {
214
+ if (!this.#isAwsServiceBus) {
215
+ const sources = props.pattern.source ?? [];
216
+ const awsSources = sources.filter((s) => typeof s === "string" && s.startsWith("aws."));
217
+ if (awsSources.length > 0) {
218
+ throw new Error(`Subscription '${id}' uses AWS service source(s) [${awsSources.join(", ")}] on a custom app event bus. AWS service events fire only on the account+region default bus; subscribing them on a custom bus deploys cleanly but never invokes the target. Use EventBusMessaging.fromAwsServiceBus(scope, id, region, account) instead of app.getEventBus().`);
219
+ }
220
+ }
221
+ return new Subscription(this, id, {
222
+ ...props,
223
+ eventBus: this.getEventBus(),
224
+ appName: props.appName ?? this.#appName
225
+ });
226
+ }
227
+ /**
228
+ * Wrap a bus imported from another account/region by ARN per D19. The
229
+ * returned handle supports `subscribe(...)` identically to created buses;
230
+ * rules are owned by the importing stack and attach to the imported bus's
231
+ * ARN. The base wrapper short-circuits resource creation when `importedBus`
232
+ * is set, so no `AWS::Events::EventBus` is synthesised and bus-level
233
+ * mutations (description, removalPolicy, CfnOutputs) are skipped.
234
+ */
235
+ static fromEventBusArn(scope, id, arn) {
236
+ const importedBus = CdkEventBus.fromEventBusArn(scope, `${id}Bus`, arn);
237
+ return new EventBusMessaging(scope, id, {
238
+ type: "eventBus",
239
+ importedBus
240
+ });
241
+ }
242
+ /**
243
+ * Wrap the AWS-managed account+region `default` event bus. This is the
244
+ * bus that receives `aws.*` service events emitted via CloudTrail
245
+ * (`aws.ecr` `CreateRepository`, `aws.ec2` state-change, etc.); custom
246
+ * Fjall app buses do not receive this traffic. The returned wrapper has
247
+ * the AWS-service brand set, so `subscribe(...)` accepts `aws.*` source
248
+ * patterns; subscribing app-source patterns is still allowed but
249
+ * unusual (the canonical app-source path is `app.getEventBus()`).
250
+ *
251
+ * @param region AWS region holding the default bus (typically the stack
252
+ * region — the default bus is per-account-per-region).
253
+ * @param account AWS account id holding the default bus.
254
+ */
255
+ static fromAwsServiceBus(scope, id, region, account) {
256
+ const arn = `arn:aws:events:${region}:${account}:event-bus/default`;
257
+ const importedBus = CdkEventBus.fromEventBusArn(scope, `${id}Bus`, arn);
258
+ return new EventBusMessaging(scope, id, {
259
+ type: "eventBus",
260
+ importedBus,
261
+ awsServiceBus: true
262
+ });
263
+ }
168
264
  }
169
265
  /**
170
266
  * Factory for creating messaging resources.
@@ -209,10 +305,8 @@ export class MessagingFactory {
209
305
  return (_app, scope) => {
210
306
  switch (props.type) {
211
307
  case "queue":
212
- validateSQSProps(props);
213
308
  return new QueueMessaging(scope, id, props);
214
309
  case "topic":
215
- validateTopicProps(props);
216
310
  return new TopicMessaging(scope, id, props);
217
311
  case "eventBus":
218
312
  return new EventBusMessaging(scope, id, props);
@@ -224,5 +318,6 @@ export class MessagingFactory {
224
318
  };
225
319
  }
226
320
  }
227
- // Re-export type guards
321
+ // Canonical D18(b) re-export pinned by subscription.test.ts integrity suite.
322
+ export { EventField, RuleTargetInput } from "aws-cdk-lib/aws-events";
228
323
  export { isQueueMessaging, isTopicMessaging, isEventBusMessaging } from "./interfaces/messaging.js";
@@ -1,5 +1,5 @@
1
1
  import { Construct } from "constructs";
2
- import { Vpc } from "../../resources/aws/networking/vpc.js";
2
+ import { DEFAULT_MAX_AZS, Vpc } from "../../resources/aws/networking/vpc.js";
3
3
  import { FjallLogger } from "../../utils/validationLogger.js";
4
4
  function validateNetworkProps(props) {
5
5
  if (props.maxAzs !== undefined && (props.maxAzs < 1 || props.maxAzs > 3)) {
@@ -8,7 +8,7 @@ function validateNetworkProps(props) {
8
8
  if (typeof props.natGateways === "object" &&
9
9
  props.natGateways !== null &&
10
10
  props.natGateways.count !== undefined) {
11
- const maxAzs = props.maxAzs ?? 3;
11
+ const maxAzs = props.maxAzs ?? DEFAULT_MAX_AZS;
12
12
  if (props.natGateways.count > maxAzs) {
13
13
  FjallLogger.warn(`'natGateways.count' (${props.natGateways.count}) exceeds maxAzs (${maxAzs}).`);
14
14
  }
@@ -20,7 +20,6 @@ function validateNetworkProps(props) {
20
20
  export class NetworkFactory {
21
21
  static build(id, props) {
22
22
  return (app, scope) => {
23
- validateNetworkProps(props);
24
23
  return new Network(scope, id, props, app);
25
24
  };
26
25
  }
@@ -29,15 +28,25 @@ export class Network extends Construct {
29
28
  vpc;
30
29
  constructor(scope, id, props, app) {
31
30
  super(scope, id);
31
+ validateNetworkProps(props);
32
32
  this.vpc = this.createVpc(id, props, app);
33
33
  }
34
34
  createVpc(id, props, app) {
35
35
  const rawAccountId = app.node.tryGetContext("accountId");
36
- const accountId = (typeof rawAccountId === "string" ? rawAccountId : undefined) ||
37
- process.env.CDK_DEFAULT_ACCOUNT;
38
- const region = process.env.CDK_DEFAULT_REGION;
36
+ const guardedCtxAccountId = typeof rawAccountId === "string" && rawAccountId !== ""
37
+ ? rawAccountId
38
+ : undefined;
39
+ const envAccountId = process.env.CDK_DEFAULT_ACCOUNT;
40
+ const accountId = guardedCtxAccountId ??
41
+ (envAccountId !== undefined && envAccountId !== ""
42
+ ? envAccountId
43
+ : undefined);
44
+ const envRegion = process.env.CDK_DEFAULT_REGION;
45
+ const region = envRegion !== undefined && envRegion !== "" ? envRegion : undefined;
39
46
  const rawIpamPoolId = app.node.tryGetContext("ipamPoolId");
40
- const ipv4IpamPoolId = typeof rawIpamPoolId === "string" ? rawIpamPoolId : undefined;
47
+ const ipv4IpamPoolId = typeof rawIpamPoolId === "string" && rawIpamPoolId !== ""
48
+ ? rawIpamPoolId
49
+ : undefined;
41
50
  const vpcProps = {
42
51
  vpcName: props.vpcName,
43
52
  accountId,
@@ -1,4 +1,5 @@
1
1
  import { type Environment, Stack, type StackProps } from "aws-cdk-lib";
2
+ import { type CustomPermissionSets } from "../../config/aws/identityCenter.js";
2
3
  import { ScpPreset } from "../../config/aws/scpPreset.js";
3
4
  import type { ScpPresetProps } from "../../config/aws/scpPreset.js";
4
5
  import { OrganisationResource } from "../../resources/aws/organisation/index.js";
@@ -32,11 +33,14 @@ export declare class Organisation extends Stack {
32
33
  private accountRefs;
33
34
  private accountMap;
34
35
  private accountsConfig;
36
+ private identityCenter?;
35
37
  constructor(id: string, props: OrganisationProps);
36
38
  private createAccountReferences;
37
39
  private setupOrganisationFeatures;
38
40
  private setupCostAllocationTagActivator;
39
41
  private setupIdentityCenter;
42
+ declarePermissionSets(customs: CustomPermissionSets): void;
43
+ assignGroupMembers(members: Record<string, string[]>): void;
40
44
  getOrganisation(): OrganisationResource;
41
45
  getAccounts(): Record<string, string>;
42
46
  enableScps(props: ScpPresetProps): ScpPreset;
@@ -4,6 +4,7 @@ import { IdentityCenter } from "../../config/aws/identityCenter.js";
4
4
  import { ScpPreset } from "../../config/aws/scpPreset.js";
5
5
  import { OrganisationResource, OrganisationAccount, CostAllocationTagActivator } from "../../resources/aws/organisation/index.js";
6
6
  import { stripAndCamelCase } from "../../utils/stripAndCamelCase.js";
7
+ import { CDK_CONTEXT_KEYS } from "../../utils/cdkContext.js";
7
8
  import { getConfig } from "../../utils/getConfig.js";
8
9
  import { extractAccountNames } from "../../utils/accountsUtils.js";
9
10
  /**
@@ -22,6 +23,7 @@ export class Organisation extends Stack {
22
23
  accountRefs = [];
23
24
  accountMap;
24
25
  accountsConfig;
26
+ identityCenter;
25
27
  constructor(id, props) {
26
28
  const config = getConfig();
27
29
  const env = props.env ?? {
@@ -40,9 +42,10 @@ export class Organisation extends Stack {
40
42
  this.accountMap[key.toLowerCase()] = value;
41
43
  }
42
44
  this.accountsConfig = props.accounts;
43
- const orgId = this.node.tryGetContext("orgId");
44
- const rootId = this.node.tryGetContext("rootId");
45
- const managementAccountId = this.node.tryGetContext("managementAccountId") ?? this.account;
45
+ const orgId = this.node.tryGetContext(CDK_CONTEXT_KEYS.ORG_ID);
46
+ const rootId = this.node.tryGetContext(CDK_CONTEXT_KEYS.ROOT_ID);
47
+ const managementAccountId = this.node.tryGetContext(CDK_CONTEXT_KEYS.MANAGEMENT_ACCOUNT_ID) ??
48
+ this.account;
46
49
  if (!orgId || !rootId) {
47
50
  throw new Error("orgId and rootId must be provided via CDK context. Run deployment through the Fjall CLI.");
48
51
  }
@@ -75,7 +78,11 @@ export class Organisation extends Stack {
75
78
  this.setupCostAllocationTagActivator();
76
79
  }
77
80
  setupCostAllocationTagActivator() {
78
- new CostAllocationTagActivator(this, "CostAllocationTagActivator");
81
+ const activator = new CostAllocationTagActivator(this, "CostAllocationTagActivator");
82
+ App.getInstance().addSchedule("CostAllocationTagActivatorSchedule", {
83
+ schedule: "rate(24 hours)",
84
+ target: activator
85
+ });
79
86
  }
80
87
  setupIdentityCenter(identityCenter, managementAccountId) {
81
88
  if (identityCenter) {
@@ -87,11 +94,23 @@ export class Organisation extends Stack {
87
94
  ssoAccounts[name] = id;
88
95
  }
89
96
  }
90
- new IdentityCenter(this, "IdentityCenter", {
97
+ this.identityCenter = new IdentityCenter(this, "IdentityCenter", {
91
98
  accounts: ssoAccounts
92
99
  });
93
100
  }
94
101
  }
102
+ declarePermissionSets(customs) {
103
+ if (this.identityCenter === undefined) {
104
+ throw new Error("Identity Center is not enabled. Pass identityCenter: true to OrganisationFactory.");
105
+ }
106
+ this.identityCenter.declarePermissionSets(customs);
107
+ }
108
+ assignGroupMembers(members) {
109
+ if (this.identityCenter === undefined) {
110
+ throw new Error("Identity Center is not enabled. Pass identityCenter: true to OrganisationFactory.");
111
+ }
112
+ this.identityCenter.assignGroupMembers(members);
113
+ }
95
114
  getOrganisation() {
96
115
  return this.org;
97
116
  }
@@ -1,9 +1,8 @@
1
1
  import { Construct } from "constructs";
2
2
  import { type IBucket, type EventType, type IBucketNotificationDestination, type NotificationKeyFilter } from "aws-cdk-lib/aws-s3";
3
- import { BucketDeployment } from "aws-cdk-lib/aws-s3-deployment";
4
3
  import { type IGrantable, type Grant } from "aws-cdk-lib/aws-iam";
5
4
  import type App from "../../app.js";
6
- import { type WebsiteHostingConfig } from "../../resources/aws/storage/index.js";
5
+ import { BucketDeployment, type WebsiteHostingConfig } from "../../resources/aws/storage/index.js";
7
6
  import { type BackupTier } from "../../utils/backupTierMapping.js";
8
7
  import { type IStorage } from "./interfaces/storage.js";
9
8
  import { type IStorageConnector } from "./interfaces/connector.js";
@@ -1,9 +1,9 @@
1
1
  import { Construct } from "constructs";
2
2
  import { BucketEncryption, HttpMethods } from "aws-cdk-lib/aws-s3";
3
- import { BucketDeployment, Source, CacheControl } from "aws-cdk-lib/aws-s3-deployment";
3
+ import { Source, CacheControl } from "aws-cdk-lib/aws-s3-deployment";
4
4
  import { Key } from "aws-cdk-lib/aws-kms";
5
5
  import { CfnOutput, Duration, RemovalPolicy, Stack } from "aws-cdk-lib";
6
- import { S3Bucket } from "../../resources/aws/storage/index.js";
6
+ import { BucketDeployment, S3Bucket } from "../../resources/aws/storage/index.js";
7
7
  import { FjallLogger } from "../../utils/validationLogger.js";
8
8
  export { isStorage } from "./interfaces/storage.js";
9
9
  function toBucketEncryption(encryption) {
@@ -50,6 +50,7 @@ export class Storage extends Construct {
50
50
  bucketDeployment;
51
51
  constructor(scope, id, props) {
52
52
  super(scope, id);
53
+ validateStorageProps(props);
53
54
  const encryptionKey = props.kmsKeyArn
54
55
  ? Key.fromKeyArn(this, `${id}KmsKey`, props.kmsKeyArn)
55
56
  : undefined;
@@ -0,0 +1,34 @@
1
+ import { type Construct } from "constructs";
2
+ import type App from "../../app.js";
3
+ import { VpcPeeringConnection } from "../../resources/aws/networking/vpcPeeringConnection.js";
4
+ export interface IVpcPeerProps {
5
+ /** Name of the remote Fjall app to peer with. */
6
+ peerAppName: string;
7
+ /** AWS account ID of the remote app. */
8
+ peerAccountId: string;
9
+ /** Region of the remote app's VPC. Defaults to the local region. */
10
+ peerRegion?: string;
11
+ /** Remote VPC ID. Resolved from SSM (`{prefix}/vpc-id`) if omitted. */
12
+ peerVpcId?: string;
13
+ /** Remote VPC CIDR. Resolved from SSM (`{prefix}/vpc-cidr`) if omitted. */
14
+ peerVpcCidr?: string;
15
+ /** Accepter role ARN. Resolved from SSM (`{prefix}/peering-role-arn`) if omitted. */
16
+ peerRoleArn?: string;
17
+ /**
18
+ * Accepter route-table IDs. Resolved from the SSM `StringListParameter`
19
+ * (`{prefix}/route-table-ids`) via `valueForTypedListParameter` if omitted.
20
+ */
21
+ peerRouteTableIds?: string[];
22
+ /** Name of the local VPC to peer from. Defaults to the app's default VPC. */
23
+ localVpcName?: string;
24
+ /** Enable DNS resolution across the peering. Defaults to true. */
25
+ enableDnsResolution?: boolean;
26
+ /** Cost-allocation override — forwarded to the underlying construct. */
27
+ costAllocationEnvironment?: string;
28
+ /** Cost-allocation override — forwarded to the underlying construct. */
29
+ costAllocationDomain?: string;
30
+ }
31
+ export type VpcPeer = VpcPeeringConnection;
32
+ export declare class VpcPeerFactory {
33
+ static build(id: string, props: IVpcPeerProps): (app: App, scope: Construct) => VpcPeer;
34
+ }
@@ -0,0 +1,38 @@
1
+ import { Stack } from "aws-cdk-lib";
2
+ import { StringListParameter, StringParameter } from "aws-cdk-lib/aws-ssm";
3
+ import { buildSsmPrefix, DEFAULT_ORG_ID, resolveOrgId } from "../../utils/cdkContext.js";
4
+ import { VpcPeeringConnection } from "../../resources/aws/networking/vpcPeeringConnection.js";
5
+ export class VpcPeerFactory {
6
+ static build(id, props) {
7
+ return (app, scope) => {
8
+ const localVpc = app.getVpc(props.localVpcName);
9
+ const orgId = resolveOrgId(app.node, DEFAULT_ORG_ID);
10
+ const ssmPrefix = buildSsmPrefix(orgId, props.peerAppName);
11
+ const peerVpcId = props.peerVpcId ??
12
+ StringParameter.valueForStringParameter(scope, `${ssmPrefix}/vpc-id`);
13
+ const peerVpcCidr = props.peerVpcCidr ??
14
+ StringParameter.valueForStringParameter(scope, `${ssmPrefix}/vpc-cidr`);
15
+ const peerRoleArn = props.peerRoleArn ??
16
+ StringParameter.valueForStringParameter(scope, `${ssmPrefix}/peering-role-arn`);
17
+ const peerRouteTableIds = props.peerRouteTableIds ??
18
+ StringListParameter.valueForTypedListParameter(scope, `${ssmPrefix}/route-table-ids`);
19
+ const resolvedPeerOrgId = orgId !== DEFAULT_ORG_ID ? orgId : undefined;
20
+ const peerRegion = props.peerRegion ?? Stack.of(scope).region;
21
+ return new VpcPeeringConnection(scope, id, {
22
+ localVpc,
23
+ localVpcCidr: localVpc.vpcCidrBlock,
24
+ peerVpcId,
25
+ peerVpcCidr,
26
+ peerAccountId: props.peerAccountId,
27
+ peerRegion,
28
+ peerRoleArn,
29
+ peerRouteTableIds,
30
+ enableDnsResolution: props.enableDnsResolution,
31
+ peerAppName: props.peerAppName,
32
+ peerOrgId: resolvedPeerOrgId,
33
+ costAllocationEnvironment: props.costAllocationEnvironment,
34
+ costAllocationDomain: props.costAllocationDomain
35
+ });
36
+ };
37
+ }
38
+ }
@@ -0,0 +1,29 @@
1
+ import { type Construct } from "constructs";
2
+ import type App from "../../app.js";
3
+ import { VpcPeeringAccepterRole } from "../../resources/aws/networking/vpcPeeringAccepterRole.js";
4
+ import { type IRelationalDatabase } from "./interfaces/database.js";
5
+ import { type IEcsCompute } from "./interfaces/compute.js";
6
+ export type ExposedResource = {
7
+ resource: IRelationalDatabase;
8
+ name: string;
9
+ allowedFromCidrs: string[];
10
+ access?: "read" | "write" | "readWrite";
11
+ } | {
12
+ resource: IEcsCompute;
13
+ serviceName: string;
14
+ name: string;
15
+ allowedFromCidrs: string[];
16
+ port?: number;
17
+ };
18
+ export interface IVpcPeerAccepterProps {
19
+ requesterAccountIds: string[];
20
+ localVpcName?: string;
21
+ publishToSsm?: boolean;
22
+ exposedResources?: ExposedResource[];
23
+ costAllocationEnvironment?: string;
24
+ costAllocationDomain?: string;
25
+ }
26
+ export type VpcPeerAccepter = VpcPeeringAccepterRole;
27
+ export declare class VpcPeerAccepterFactory {
28
+ static build(id: string, props: IVpcPeerAccepterProps): (app: App, scope: Construct) => VpcPeerAccepter;
29
+ }