@fjall/components-infrastructure 0.96.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 (209) hide show
  1. package/dist/lib/app.d.ts +68 -1
  2. package/dist/lib/app.js +113 -4
  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 +2 -4
  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 +93 -5
  36. package/dist/lib/patterns/aws/computeEcs.js +867 -37
  37. package/dist/lib/patterns/aws/computeEcsTypes.d.ts +528 -25
  38. package/dist/lib/patterns/aws/computeEcsTypes.js +10 -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 +6 -4
  44. package/dist/lib/patterns/aws/index.d.ts +1 -0
  45. package/dist/lib/patterns/aws/index.js +1 -0
  46. package/dist/lib/patterns/aws/interfaces/compute.d.ts +7 -1
  47. package/dist/lib/patterns/aws/interfaces/database.d.ts +187 -8
  48. package/dist/lib/patterns/aws/interfaces/database.js +17 -3
  49. package/dist/lib/patterns/aws/interfaces/index.d.ts +2 -1
  50. package/dist/lib/patterns/aws/interfaces/index.js +3 -1
  51. package/dist/lib/patterns/aws/interfaces/messaging.d.ts +7 -0
  52. package/dist/lib/patterns/aws/interfaces/migrationContributor.d.ts +47 -0
  53. package/dist/lib/patterns/aws/interfaces/migrationContributor.js +9 -0
  54. package/dist/lib/patterns/aws/messaging.d.ts +66 -10
  55. package/dist/lib/patterns/aws/messaging.js +115 -20
  56. package/dist/lib/patterns/aws/network.js +16 -7
  57. package/dist/lib/patterns/aws/organisation.d.ts +4 -0
  58. package/dist/lib/patterns/aws/organisation.js +22 -4
  59. package/dist/lib/patterns/aws/storage.d.ts +1 -2
  60. package/dist/lib/patterns/aws/storage.js +3 -2
  61. package/dist/lib/patterns/aws/vpcPeer.js +3 -1
  62. package/dist/lib/resources/aws/analytics/clickhouse.js +18 -9
  63. package/dist/lib/resources/aws/analytics/clickhouseAlarms.d.ts +24 -9
  64. package/dist/lib/resources/aws/analytics/clickhouseAlarms.js +61 -10
  65. package/dist/lib/resources/aws/analytics/clickhouseConstants.d.ts +3 -3
  66. package/dist/lib/resources/aws/analytics/clickhouseConstants.js +3 -3
  67. package/dist/lib/resources/aws/analytics/clickhouseTypes.d.ts +7 -1
  68. package/dist/lib/resources/aws/analytics/clickhouseUserData.d.ts +1 -1
  69. package/dist/lib/resources/aws/analytics/clickhouseUserData.js +53 -3
  70. package/dist/lib/resources/aws/base/awsStack.js +4 -2
  71. package/dist/lib/resources/aws/compute/__tmp__/regression-shape.d.ts +2 -0
  72. package/dist/lib/resources/aws/compute/__tmp__/regression-shape.js +11 -0
  73. package/dist/lib/resources/aws/compute/asgInlineLifecycleHook.d.ts +52 -0
  74. package/dist/lib/resources/aws/compute/asgInlineLifecycleHook.js +60 -0
  75. package/dist/lib/resources/aws/compute/blockDeviceVolume.d.ts +8 -0
  76. package/dist/lib/resources/aws/compute/blockDeviceVolume.js +10 -0
  77. package/dist/lib/resources/aws/compute/ec2.d.ts +132 -12
  78. package/dist/lib/resources/aws/compute/ec2.js +163 -23
  79. package/dist/lib/resources/aws/compute/ec2GracefulTerminationHandler.d.ts +41 -0
  80. package/dist/lib/resources/aws/compute/ec2GracefulTerminationHandler.js +194 -0
  81. package/dist/lib/resources/aws/compute/ec2GracefulTerminationLambda.source.cjs +458 -0
  82. package/dist/lib/resources/aws/compute/ecs.d.ts +27 -1
  83. package/dist/lib/resources/aws/compute/ecs.js +42 -2
  84. package/dist/lib/resources/aws/compute/ecsConstants.d.ts +9 -0
  85. package/dist/lib/resources/aws/compute/ecsConstants.js +16 -0
  86. package/dist/lib/resources/aws/compute/ecsImages.js +32 -20
  87. package/dist/lib/resources/aws/compute/ecsLifecycleHookMigration.d.ts +96 -0
  88. package/dist/lib/resources/aws/compute/ecsLifecycleHookMigration.js +113 -0
  89. package/dist/lib/resources/aws/compute/ecsNetworking.d.ts +2 -1
  90. package/dist/lib/resources/aws/compute/ecsNetworking.js +18 -6
  91. package/dist/lib/resources/aws/compute/ecsServiceFactory.d.ts +13 -4
  92. package/dist/lib/resources/aws/compute/ecsServiceFactory.js +155 -33
  93. package/dist/lib/resources/aws/compute/ecsTaskDefinition.d.ts +31 -1
  94. package/dist/lib/resources/aws/compute/ecsTaskDefinition.js +102 -6
  95. package/dist/lib/resources/aws/compute/ecsTypes.d.ts +173 -13
  96. package/dist/lib/resources/aws/compute/ecsValidation.d.ts +9 -0
  97. package/dist/lib/resources/aws/compute/ecsValidation.js +63 -0
  98. package/dist/lib/resources/aws/compute/index.d.ts +2 -0
  99. package/dist/lib/resources/aws/compute/index.js +2 -0
  100. package/dist/lib/resources/aws/compute/lambda.d.ts +7 -13
  101. package/dist/lib/resources/aws/compute/lambda.js +30 -38
  102. package/dist/lib/resources/aws/compute/lifecycleHookLambda.source.cjs +192 -0
  103. package/dist/lib/resources/aws/compute/persistentDataVolume.d.ts +104 -0
  104. package/dist/lib/resources/aws/compute/persistentDataVolume.js +245 -0
  105. package/dist/lib/resources/aws/compute/persistentDataVolumeLambda.source.cjs +398 -0
  106. package/dist/lib/resources/aws/compute/samApplication.d.ts +15 -0
  107. package/dist/lib/resources/aws/compute/samApplication.js +27 -0
  108. package/dist/lib/resources/aws/database/clickhouseConstants.d.ts +159 -0
  109. package/dist/lib/resources/aws/database/clickhouseConstants.js +181 -0
  110. package/dist/lib/resources/aws/database/clickhouseSchemas.d.ts +71 -0
  111. package/dist/lib/resources/aws/database/clickhouseSchemas.js +157 -0
  112. package/dist/lib/resources/aws/database/clickhouseSecurityGroup.d.ts +14 -0
  113. package/dist/lib/resources/aws/database/clickhouseSecurityGroup.js +23 -0
  114. package/dist/lib/resources/aws/database/clickhouseUserData.d.ts +69 -0
  115. package/dist/lib/resources/aws/database/clickhouseUserData.js +371 -0
  116. package/dist/lib/resources/aws/database/clickhouseXmlRenderer.d.ts +56 -0
  117. package/dist/lib/resources/aws/database/clickhouseXmlRenderer.js +112 -0
  118. package/dist/lib/resources/aws/database/rdsAurora.d.ts +8 -1
  119. package/dist/lib/resources/aws/database/rdsAurora.js +42 -32
  120. package/dist/lib/resources/aws/database/rdsAuroraGlobal.d.ts +15 -2
  121. package/dist/lib/resources/aws/database/rdsAuroraGlobal.js +39 -43
  122. package/dist/lib/resources/aws/database/rdsDefaults.d.ts +6 -0
  123. package/dist/lib/resources/aws/database/rdsDefaults.js +7 -1
  124. package/dist/lib/resources/aws/database/rdsHelpers.d.ts +3 -3
  125. package/dist/lib/resources/aws/database/rdsHelpers.js +1 -0
  126. package/dist/lib/resources/aws/database/rdsInstance.d.ts +8 -1
  127. package/dist/lib/resources/aws/database/rdsInstance.js +51 -34
  128. package/dist/lib/resources/aws/database/rdsProxyOutput.d.ts +1 -1
  129. package/dist/lib/resources/aws/database/rdsProxyOutput.js +1 -1
  130. package/dist/lib/resources/aws/iam/delegationRole.js +1 -1
  131. package/dist/lib/resources/aws/iam/identityCenter/groupMembership.d.ts +9 -0
  132. package/dist/lib/resources/aws/iam/identityCenter/groupMembership.js +12 -0
  133. package/dist/lib/resources/aws/iam/identityCenter/index.d.ts +1 -0
  134. package/dist/lib/resources/aws/iam/identityCenter/index.js +1 -0
  135. package/dist/lib/resources/aws/iam/identityCenter/permissionSet.d.ts +1 -0
  136. package/dist/lib/resources/aws/iam/identityCenter/permissionSet.js +1 -0
  137. package/dist/lib/resources/aws/logging/logGroup.d.ts +0 -8
  138. package/dist/lib/resources/aws/logging/logGroup.js +0 -11
  139. package/dist/lib/resources/aws/messaging/defaultEventBus.d.ts +7 -0
  140. package/dist/lib/resources/aws/messaging/defaultEventBus.js +21 -0
  141. package/dist/lib/resources/aws/messaging/eventBridgeRule.d.ts +96 -0
  142. package/dist/lib/resources/aws/messaging/eventBridgeRule.js +110 -0
  143. package/dist/lib/resources/aws/messaging/eventTargets.d.ts +84 -0
  144. package/dist/lib/resources/aws/messaging/eventTargets.js +152 -0
  145. package/dist/lib/resources/aws/messaging/eventbridge.d.ts +25 -2
  146. package/dist/lib/resources/aws/messaging/eventbridge.js +22 -10
  147. package/dist/lib/resources/aws/messaging/index.d.ts +5 -0
  148. package/dist/lib/resources/aws/messaging/index.js +2 -0
  149. package/dist/lib/resources/aws/messaging/schedule.d.ts +118 -0
  150. package/dist/lib/resources/aws/messaging/schedule.js +64 -0
  151. package/dist/lib/resources/aws/messaging/sns.d.ts +2 -1
  152. package/dist/lib/resources/aws/messaging/sqs.d.ts +2 -1
  153. package/dist/lib/resources/aws/messaging/subscription.d.ts +112 -0
  154. package/dist/lib/resources/aws/messaging/subscription.js +67 -0
  155. package/dist/lib/resources/aws/messaging/utils.d.ts +6 -0
  156. package/dist/lib/resources/aws/messaging/utils.js +10 -0
  157. package/dist/lib/resources/aws/monitoring/clickhouseAlarms.d.ts +60 -0
  158. package/dist/lib/resources/aws/monitoring/clickhouseAlarms.js +139 -0
  159. package/dist/lib/resources/aws/monitoring/index.d.ts +2 -0
  160. package/dist/lib/resources/aws/monitoring/index.js +2 -0
  161. package/dist/lib/resources/aws/monitoring/scheduleAlarms.d.ts +47 -0
  162. package/dist/lib/resources/aws/monitoring/scheduleAlarms.js +106 -0
  163. package/dist/lib/resources/aws/networking/crossAccountDelegationRecord.js +6 -4
  164. package/dist/lib/resources/aws/networking/crossAccountReturnRoutes.js +17 -13
  165. package/dist/lib/resources/aws/networking/dnsRecord/dnsRecordBase.js +7 -5
  166. package/dist/lib/resources/aws/networking/domainCertificate.d.ts +2 -2
  167. package/dist/lib/resources/aws/networking/domainCertificate.js +6 -4
  168. package/dist/lib/resources/aws/networking/hostedZone.js +6 -5
  169. package/dist/lib/resources/aws/networking/serviceDiscovery.d.ts +96 -0
  170. package/dist/lib/resources/aws/networking/serviceDiscovery.js +96 -0
  171. package/dist/lib/resources/aws/networking/vpc.d.ts +4 -1
  172. package/dist/lib/resources/aws/networking/vpc.js +4 -1
  173. package/dist/lib/resources/aws/networking/vpcPeeringConnection.js +21 -3
  174. package/dist/lib/resources/aws/organisation/costAllocationTagActivator.d.ts +16 -5
  175. package/dist/lib/resources/aws/organisation/costAllocationTagActivator.js +17 -3
  176. package/dist/lib/resources/aws/organisation/index.d.ts +1 -1
  177. package/dist/lib/resources/aws/organisation/organisationPolicy.d.ts +2 -0
  178. package/dist/lib/resources/aws/organisation/organisationPolicy.js +3 -2
  179. package/dist/lib/resources/aws/secrets/secret.d.ts +7 -0
  180. package/dist/lib/resources/aws/secrets/secret.js +4 -3
  181. package/dist/lib/resources/aws/storage/bucketDeployment.d.ts +16 -0
  182. package/dist/lib/resources/aws/storage/bucketDeployment.js +17 -0
  183. package/dist/lib/resources/aws/storage/ecr.js +5 -5
  184. package/dist/lib/resources/aws/storage/index.d.ts +1 -0
  185. package/dist/lib/resources/aws/storage/index.js +1 -0
  186. package/dist/lib/resources/aws/storage/s3.js +10 -3
  187. package/dist/lib/resources/aws/utilities/customResource.js +18 -9
  188. package/dist/lib/synth_dump.d.ts +1 -0
  189. package/dist/lib/synth_dump.js +42 -0
  190. package/dist/lib/utils/cdkContext.d.ts +2 -0
  191. package/dist/lib/utils/cdkContext.js +4 -2
  192. package/dist/lib/utils/connections.js +6 -0
  193. package/dist/lib/utils/connector.d.ts +12 -0
  194. package/dist/lib/utils/costAllocationTags.d.ts +9 -0
  195. package/dist/lib/utils/costAllocationTags.js +11 -1
  196. package/dist/lib/utils/databaseTypes.d.ts +14 -0
  197. package/dist/lib/utils/getConfig.d.ts +2 -0
  198. package/dist/lib/utils/getConfig.js +2 -0
  199. package/dist/lib/utils/index.d.ts +1 -0
  200. package/dist/lib/utils/index.js +1 -0
  201. package/dist/lib/utils/manifestWriter.d.ts +6 -89
  202. package/dist/lib/utils/manifestWriter.js +36 -23
  203. package/dist/lib/utils/migrationVersionResolvers.d.ts +2 -0
  204. package/dist/lib/utils/migrationVersionResolvers.js +2 -0
  205. package/dist/lib/utils/orgConfigParser.js +2 -1
  206. package/dist/lib/utils/resolveAlertsTopic.d.ts +14 -0
  207. package/dist/lib/utils/resolveAlertsTopic.js +30 -0
  208. package/dist/lib/utils/validationLogger.js +6 -3
  209. package/package.json +22 -19
@@ -1,25 +1,37 @@
1
1
  import { Construct } from "constructs";
2
2
  import { CfnOutput } from "aws-cdk-lib";
3
3
  import { EventBus } from "aws-cdk-lib/aws-events";
4
+ import { env } from "../../../utils/env.js";
4
5
  import { toRemovalPolicy } from "./utils.js";
5
6
  export class EventBridgeBus extends Construct {
6
7
  id;
7
- eventBus;
8
+ #eventBus;
8
9
  constructor(scope, id, props) {
9
10
  super(scope, id);
10
11
  this.id = id;
11
- this.eventBus = new EventBus(this, `${id}EventBus`, {
12
- eventBusName: props.eventBusName
12
+ if (props.importedBus !== undefined) {
13
+ this.#eventBus = props.importedBus;
14
+ return;
15
+ }
16
+ const description = props.description ??
17
+ (props.appName
18
+ ? `EventBus ${props.appName} — Fjall app event bus`
19
+ : undefined);
20
+ const removalPolicyValue = props.removalPolicy ?? env({ default: "DESTROY", production: "RETAIN" });
21
+ const ownedBus = new EventBus(this, `${id}EventBus`, {
22
+ eventBusName: props.eventBusName,
23
+ description
13
24
  });
14
- this.eventBus.applyRemovalPolicy(toRemovalPolicy(props.removalPolicy));
25
+ this.#eventBus = ownedBus;
26
+ ownedBus.applyRemovalPolicy(toRemovalPolicy(removalPolicyValue));
15
27
  new CfnOutput(this, `${id}EventBusArn`, {
16
28
  key: `${id}EventBusArn`,
17
- value: this.eventBus.eventBusArn,
29
+ value: ownedBus.eventBusArn,
18
30
  description: `EventBridge event bus ARN for ${id}`
19
31
  });
20
32
  new CfnOutput(this, `${id}EventBusName`, {
21
33
  key: `${id}EventBusName`,
22
- value: this.eventBus.eventBusName,
34
+ value: ownedBus.eventBusName,
23
35
  description: `EventBridge event bus name for ${id}`
24
36
  });
25
37
  }
@@ -27,24 +39,24 @@ export class EventBridgeBus extends Construct {
27
39
  * Get the event bus ARN.
28
40
  */
29
41
  getEventBusArn() {
30
- return this.eventBus.eventBusArn;
42
+ return this.#eventBus.eventBusArn;
31
43
  }
32
44
  /**
33
45
  * Get the event bus name.
34
46
  */
35
47
  getEventBusName() {
36
- return this.eventBus.eventBusName;
48
+ return this.#eventBus.eventBusName;
37
49
  }
38
50
  /**
39
51
  * Get the underlying CDK EventBus construct.
40
52
  */
41
53
  getEventBus() {
42
- return this.eventBus;
54
+ return this.#eventBus;
43
55
  }
44
56
  /**
45
57
  * Grant put events permissions to the grantee.
46
58
  */
47
59
  grantPutEventsTo(grantee) {
48
- return this.eventBus.grantPutEventsTo(grantee);
60
+ return this.#eventBus.grantPutEventsTo(grantee);
49
61
  }
50
62
  }
@@ -2,3 +2,8 @@ export * from "./eventbridge.js";
2
2
  export * from "./sns.js";
3
3
  export * from "./sqs.js";
4
4
  export * from "./utils.js";
5
+ export { Schedule, type ScheduleProps, type ScheduleTarget } from "./schedule.js";
6
+ export { Subscription, type SubscriptionProps, type SubscriptionTarget } from "./subscription.js";
7
+ export type { EventBridgeRetryPolicy } from "./eventBridgeRule.js";
8
+ export type { EcsScheduleTarget } from "./eventTargets.js";
9
+ export type { ScheduleAlarmThresholds } from "./schedule.js";
@@ -2,3 +2,5 @@ export * from "./eventbridge.js";
2
2
  export * from "./sns.js";
3
3
  export * from "./sqs.js";
4
4
  export * from "./utils.js";
5
+ export { Schedule } from "./schedule.js";
6
+ export { Subscription } from "./subscription.js";
@@ -0,0 +1,118 @@
1
+ import { Construct } from "constructs";
2
+ import { type IRule } from "aws-cdk-lib/aws-events";
3
+ import type { IRole } from "aws-cdk-lib/aws-iam";
4
+ import type { ITopic } from "aws-cdk-lib/aws-sns";
5
+ import { type EventBridgeRetryPolicy } from "./eventBridgeRule.js";
6
+ import type { ScheduleTargetInput } from "./eventTargets.js";
7
+ import type { SQSQueue } from "./sqs.js";
8
+ import type { ScheduleAlarmThresholds } from "../monitoring/scheduleAlarms.js";
9
+ export type { ScheduleAlarmThresholds } from "../monitoring/scheduleAlarms.js";
10
+ /**
11
+ * Public input type for `Schedule.target`. Re-exported so consumers can
12
+ * type variables against it. Callers pass wrapper instances directly (D2).
13
+ */
14
+ export type ScheduleTarget = ScheduleTargetInput;
15
+ /**
16
+ * Construction-time props for `Schedule`. Owns the user-facing surface;
17
+ * description / DLQ / KMS-grant / retry-policy / alarm wiring all flow
18
+ * through the `EventBridgeRule` base wrapper.
19
+ */
20
+ export interface ScheduleProps {
21
+ /** Cron or rate expression. Validated against `VALIDATION_PATTERNS.SCHEDULE_EXPRESSION`. */
22
+ schedule: string;
23
+ /** What receives the event (Fjall wrapper instance per D2). */
24
+ target: ScheduleTarget;
25
+ /**
26
+ * SQS FIFO message group id. Required when target is a FIFO queue (D14);
27
+ * rejected for non-queue targets and non-FIFO queues. Validation lives in
28
+ * `resolveTarget(...)` (single source of truth).
29
+ */
30
+ messageGroupId?: string;
31
+ /**
32
+ * JSON payload sent to the target on every tick (D5 — typed as
33
+ * `Record<string, unknown>`). Translates to `message` (SQS) or `event`
34
+ * (Lambda / EventBus) on the underlying adapter. Values may be
35
+ * `EventField.*` tokens for payload-template substitution.
36
+ * `scheduledAt: EventField.time` is auto-injected unless the caller
37
+ * already provides a `scheduledAt` key.
38
+ *
39
+ * Not supported on ECS targets — CDK's `EcsTask` adapter ignores arbitrary
40
+ * input; use container command/environment overrides on the task definition
41
+ * instead. Passing `payload` against an ECS target throws.
42
+ *
43
+ * @example
44
+ * app.addSchedule("MetricsCollection", {
45
+ * schedule: "rate(5 minutes)",
46
+ * target: monitoringQueue,
47
+ * payload: { type: "metrics-collection" },
48
+ * messageGroupId: "monitoring-metrics-collection"
49
+ * });
50
+ */
51
+ payload?: Record<string, unknown>;
52
+ /**
53
+ * Application name used to build the default description when `description`
54
+ * is not supplied. Constructor-injected by `App.addSchedule(...)` per
55
+ * Stage-2 v2 — NOT derived from `Stack.of(this).stackName`.
56
+ */
57
+ appName?: string;
58
+ /** Override the default description ("Schedule <id> for <appName> — fires <schedule>"). */
59
+ description?: string;
60
+ /**
61
+ * When `{ enabled: true }` provisions a sibling `<id>Dlq`; otherwise honour
62
+ * the supplied queue. Typed against the resource-layer `SQSQueue` so the
63
+ * patterns-layer `QueueMessaging` (which extends `SQSQueue`) is still
64
+ * accepted without crossing the layer boundary.
65
+ */
66
+ deadLetterQueue?: {
67
+ enabled: true;
68
+ queue?: SQSQueue;
69
+ } | {
70
+ enabled: false;
71
+ } | SQSQueue;
72
+ /**
73
+ * Retry policy. Default for Schedule is `Duration.minutes(15)` / `2 attempts`
74
+ * per D15. AWS default of 24h/185 is wrong for cron-driven targets — overlapping
75
+ * retries block next ticks.
76
+ */
77
+ retryPolicy?: EventBridgeRetryPolicy;
78
+ enabled?: boolean;
79
+ role?: IRole;
80
+ crossStackScope?: Construct;
81
+ /** SNS topic for D13 alarms. When supplied, alarms are auto-provisioned unless `alarms === false`. */
82
+ alertsTopic?: ITopic;
83
+ /** Suppress alarms even when `alertsTopic` is supplied. */
84
+ alarms?: boolean;
85
+ /** Tunable alarm thresholds; ignored when `alertsTopic` is undefined OR `alarms === false`. */
86
+ alarmConfig?: ScheduleAlarmThresholds;
87
+ /** Application id tag for alarm webhook routing. */
88
+ applicationId?: string;
89
+ /**
90
+ * Stack placement override for `App.addSchedule(...)`. Defaults to the
91
+ * messaging stack; set to `"compute"` when the schedule's target lives in
92
+ * the compute stack and CFN cross-stack output churn is undesired.
93
+ */
94
+ stackPlacement?: "messaging" | "compute";
95
+ }
96
+ /**
97
+ * Schedule resource — composes an EventBridge `Rule` with a schedule expression
98
+ * and a single target. Description, DLQ, KMS-grant on CMK-encrypted DLQs,
99
+ * retry-policy default, FIFO validation, and D13 alarm wiring all delegate to
100
+ * the shared `EventBridgeRule` base wrapper. Tags propagate from the App
101
+ * aspect — no per-wrapper `applyCostAllocationTags` call per D10.
102
+ *
103
+ * **Idempotency contract:** EventBridge can deliver the same payload up to
104
+ * `retryAttempts + 1` times during transient target failures. SQS-targeted
105
+ * schedules with FIFO + content-based deduplication absorb same-content retries
106
+ * automatically; Lambda-targeted handlers MUST be idempotent (write-once,
107
+ * conditional updates, idempotency keys).
108
+ */
109
+ export declare class Schedule extends Construct {
110
+ #private;
111
+ readonly id: string;
112
+ readonly deadLetterQueue?: SQSQueue;
113
+ constructor(scope: Construct, id: string, props: ScheduleProps);
114
+ /** Get the underlying EventBridge rule (interface-typed per D18(a)). */
115
+ getRule(): IRule;
116
+ /** Get the ARN of the underlying rule. */
117
+ getRuleArn(): string;
118
+ }
@@ -0,0 +1,64 @@
1
+ import { Construct } from "constructs";
2
+ import { Schedule as CdkSchedule } from "aws-cdk-lib/aws-events";
3
+ import { VALIDATION_PATTERNS, VALIDATION_MESSAGES, parseRateExpression } from "@fjall/generator";
4
+ import { EventBridgeRule, buildScheduleDescription } from "./eventBridgeRule.js";
5
+ /**
6
+ * Schedule resource — composes an EventBridge `Rule` with a schedule expression
7
+ * and a single target. Description, DLQ, KMS-grant on CMK-encrypted DLQs,
8
+ * retry-policy default, FIFO validation, and D13 alarm wiring all delegate to
9
+ * the shared `EventBridgeRule` base wrapper. Tags propagate from the App
10
+ * aspect — no per-wrapper `applyCostAllocationTags` call per D10.
11
+ *
12
+ * **Idempotency contract:** EventBridge can deliver the same payload up to
13
+ * `retryAttempts + 1` times during transient target failures. SQS-targeted
14
+ * schedules with FIFO + content-based deduplication absorb same-content retries
15
+ * automatically; Lambda-targeted handlers MUST be idempotent (write-once,
16
+ * conditional updates, idempotency keys).
17
+ */
18
+ export class Schedule extends Construct {
19
+ id;
20
+ deadLetterQueue;
21
+ #base;
22
+ constructor(scope, id, props) {
23
+ super(scope, id);
24
+ this.id = id;
25
+ if (!VALIDATION_PATTERNS.SCHEDULE_EXPRESSION.test(props.schedule)) {
26
+ throw new Error(`${VALIDATION_MESSAGES.SCHEDULE_EXPRESSION} (received: ${props.schedule})`);
27
+ }
28
+ const description = props.description ??
29
+ (props.appName
30
+ ? buildScheduleDescription(props.appName, id, props.schedule)
31
+ : undefined);
32
+ const cadence = parseRateExpression(props.schedule);
33
+ const expectedTicksPerHour = cadence !== undefined ? (60 * 60_000) / cadence.everyMs : undefined;
34
+ this.#base = new EventBridgeRule(this, `${id}Base`, {
35
+ kind: "schedule",
36
+ schedule: CdkSchedule.expression(props.schedule),
37
+ description,
38
+ target: props.target,
39
+ messageGroupId: props.messageGroupId,
40
+ payload: props.payload,
41
+ deadLetterQueue: props.deadLetterQueue,
42
+ retryPolicy: props.retryPolicy,
43
+ enabled: props.enabled,
44
+ role: props.role,
45
+ crossStackScope: props.crossStackScope,
46
+ alertsTopic: props.alertsTopic,
47
+ alarms: props.alarms,
48
+ alarmConfig: props.alarmConfig,
49
+ applicationId: props.applicationId,
50
+ expectedTicksPerHour
51
+ });
52
+ if (this.#base.deadLetterQueue !== undefined) {
53
+ this.deadLetterQueue = this.#base.deadLetterQueue;
54
+ }
55
+ }
56
+ /** Get the underlying EventBridge rule (interface-typed per D18(a)). */
57
+ getRule() {
58
+ return this.#base.getRule();
59
+ }
60
+ /** Get the ARN of the underlying rule. */
61
+ getRuleArn() {
62
+ return this.#base.getRuleArn();
63
+ }
64
+ }
@@ -1,12 +1,13 @@
1
1
  import { Construct } from "constructs";
2
2
  import { type ITopic } from "aws-cdk-lib/aws-sns";
3
3
  import { type IGrantable, type Grant } from "aws-cdk-lib/aws-iam";
4
+ import { type RemovalPolicyString } from "./utils.js";
4
5
  export interface SNSTopicProps {
5
6
  topicName?: string;
6
7
  displayName?: string;
7
8
  fifo?: boolean;
8
9
  contentBasedDeduplication?: boolean;
9
- removalPolicy?: "DESTROY" | "RETAIN";
10
+ removalPolicy?: RemovalPolicyString;
10
11
  }
11
12
  export declare class SNSTopic extends Construct {
12
13
  readonly id: string;
@@ -1,6 +1,7 @@
1
1
  import { Construct } from "constructs";
2
2
  import { type IQueue } from "aws-cdk-lib/aws-sqs";
3
3
  import { type IGrantable, type Grant } from "aws-cdk-lib/aws-iam";
4
+ import { type RemovalPolicyString } from "./utils.js";
4
5
  /**
5
6
  * AWS SQS service limits and defaults.
6
7
  * @see https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-quotas.html
@@ -59,7 +60,7 @@ export interface SQSQueueProps {
59
60
  contentBasedDeduplication?: boolean;
60
61
  fifoThroughputLimit?: "perQueue" | "perMessageGroupId";
61
62
  deduplicationScope?: "queue" | "messageGroup";
62
- removalPolicy?: "DESTROY" | "RETAIN";
63
+ removalPolicy?: RemovalPolicyString;
63
64
  }
64
65
  export declare class SQSQueue extends Construct {
65
66
  readonly id: string;
@@ -0,0 +1,112 @@
1
+ import { Construct } from "constructs";
2
+ import { type EventPattern, type IEventBus, type IRule } from "aws-cdk-lib/aws-events";
3
+ import type { IRole } from "aws-cdk-lib/aws-iam";
4
+ import type { ITopic } from "aws-cdk-lib/aws-sns";
5
+ import { type EventBridgeRetryPolicy } from "./eventBridgeRule.js";
6
+ import type { ScheduleAlarmThresholds } from "../monitoring/scheduleAlarms.js";
7
+ import type { SubscriptionTargetInput } from "./eventTargets.js";
8
+ import type { SQSQueue } from "./sqs.js";
9
+ /**
10
+ * Public input type for `Subscription.target`. Re-exported so consumers can
11
+ * type variables against it. Callers pass wrapper instances directly (D2).
12
+ */
13
+ export type SubscriptionTarget = SubscriptionTargetInput;
14
+ /**
15
+ * Construction-time props for `Subscription`. Owns the user-facing surface;
16
+ * description / DLQ / KMS-grant / retry-policy / alarm wiring all flow
17
+ * through the `EventBridgeRule` base wrapper.
18
+ */
19
+ export interface SubscriptionProps {
20
+ /** EventBridge event-pattern object — re-exported from `aws-cdk-lib/aws-events`. */
21
+ pattern: EventPattern;
22
+ /** What receives matching events (Fjall wrapper instance per D2). */
23
+ target: SubscriptionTarget;
24
+ /**
25
+ * SQS FIFO message group id. Required when target is a FIFO queue (D14);
26
+ * rejected for non-queue targets and non-FIFO queues. Validation lives in
27
+ * `resolveTarget(...)` (single source of truth).
28
+ */
29
+ messageGroupId?: string;
30
+ /**
31
+ * Optional JSON payload that overrides the matched event detail before
32
+ * delivery to the target (D5 — typed as `Record<string, unknown>`).
33
+ * Translates to `message` (SQS) or `event` (Lambda / EventBus / CodeBuild)
34
+ * on the underlying adapter. Values may be `EventField.*` tokens for
35
+ * payload-template substitution (e.g.
36
+ * `EventField.fromPath("$.detail.repository.name")`). When omitted, the
37
+ * full matched event is forwarded verbatim — the common pub/sub case.
38
+ *
39
+ * Not supported on ECS targets — CDK's `EcsTask` adapter ignores arbitrary
40
+ * input; use container command/environment overrides on the task definition
41
+ * instead. Passing `payload` against an ECS target throws.
42
+ */
43
+ payload?: Record<string, unknown>;
44
+ /**
45
+ * Application name used to build the default description when `description`
46
+ * is not supplied. Constructor-injected by `EventBusMessaging.subscribe(...)`.
47
+ */
48
+ appName?: string;
49
+ /** Override the default description ("Subscription <id> for <appName>"). */
50
+ description?: string;
51
+ /** Bus that owns this subscription. Threaded by `EventBusMessaging.subscribe(...)`. */
52
+ eventBus?: IEventBus;
53
+ /**
54
+ * When `{ enabled: true }` provisions a sibling `<id>Dlq`; otherwise honour
55
+ * the supplied queue. Typed against the resource-layer `SQSQueue` so the
56
+ * patterns-layer `QueueMessaging` (which extends `SQSQueue`) is still
57
+ * accepted without crossing the layer boundary.
58
+ */
59
+ deadLetterQueue?: {
60
+ enabled: true;
61
+ queue?: SQSQueue;
62
+ } | {
63
+ enabled: false;
64
+ } | SQSQueue;
65
+ /**
66
+ * Retry policy. Subscription default is AWS defaults (24h / 185 attempts) per
67
+ * D15 — pub/sub is business-signal, late > never. Override to tighter windows
68
+ * for time-sensitive subscriptions.
69
+ */
70
+ retryPolicy?: EventBridgeRetryPolicy;
71
+ enabled?: boolean;
72
+ role?: IRole;
73
+ crossStackScope?: Construct;
74
+ /** SNS topic for D13 alarms. When supplied, alarms are auto-provisioned unless `alarms === false`. */
75
+ alertsTopic?: ITopic;
76
+ /** Suppress alarms even when `alertsTopic` is supplied. */
77
+ alarms?: boolean;
78
+ /** Tunable alarm thresholds; ignored when `alertsTopic` is undefined OR `alarms === false`. */
79
+ alarmConfig?: ScheduleAlarmThresholds;
80
+ /** Application id tag for alarm webhook routing. */
81
+ applicationId?: string;
82
+ }
83
+ /**
84
+ * Subscription resource — composes an EventBridge `Rule` with an event-pattern
85
+ * filter and a single target. Shares the `EventBridgeRule` base wrapper with
86
+ * `Schedule`; the only behavioural difference is `kind: "subscription"`,
87
+ * which leaves retry policy unset (AWS defaults per D15) and suppresses the
88
+ * D13 missed-tick `MatchedEvents` alarm (subscriptions are event-driven, not
89
+ * periodic, so the missed-tick semantics don't apply).
90
+ *
91
+ * **Idempotency contract:** EventBridge can deliver the same payload up to
92
+ * `retryAttempts + 1` times. SQS-targeted subscriptions with FIFO + content-based
93
+ * deduplication absorb same-content retries; Lambda handlers MUST be idempotent.
94
+ *
95
+ * **Delete ordering (D17):** when the bus's removalPolicy is DESTROY, the
96
+ * subscription's underlying rule must delete BEFORE the bus to avoid CFN's
97
+ * `EventBus can't be deleted since it has rules` error. The constructor calls
98
+ * `rule.node.addDependency(eventBus)` (rule depends on bus) so CFN creates
99
+ * the bus first and tears the rule down first. The dependency is added
100
+ * unconditionally because `IEventBus` does not expose `removalPolicy`; for
101
+ * RETAIN buses the dep is harmless.
102
+ */
103
+ export declare class Subscription extends Construct {
104
+ #private;
105
+ readonly id: string;
106
+ readonly deadLetterQueue?: SQSQueue;
107
+ constructor(scope: Construct, id: string, props: SubscriptionProps);
108
+ /** Get the underlying EventBridge rule (interface-typed per D18(a)). */
109
+ getRule(): IRule;
110
+ /** Get the ARN of the underlying rule. */
111
+ getRuleArn(): string;
112
+ }
@@ -0,0 +1,67 @@
1
+ import { Construct } from "constructs";
2
+ import { EventBridgeRule, buildSubscriptionDescription } from "./eventBridgeRule.js";
3
+ /**
4
+ * Subscription resource — composes an EventBridge `Rule` with an event-pattern
5
+ * filter and a single target. Shares the `EventBridgeRule` base wrapper with
6
+ * `Schedule`; the only behavioural difference is `kind: "subscription"`,
7
+ * which leaves retry policy unset (AWS defaults per D15) and suppresses the
8
+ * D13 missed-tick `MatchedEvents` alarm (subscriptions are event-driven, not
9
+ * periodic, so the missed-tick semantics don't apply).
10
+ *
11
+ * **Idempotency contract:** EventBridge can deliver the same payload up to
12
+ * `retryAttempts + 1` times. SQS-targeted subscriptions with FIFO + content-based
13
+ * deduplication absorb same-content retries; Lambda handlers MUST be idempotent.
14
+ *
15
+ * **Delete ordering (D17):** when the bus's removalPolicy is DESTROY, the
16
+ * subscription's underlying rule must delete BEFORE the bus to avoid CFN's
17
+ * `EventBus can't be deleted since it has rules` error. The constructor calls
18
+ * `rule.node.addDependency(eventBus)` (rule depends on bus) so CFN creates
19
+ * the bus first and tears the rule down first. The dependency is added
20
+ * unconditionally because `IEventBus` does not expose `removalPolicy`; for
21
+ * RETAIN buses the dep is harmless.
22
+ */
23
+ export class Subscription extends Construct {
24
+ id;
25
+ deadLetterQueue;
26
+ #base;
27
+ constructor(scope, id, props) {
28
+ super(scope, id);
29
+ this.id = id;
30
+ const description = props.description ??
31
+ (props.appName
32
+ ? buildSubscriptionDescription(props.appName, id)
33
+ : undefined);
34
+ this.#base = new EventBridgeRule(this, `${id}Base`, {
35
+ kind: "subscription",
36
+ eventPattern: props.pattern,
37
+ description,
38
+ target: props.target,
39
+ messageGroupId: props.messageGroupId,
40
+ payload: props.payload,
41
+ eventBus: props.eventBus,
42
+ deadLetterQueue: props.deadLetterQueue,
43
+ retryPolicy: props.retryPolicy,
44
+ enabled: props.enabled,
45
+ role: props.role,
46
+ crossStackScope: props.crossStackScope,
47
+ alertsTopic: props.alertsTopic,
48
+ alarms: props.alarms,
49
+ alarmConfig: props.alarmConfig,
50
+ applicationId: props.applicationId
51
+ });
52
+ if (this.#base.deadLetterQueue !== undefined) {
53
+ this.deadLetterQueue = this.#base.deadLetterQueue;
54
+ }
55
+ if (props.eventBus !== undefined) {
56
+ this.#base.getRule().node.addDependency(props.eventBus);
57
+ }
58
+ }
59
+ /** Get the underlying EventBridge rule (interface-typed per D18(a)). */
60
+ getRule() {
61
+ return this.#base.getRule();
62
+ }
63
+ /** Get the ARN of the underlying rule. */
64
+ getRuleArn() {
65
+ return this.#base.getRuleArn();
66
+ }
67
+ }
@@ -1,2 +1,8 @@
1
+ import { Schedule as CdkSchedule, type CronOptions } from "aws-cdk-lib/aws-events";
2
+ import { type Duration } from "aws-cdk-lib";
1
3
  export { toRemovalPolicy } from "../../../utils/removalPolicy.js";
2
4
  export type RemovalPolicyString = "DESTROY" | "RETAIN";
5
+ export type ScheduleExpression = CdkSchedule;
6
+ export declare function cronSchedule(options: CronOptions): CdkSchedule;
7
+ export declare function rateSchedule(duration: Duration): CdkSchedule;
8
+ export declare function expressionSchedule(expression: string): CdkSchedule;
@@ -1 +1,11 @@
1
+ import { Schedule as CdkSchedule } from "aws-cdk-lib/aws-events";
1
2
  export { toRemovalPolicy } from "../../../utils/removalPolicy.js";
3
+ export function cronSchedule(options) {
4
+ return CdkSchedule.cron(options);
5
+ }
6
+ export function rateSchedule(duration) {
7
+ return CdkSchedule.rate(duration);
8
+ }
9
+ export function expressionSchedule(expression) {
10
+ return CdkSchedule.expression(expression);
11
+ }
@@ -0,0 +1,60 @@
1
+ import { Alarm } from "aws-cdk-lib/aws-cloudwatch";
2
+ import type { IRole } from "aws-cdk-lib/aws-iam";
3
+ import type { ITopic } from "aws-cdk-lib/aws-sns";
4
+ import type { ILogGroup } from "aws-cdk-lib/aws-logs";
5
+ import type { Construct } from "constructs";
6
+ export interface ClickHouseAlarmThresholds {
7
+ /** EC2 host CPU % over 5 min. Default 90. */
8
+ cpuThreshold?: number;
9
+ /** EC2 host memory % over 5 min (requires CWAgent). Default 80. */
10
+ memoryThreshold?: number;
11
+ /** EBS root-volume disk % used. Default 70 (warn) — paired with critical at 85. */
12
+ diskWarnThreshold?: number;
13
+ /** EBS root-volume disk % used. Default 85. */
14
+ diskCriticalThreshold?: number;
15
+ }
16
+ export interface ClickHouseAlarmsProps {
17
+ scope: Construct;
18
+ /**
19
+ * EC2 instance role (D10 — single accessor on `EcsCompute`). Drives the
20
+ * BACKUP failure alarm description so the responder grep target points at
21
+ * the role to inspect for missing S3 grants.
22
+ */
23
+ instanceRole: IRole;
24
+ /**
25
+ * AutoScalingGroupName token from `EcsCompute.getAutoScalingGroupName()`.
26
+ * Required for `AWS/EC2` and `CWAgent` metric dimensions (CloudWatch keys
27
+ * EC2 host metrics by ASG name; the role itself does not surface here).
28
+ */
29
+ asgName: string;
30
+ alarmTopic: ITopic;
31
+ /**
32
+ * Webapp log group. Required to wire the stuck-merge alarm — `client.ts`
33
+ * emits `serverLogger.warn("ClickHouse", "Stuck merge detected")` when
34
+ * `system.merges` shows a merge elapsed > 30 min.
35
+ */
36
+ webappLogGroup: ILogGroup;
37
+ /**
38
+ * Backup-task log group. Required to wire the backup-failure alarm —
39
+ * `BACKUP DATABASE … TO S3(…)` emits `AccessDenied` / `S3Exception` lines
40
+ * when the IAM grant or bucket policy is misconfigured (silent before the
41
+ * alarm landed; the daily backup task exited non-zero with no signal).
42
+ */
43
+ backupTaskLogGroup: ILogGroup;
44
+ config?: ClickHouseAlarmThresholds;
45
+ }
46
+ /**
47
+ * Single-node ClickHouse posture alarms. Covers host-level CPU + (optional)
48
+ * memory and disk via the CloudWatch Agent metric namespace `CWAgent`, plus
49
+ * two log-driven alarms:
50
+ *
51
+ * - **Stuck merges** — `client.ts` polls `system.merges` every 5 min and logs
52
+ * `serverLogger.warn("ClickHouse", "Stuck merge detected")` when elapsed
53
+ * exceeds 30 min. The metric filter on the webapp log group emits a count
54
+ * metric per match; the alarm fires on Sum >= 1 over 5 min × 2 evaluations.
55
+ * - **Backup failures** — `AccessDenied` or `S3Exception` from the backup
56
+ * task's BACKUP DATABASE TO S3 statement. Closes the silent-failure mode
57
+ * that masked the original IAM-grant misconfiguration (see
58
+ * `designs/2026-04-27-clickhouse-backup-iam-role.md`).
59
+ */
60
+ export declare function createClickHouseAlarms(props: ClickHouseAlarmsProps): Alarm[];