@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
@@ -0,0 +1,96 @@
1
+ import { Construct } from "constructs";
2
+ import { Duration } from "aws-cdk-lib";
3
+ import { type IVpc } from "aws-cdk-lib/aws-ec2";
4
+ import { type IPrivateDnsNamespace, type IService } from "aws-cdk-lib/aws-servicediscovery";
5
+ /**
6
+ * Plumbing-only base resource wrapping `aws-cdk-lib/aws-servicediscovery`'s
7
+ * `PrivateDnsNamespace`. Per D7 + D29 of the ClickHouse Database Factory
8
+ * promotion design, the only consumer entry point is `App.getNamespace()` —
9
+ * this class is NOT re-exported from `lib/index.ts`.
10
+ *
11
+ * No `static fromXxx(...)` factory is exposed: cross-stack consumption is
12
+ * single-stack-only for v1 per D29. If/when cross-stack arises, a `fromXxx`
13
+ * factory lands then, not now.
14
+ */
15
+ export interface ServiceDiscoveryNamespaceProps {
16
+ vpc: IVpc;
17
+ name: string;
18
+ /** Override the default description (`"ServiceDiscovery <name> — Fjall private DNS namespace"`). */
19
+ description?: string;
20
+ /**
21
+ * Removal policy. Default resolves via the `env()` helper (production →
22
+ * RETAIN; non-prod → DESTROY) — matches the convention codified in D17 of
23
+ * the EventBridge promotion design. NODE_ENV is intentionally NOT consulted
24
+ * because it is unset during CDK synth in Fjall's deployment paths.
25
+ */
26
+ removalPolicy?: "DESTROY" | "RETAIN";
27
+ }
28
+ /**
29
+ * Properties for registering a Cloud Map service inside the namespace via
30
+ * `registerService(...)`. Single source of truth for the second-tier wrapper
31
+ * around `AWS::ServiceDiscovery::Service`. Per D7(d), this method is
32
+ * internal-only — never consumed directly from user infrastructure code.
33
+ */
34
+ export interface ServiceRegistrationProps {
35
+ /** Service name within the namespace (forms the leftmost label of the FQDN). */
36
+ name: string;
37
+ /**
38
+ * Description override. Default: `"Fjall internal service: <name>"`.
39
+ * Operators see this in the Cloud Map console; explicit overrides are
40
+ * preferred when the service name alone is ambiguous (e.g. `"clickhouse"`
41
+ * is fine; `"web"` benefits from a description naming the role).
42
+ */
43
+ description?: string;
44
+ /**
45
+ * DNS TTL applied to the A records returned for this service. Default:
46
+ * 60 seconds — matches CDK's implicit ECS default. Raise for stable
47
+ * services (cuts query volume); lower for rapidly-changing instance sets.
48
+ */
49
+ dnsTtl?: Duration;
50
+ /**
51
+ * DNS record type. Default `"A"` — appropriate for `awsvpc` ECS services
52
+ * where each task has its own ENI IP. Set to `"SRV"` when the consumer is
53
+ * an ECS service running under `host` or `bridge` network mode: SRV records
54
+ * carry both the host IP and the published port, which `A` records cannot.
55
+ * CDK's `Ec2Service.associateCloudMapService(...)` requires SRV (and a
56
+ * `containerName` + `containerPort`) under those modes.
57
+ */
58
+ dnsRecordType?: "A" | "SRV";
59
+ }
60
+ export declare class ServiceDiscoveryNamespace extends Construct {
61
+ #private;
62
+ readonly id: string;
63
+ constructor(scope: Construct, id: string, props: ServiceDiscoveryNamespaceProps);
64
+ /**
65
+ * Get the underlying CDK private DNS namespace as the `IPrivateDnsNamespace`
66
+ * interface. Per D18(a), the public surface is the interface, never the
67
+ * concrete `PrivateDnsNamespace` class.
68
+ */
69
+ getNamespace(): IPrivateDnsNamespace;
70
+ getNamespaceArn(): string;
71
+ getNamespaceName(): string;
72
+ /**
73
+ * Register a Cloud Map service inside this namespace. Creates an
74
+ * `AWS::ServiceDiscovery::Service` resource via the underlying CDK
75
+ * `PrivateDnsNamespace.createService(...)` with Fjall description discipline
76
+ * applied. Internal-only per D7(d) — Fjall resources call this from inside
77
+ * their construct bodies; user code never invokes it directly.
78
+ *
79
+ * Throws on duplicate registration: a single namespace cannot host two
80
+ * services with the same DNS name. Caught at synth time, not deploy time.
81
+ */
82
+ registerService(props: ServiceRegistrationProps): IService;
83
+ /**
84
+ * True if a service with this name has been registered in the namespace.
85
+ * Cheap registry lookup; does NOT consult AWS — only counts services
86
+ * registered via `registerService(...)` on this construct.
87
+ */
88
+ hasService(name: string): boolean;
89
+ /**
90
+ * Build the FQDN for a previously-registered service:
91
+ * `<serviceName>.<namespaceName>` (e.g. `clickhouse.acme.local`). Throws if
92
+ * the service has not been registered — prevents typos that would silently
93
+ * resolve to NXDOMAIN at runtime.
94
+ */
95
+ getEndpoint(serviceName: string): string;
96
+ }
@@ -0,0 +1,96 @@
1
+ import { Construct } from "constructs";
2
+ import { CfnOutput, Duration } from "aws-cdk-lib";
3
+ import { PrivateDnsNamespace, DnsRecordType } from "aws-cdk-lib/aws-servicediscovery";
4
+ import { env } from "../../../utils/env.js";
5
+ import { toRemovalPolicy } from "../../../utils/removalPolicy.js";
6
+ export class ServiceDiscoveryNamespace extends Construct {
7
+ id;
8
+ #namespace;
9
+ #services = new Map();
10
+ constructor(scope, id, props) {
11
+ super(scope, id);
12
+ this.id = id;
13
+ const description = props.description ??
14
+ `ServiceDiscovery ${props.name} — Fjall private DNS namespace`;
15
+ const removalPolicyValue = props.removalPolicy ?? env({ default: "DESTROY", production: "RETAIN" });
16
+ const namespace = new PrivateDnsNamespace(this, `${id}Namespace`, {
17
+ vpc: props.vpc,
18
+ name: props.name,
19
+ description
20
+ });
21
+ this.#namespace = namespace;
22
+ namespace.applyRemovalPolicy(toRemovalPolicy(removalPolicyValue));
23
+ new CfnOutput(this, `${id}NamespaceArn`, {
24
+ key: `${id}NamespaceArn`,
25
+ value: namespace.namespaceArn,
26
+ description: `Cloud Map private DNS namespace ARN for ${id}`
27
+ });
28
+ new CfnOutput(this, `${id}NamespaceName`, {
29
+ key: `${id}NamespaceName`,
30
+ value: namespace.namespaceName,
31
+ description: `Cloud Map private DNS namespace name for ${id}`
32
+ });
33
+ }
34
+ /**
35
+ * Get the underlying CDK private DNS namespace as the `IPrivateDnsNamespace`
36
+ * interface. Per D18(a), the public surface is the interface, never the
37
+ * concrete `PrivateDnsNamespace` class.
38
+ */
39
+ getNamespace() {
40
+ return this.#namespace;
41
+ }
42
+ getNamespaceArn() {
43
+ return this.#namespace.namespaceArn;
44
+ }
45
+ getNamespaceName() {
46
+ return this.#namespace.namespaceName;
47
+ }
48
+ /**
49
+ * Register a Cloud Map service inside this namespace. Creates an
50
+ * `AWS::ServiceDiscovery::Service` resource via the underlying CDK
51
+ * `PrivateDnsNamespace.createService(...)` with Fjall description discipline
52
+ * applied. Internal-only per D7(d) — Fjall resources call this from inside
53
+ * their construct bodies; user code never invokes it directly.
54
+ *
55
+ * Throws on duplicate registration: a single namespace cannot host two
56
+ * services with the same DNS name. Caught at synth time, not deploy time.
57
+ */
58
+ registerService(props) {
59
+ if (this.#services.has(props.name)) {
60
+ throw new Error(`ServiceDiscoveryNamespace '${this.#namespace.namespaceName}': ` +
61
+ `service '${props.name}' is already registered. Each service name ` +
62
+ `must be unique within a namespace.`);
63
+ }
64
+ const description = props.description ?? `Fjall internal service: ${props.name}`;
65
+ const service = this.#namespace.createService(`Service-${props.name}`, {
66
+ name: props.name,
67
+ description,
68
+ dnsTtl: props.dnsTtl ?? Duration.seconds(60),
69
+ dnsRecordType: props.dnsRecordType === "SRV" ? DnsRecordType.SRV : DnsRecordType.A
70
+ });
71
+ this.#services.set(props.name, service);
72
+ return service;
73
+ }
74
+ /**
75
+ * True if a service with this name has been registered in the namespace.
76
+ * Cheap registry lookup; does NOT consult AWS — only counts services
77
+ * registered via `registerService(...)` on this construct.
78
+ */
79
+ hasService(name) {
80
+ return this.#services.has(name);
81
+ }
82
+ /**
83
+ * Build the FQDN for a previously-registered service:
84
+ * `<serviceName>.<namespaceName>` (e.g. `clickhouse.acme.local`). Throws if
85
+ * the service has not been registered — prevents typos that would silently
86
+ * resolve to NXDOMAIN at runtime.
87
+ */
88
+ getEndpoint(serviceName) {
89
+ if (!this.#services.has(serviceName)) {
90
+ throw new Error(`ServiceDiscoveryNamespace '${this.#namespace.namespaceName}': ` +
91
+ `service '${serviceName}' has not been registered. Call ` +
92
+ `registerService({ name: '${serviceName}' }) before resolving its endpoint.`);
93
+ }
94
+ return `${serviceName}.${this.#namespace.namespaceName}`;
95
+ }
96
+ }
@@ -1,10 +1,13 @@
1
1
  import { type Construct } from "constructs";
2
2
  import * as ec2 from "aws-cdk-lib/aws-ec2";
3
3
  import { type StackBuilder } from "../base/awsStack.js";
4
+ export declare const FLOW_LOG_TRAFFIC_TYPES: readonly ["ALL", "ACCEPT", "REJECT"];
5
+ export type FlowLogTrafficType = (typeof FLOW_LOG_TRAFFIC_TYPES)[number];
6
+ export declare const DEFAULT_MAX_AZS = 3;
4
7
  export interface VpcFlowLogConfig {
5
8
  destination?: "cloudwatch" | "s3";
6
9
  retentionDays?: number;
7
- trafficType?: "ALL" | "ACCEPT" | "REJECT";
10
+ trafficType?: FlowLogTrafficType;
8
11
  }
9
12
  export interface VpcNatConfig {
10
13
  count?: number;
@@ -1,18 +1,21 @@
1
- import { Duration, RemovalPolicy, Stack } from "aws-cdk-lib";
1
+ import { CfnOutput, Duration, RemovalPolicy, Stack } from "aws-cdk-lib";
2
2
  import * as ec2 from "aws-cdk-lib/aws-ec2";
3
3
  import * as s3 from "aws-cdk-lib/aws-s3";
4
4
  import { LogGroup } from "../logging/logGroup.js";
5
5
  import { S3Bucket } from "../storage/index.js";
6
+ export const FLOW_LOG_TRAFFIC_TYPES = ["ALL", "ACCEPT", "REJECT"];
7
+ // Read at two sites (resources-layer constructor default + patterns-layer natGateways guard) that must agree.
8
+ export const DEFAULT_MAX_AZS = 3;
6
9
  export class Vpc extends ec2.Vpc {
7
10
  gatewayEndpoints = [];
8
11
  interfaceEndpoints = [];
9
12
  hasNatGateways;
10
13
  constructor(scope, id, props) {
11
14
  const { maxAzs: maxAzsFromProps, vpcName: explicitName, ...restProps } = props ?? {};
12
- const maxAzs = maxAzsFromProps ?? 3;
15
+ const maxAzs = maxAzsFromProps ?? DEFAULT_MAX_AZS;
13
16
  const natGateways = Vpc.resolveNatGateways(props);
14
17
  const vpcName = explicitName ?? id;
15
- super(scope, `vpc-${id}`, {
18
+ super(scope, `Vpc${id}`, {
16
19
  ...restProps,
17
20
  vpcName,
18
21
  natGateways,
@@ -23,6 +26,10 @@ export class Vpc extends ec2.Vpc {
23
26
  });
24
27
  this.hasNatGateways = natGateways !== 0;
25
28
  this.addInterfaceEndpoints(id, props, this.hasNatGateways);
29
+ new CfnOutput(this, "VpcCidrBlock", {
30
+ value: this.vpcCidrBlock,
31
+ exportName: `${Stack.of(this).stackName}-vpc-cidr`
32
+ });
26
33
  }
27
34
  static gatewayEndpoints(props) {
28
35
  if (props?.endpointsConfig === false) {
@@ -0,0 +1,18 @@
1
+ import { Construct } from "constructs";
2
+ import { Role } from "aws-cdk-lib/aws-iam";
3
+ import { type IVpc } from "aws-cdk-lib/aws-ec2";
4
+ export interface VpcPeeringAccepterRoleProps {
5
+ /** AWS account IDs allowed to initiate peering and manage return routes. */
6
+ readonly requesterAccountIds: string[];
7
+ /** The local VPC this role is scoped to. */
8
+ readonly localVpc: IVpc;
9
+ /** Cost-allocation override — defaults to `"management"`. */
10
+ readonly costAllocationEnvironment?: string;
11
+ /** Cost-allocation override — defaults to the local VPC's construct id. */
12
+ readonly costAllocationDomain?: string;
13
+ }
14
+ export declare class VpcPeeringAccepterRole extends Construct {
15
+ readonly role: Role;
16
+ readonly roleArn: string;
17
+ constructor(scope: Construct, id: string, props: VpcPeeringAccepterRoleProps);
18
+ }
@@ -0,0 +1,61 @@
1
+ import { Construct } from "constructs";
2
+ import { ArnFormat, Stack, Tags } from "aws-cdk-lib";
3
+ import { AccountPrincipal, CompositePrincipal, PolicyDocument, PolicyStatement, Role } from "aws-cdk-lib/aws-iam";
4
+ import { COST_ALLOCATION_TAGS, DEFAULT_COST_ALLOCATION_ENVIRONMENT } from "../../../utils/costAllocationTags.js";
5
+ export class VpcPeeringAccepterRole extends Construct {
6
+ role;
7
+ roleArn;
8
+ constructor(scope, id, props) {
9
+ super(scope, id);
10
+ const vpcArnPattern = Stack.of(this).formatArn({
11
+ service: "ec2",
12
+ region: "*",
13
+ account: "*",
14
+ resource: "vpc",
15
+ resourceName: props.localVpc.vpcId,
16
+ arnFormat: ArnFormat.SLASH_RESOURCE_NAME
17
+ });
18
+ this.role = new Role(this, "Role", {
19
+ assumedBy: new CompositePrincipal(...props.requesterAccountIds.map((accountId) => new AccountPrincipal(accountId))),
20
+ inlinePolicies: {
21
+ allowPeering: new PolicyDocument({
22
+ statements: [
23
+ new PolicyStatement({
24
+ actions: [
25
+ "ec2:AcceptVpcPeeringConnection",
26
+ "ec2:ModifyVpcPeeringConnectionOptions"
27
+ ],
28
+ resources: ["*"],
29
+ conditions: {
30
+ StringEquals: {
31
+ "ec2:AccepterVpc": vpcArnPattern
32
+ }
33
+ }
34
+ }),
35
+ new PolicyStatement({
36
+ actions: ["ec2:CreateRoute", "ec2:DeleteRoute"],
37
+ resources: ["*"],
38
+ conditions: {
39
+ StringEquals: {
40
+ "ec2:Vpc": vpcArnPattern
41
+ }
42
+ }
43
+ }),
44
+ new PolicyStatement({
45
+ actions: [
46
+ "ec2:DescribeRouteTables",
47
+ "ec2:DescribeVpcPeeringConnections"
48
+ ],
49
+ resources: ["*"]
50
+ })
51
+ ]
52
+ })
53
+ }
54
+ });
55
+ this.roleArn = this.role.roleArn;
56
+ Tags.of(this).add("fjall:resource:type", "vpc-peering-accepter");
57
+ Tags.of(this).add(COST_ALLOCATION_TAGS.ENVIRONMENT, props.costAllocationEnvironment ?? DEFAULT_COST_ALLOCATION_ENVIRONMENT);
58
+ Tags.of(this).add(COST_ALLOCATION_TAGS.SERVICE, "vpcPeeringAccepter");
59
+ Tags.of(this).add(COST_ALLOCATION_TAGS.DOMAIN, props.costAllocationDomain ?? props.localVpc.node.id);
60
+ }
61
+ }
@@ -0,0 +1,49 @@
1
+ import { Construct } from "constructs";
2
+ import { CfnVPCPeeringConnection, type IVpc, type SubnetSelection } from "aws-cdk-lib/aws-ec2";
3
+ export interface VpcPeeringConnectionProps {
4
+ /** The local VPC to peer from. */
5
+ readonly localVpc: IVpc;
6
+ /** The local VPC CIDR (destination of the accepter's return routes). */
7
+ readonly localVpcCidr: string;
8
+ /** The remote VPC ID. */
9
+ readonly peerVpcId: string;
10
+ /** The remote VPC CIDR (destination of the local routes). */
11
+ readonly peerVpcCidr: string;
12
+ /** Remote account ID — required for cross-account peering. */
13
+ readonly peerAccountId?: string;
14
+ /** Remote region — required for cross-region peering. */
15
+ readonly peerRegion?: string;
16
+ /** ARN of the accepter role (for auto-accept and cross-account route management). */
17
+ readonly peerRoleArn?: string;
18
+ /** Route-table IDs in the accepter VPC (for cross-account return routes). */
19
+ readonly peerRouteTableIds?: string[];
20
+ /** Local subnet selection for routes. Defaults to `PRIVATE_WITH_EGRESS`. */
21
+ readonly routeSubnets?: SubnetSelection;
22
+ /** Enable DNS resolution across the peering on both sides. Defaults to true. */
23
+ readonly enableDnsResolution?: boolean;
24
+ /**
25
+ * Optional cross-app label — when present, added as the `fjall:peering:peer-app`
26
+ * tag and used as the default cost-allocation domain.
27
+ */
28
+ readonly peerAppName?: string;
29
+ /**
30
+ * Optional organisation ID of the remote app — surfaced as a public-readonly
31
+ * property on the construct for downstream consumers (ECS `remoteConnections`)
32
+ * that need to build cross-app SSM paths.
33
+ */
34
+ readonly peerOrgId?: string;
35
+ /** Cost-allocation override — defaults to `"management"`. */
36
+ readonly costAllocationEnvironment?: string;
37
+ /**
38
+ * Cost-allocation override — defaults to `peerAppName` if provided, otherwise
39
+ * the peer VPC ID.
40
+ */
41
+ readonly costAllocationDomain?: string;
42
+ }
43
+ export declare class VpcPeeringConnection extends Construct {
44
+ readonly peeringConnectionId: string;
45
+ readonly peering: CfnVPCPeeringConnection;
46
+ readonly peerAppName: string | undefined;
47
+ readonly peerOrgId: string | undefined;
48
+ constructor(scope: Construct, id: string, props: VpcPeeringConnectionProps);
49
+ }
@@ -0,0 +1,106 @@
1
+ import { Construct } from "constructs";
2
+ import { Stack, Tags } from "aws-cdk-lib";
3
+ import { CfnRoute, CfnVPCPeeringConnection, SubnetType } from "aws-cdk-lib/aws-ec2";
4
+ import { PolicyStatement } from "aws-cdk-lib/aws-iam";
5
+ import { AwsCustomResource, AwsCustomResourcePolicy, PhysicalResourceId } from "aws-cdk-lib/custom-resources";
6
+ import { COST_ALLOCATION_TAGS, DEFAULT_COST_ALLOCATION_ENVIRONMENT } from "../../../utils/costAllocationTags.js";
7
+ import { CrossAccountReturnRoutes } from "./crossAccountReturnRoutes.js";
8
+ export class VpcPeeringConnection extends Construct {
9
+ peeringConnectionId;
10
+ peering;
11
+ peerAppName;
12
+ peerOrgId;
13
+ constructor(scope, id, props) {
14
+ super(scope, id);
15
+ this.peerAppName = props.peerAppName;
16
+ this.peerOrgId = props.peerOrgId;
17
+ this.peering = new CfnVPCPeeringConnection(this, "Peering", {
18
+ vpcId: props.localVpc.vpcId,
19
+ peerVpcId: props.peerVpcId,
20
+ peerOwnerId: props.peerAccountId,
21
+ peerRegion: props.peerRegion,
22
+ peerRoleArn: props.peerRoleArn
23
+ });
24
+ this.peeringConnectionId = this.peering.attrId;
25
+ const subnets = props.localVpc.selectSubnets(props.routeSubnets ?? { subnetType: SubnetType.PRIVATE_WITH_EGRESS });
26
+ for (const subnet of subnets.subnets) {
27
+ new CfnRoute(this, `Route${subnet.node.id}`, {
28
+ routeTableId: subnet.routeTable.routeTableId,
29
+ destinationCidrBlock: props.peerVpcCidr,
30
+ vpcPeeringConnectionId: this.peering.attrId
31
+ });
32
+ }
33
+ const enableDnsResolution = props.enableDnsResolution !== false;
34
+ // Requester-side DNS runs in the local account, so a plain AwsCustomResource
35
+ // is sufficient. The accepter side is delegated to the cross-account Lambda.
36
+ if (enableDnsResolution) {
37
+ new AwsCustomResource(this, "EnableRequesterDns", {
38
+ onCreate: {
39
+ service: "EC2",
40
+ action: "modifyVpcPeeringConnectionOptions",
41
+ parameters: {
42
+ VpcPeeringConnectionId: this.peering.attrId,
43
+ RequesterPeeringConnectionOptions: {
44
+ AllowDnsResolutionFromRemoteVpc: true
45
+ }
46
+ },
47
+ physicalResourceId: PhysicalResourceId.of(`${id}-requester-dns`)
48
+ },
49
+ policy: AwsCustomResourcePolicy.fromStatements([
50
+ new PolicyStatement({
51
+ actions: ["ec2:ModifyVpcPeeringConnectionOptions"],
52
+ resources: [
53
+ Stack.of(this).formatArn({
54
+ service: "ec2",
55
+ resource: "vpc-peering-connection",
56
+ resourceName: this.peering.attrId
57
+ })
58
+ ]
59
+ })
60
+ ])
61
+ });
62
+ }
63
+ const hasPeerRoleArn = props.peerRoleArn !== undefined;
64
+ const hasPeerRegion = props.peerRegion !== undefined;
65
+ const hasPeerRouteTableIds = props.peerRouteTableIds !== undefined &&
66
+ props.peerRouteTableIds.length > 0;
67
+ const presentCount = Number(hasPeerRoleArn) +
68
+ Number(hasPeerRegion) +
69
+ Number(hasPeerRouteTableIds);
70
+ if (presentCount > 0 && presentCount < 3) {
71
+ const missing = [];
72
+ if (!hasPeerRoleArn)
73
+ missing.push("peerRoleArn");
74
+ if (!hasPeerRegion)
75
+ missing.push("peerRegion");
76
+ if (!hasPeerRouteTableIds)
77
+ missing.push("peerRouteTableIds");
78
+ throw new Error(`VpcPeeringConnection: cross-account return routes require all of ` +
79
+ `peerRoleArn, peerRegion, and peerRouteTableIds (non-empty). Missing: ${missing.join(", ")}.`);
80
+ }
81
+ if (props.peerRoleArn !== undefined &&
82
+ props.peerRegion !== undefined &&
83
+ props.peerRouteTableIds !== undefined &&
84
+ props.peerRouteTableIds.length > 0) {
85
+ new CrossAccountReturnRoutes(this, "ReturnRoutes", {
86
+ peerRoleArn: props.peerRoleArn,
87
+ peerRegion: props.peerRegion,
88
+ routeTableIds: props.peerRouteTableIds,
89
+ localVpcCidr: props.localVpcCidr,
90
+ peeringConnectionId: this.peering.attrId,
91
+ enableDns: enableDnsResolution
92
+ });
93
+ }
94
+ Tags.of(this).add("fjall:resource:type", "vpc-peering");
95
+ Tags.of(this).add("fjall:peering:peer-vpc", props.peerVpcId);
96
+ if (props.peerAccountId) {
97
+ Tags.of(this).add("fjall:peering:peer-account", props.peerAccountId);
98
+ }
99
+ if (props.peerAppName) {
100
+ Tags.of(this).add("fjall:peering:peer-app", props.peerAppName);
101
+ }
102
+ Tags.of(this).add(COST_ALLOCATION_TAGS.ENVIRONMENT, props.costAllocationEnvironment ?? DEFAULT_COST_ALLOCATION_ENVIRONMENT);
103
+ Tags.of(this).add(COST_ALLOCATION_TAGS.SERVICE, "vpcPeering");
104
+ Tags.of(this).add(COST_ALLOCATION_TAGS.DOMAIN, props.costAllocationDomain ?? props.peerAppName ?? props.peerVpcId);
105
+ }
106
+ }
@@ -1,17 +1,28 @@
1
1
  import { Construct } from "constructs";
2
+ import { type IFunction } from "aws-cdk-lib/aws-lambda";
2
3
  import { LambdaFunction } from "../compute/lambda.js";
3
- export interface CostAllocationTagActivatorProps {
4
- /** EventBridge schedule expression. Default: "rate(24 hours)" */
5
- scheduleExpression?: string;
6
- }
7
4
  /**
8
5
  * Deploys a Lambda that auto-discovers and activates cost allocation tags.
9
6
  *
10
7
  * Runs daily in the management account. Any non-AWS tag applied to resources
11
8
  * (via app.addTags() or CDK aspects) is automatically activated in Cost
12
9
  * Explorer within 24 hours — no manual intervention required.
10
+ *
11
+ * The schedule is NOT wired by this construct — callers wire the cadence via
12
+ * `app.addSchedule(...)` so the EventBridge rule lives in the App's messaging
13
+ * stack alongside every other Fjall schedule (D9). The activator implements
14
+ * the structural `LambdaComputeShape` (duck-typed by `eventTargets.ts`), so it
15
+ * can be passed directly as `target` to `app.addSchedule(...)` without a
16
+ * `LambdaCompute` wrapper.
13
17
  */
14
18
  export declare class CostAllocationTagActivator extends Construct {
19
+ /** Marks this construct as a structural Lambda target for `eventTargets.ts`. */
20
+ readonly computeType: "lambda";
15
21
  readonly lambda: LambdaFunction;
16
- constructor(scope: Construct, id: string, props?: CostAllocationTagActivatorProps);
22
+ constructor(scope: Construct, id: string);
23
+ /**
24
+ * Structural `LambdaComputeShape` accessor — returns the activator's Lambda
25
+ * so `eventTargets.ts#resolveTarget` can wire it as an EventBridge target.
26
+ */
27
+ getFunction(): IFunction;
17
28
  }
@@ -8,12 +8,20 @@ import { LambdaFunction } from "../compute/lambda.js";
8
8
  * Runs daily in the management account. Any non-AWS tag applied to resources
9
9
  * (via app.addTags() or CDK aspects) is automatically activated in Cost
10
10
  * Explorer within 24 hours — no manual intervention required.
11
+ *
12
+ * The schedule is NOT wired by this construct — callers wire the cadence via
13
+ * `app.addSchedule(...)` so the EventBridge rule lives in the App's messaging
14
+ * stack alongside every other Fjall schedule (D9). The activator implements
15
+ * the structural `LambdaComputeShape` (duck-typed by `eventTargets.ts`), so it
16
+ * can be passed directly as `target` to `app.addSchedule(...)` without a
17
+ * `LambdaCompute` wrapper.
11
18
  */
12
19
  export class CostAllocationTagActivator extends Construct {
20
+ /** Marks this construct as a structural Lambda target for `eventTargets.ts`. */
21
+ computeType = "lambda";
13
22
  lambda;
14
- constructor(scope, id, props) {
23
+ constructor(scope, id) {
15
24
  super(scope, id);
16
- const schedule = props?.scheduleExpression ?? "rate(24 hours)";
17
25
  this.lambda = new LambdaFunction(this, "TagActivatorFunction", {
18
26
  runtime: Runtime.NODEJS_22_X,
19
27
  handler: "index.handler",
@@ -21,7 +29,6 @@ export class CostAllocationTagActivator extends Construct {
21
29
  lambdaDescription: "Auto-discovers and activates cost allocation tags in Cost Explorer",
22
30
  memorySize: 128,
23
31
  timeout: 60,
24
- scheduleExpression: schedule,
25
32
  inlinePolicy: [
26
33
  new PolicyStatement({
27
34
  effect: Effect.ALLOW,
@@ -34,6 +41,13 @@ export class CostAllocationTagActivator extends Construct {
34
41
  ]
35
42
  });
36
43
  }
44
+ /**
45
+ * Structural `LambdaComputeShape` accessor — returns the activator's Lambda
46
+ * so `eventTargets.ts#resolveTarget` can wire it as an EventBridge target.
47
+ */
48
+ getFunction() {
49
+ return this.lambda;
50
+ }
37
51
  }
38
52
  const HANDLER_CODE = `
39
53
  const { CostExplorerClient, ListCostAllocationTagsCommand, UpdateCostAllocationTagsStatusCommand } = require("@aws-sdk/client-cost-explorer");
@@ -2,4 +2,4 @@ export { Organisation as OrganisationResource, type OrganisationProps as Organis
2
2
  export { type OrganisationalUnitProps } from "./organisationalUnit.js";
3
3
  export { OrganisationAccount, type OrganisationAccountProps } from "./organisationAccount.js";
4
4
  export { OrganisationPolicy, type OrganisationPolicyProps, type OrganisationPolicyType } from "./organisationPolicy.js";
5
- export { CostAllocationTagActivator, type CostAllocationTagActivatorProps } from "./costAllocationTagActivator.js";
5
+ export { CostAllocationTagActivator } from "./costAllocationTagActivator.js";
@@ -1,4 +1,5 @@
1
1
  import { Construct } from "constructs";
2
+ import { type KeyValue } from "../../../types.js";
2
3
  export type OrganisationPolicyType = "SERVICE_CONTROL_POLICY" | "TAG_POLICY" | "BACKUP_POLICY" | "AISERVICES_OPT_OUT_POLICY";
3
4
  export interface OrganisationPolicyProps {
4
5
  name: string;
@@ -6,6 +7,7 @@ export interface OrganisationPolicyProps {
6
7
  content: string | Record<string, unknown>;
7
8
  description?: string;
8
9
  targetIds?: string[];
10
+ tags?: KeyValue[];
9
11
  }
10
12
  export declare class OrganisationPolicy extends Construct {
11
13
  readonly policyId: string;
@@ -10,7 +10,7 @@ export class OrganisationPolicy extends Construct {
10
10
  content = JSON.parse(props.content);
11
11
  }
12
12
  catch {
13
- throw new Error(`Invalid JSON in organisation policy "${props.name}": ${props.content.slice(0, 100)}`);
13
+ throw new Error(`Invalid JSON in organisation policy "${props.name}"`);
14
14
  }
15
15
  }
16
16
  else {
@@ -21,7 +21,8 @@ export class OrganisationPolicy extends Construct {
21
21
  type: props.policyType,
22
22
  content,
23
23
  description: props.description,
24
- targetIds: props.targetIds
24
+ targetIds: props.targetIds,
25
+ tags: props.tags?.map((t) => ({ key: t.key, value: t.value }))
25
26
  });
26
27
  this.policyId = policy.attrId;
27
28
  }
@@ -8,6 +8,13 @@ interface SecretProps {
8
8
  secretObjectValue?: {
9
9
  [key: string]: SecretValue;
10
10
  };
11
+ /**
12
+ * Plain-text secret value. WARNING: embedded in the CloudFormation template
13
+ * via `SecretValue.unsafePlainText` — anyone with read access to the synth
14
+ * output, the deploy artefact, or the CFN stack template can recover it.
15
+ * Prefer `generateSecretString` (server-generated, never leaves AWS) or
16
+ * `secretObjectValue` with `SecretValue.ssmSecure(...)` for inputs.
17
+ */
11
18
  secretStringValue?: string;
12
19
  description?: string;
13
20
  aliasName?: string;
@@ -17,15 +17,16 @@ export class Secret extends Construct {
17
17
  return;
18
18
  }
19
19
  // Create KMS key for new secrets only
20
- this.secretsCustomerManagedKey = new CustomerManagedKey(this, `${id}CustomerManagedKey`, {
20
+ const customerManagedKey = new CustomerManagedKey(this, `${id}CustomerManagedKey`, {
21
21
  aliasName: `cmk/${id}`
22
22
  });
23
+ this.secretsCustomerManagedKey = customerManagedKey;
23
24
  /**
24
25
  * If a secretStringValue is provided, use it to create the secret.
25
26
  */
26
27
  const secretStringValue = props.secretStringValue
27
28
  ? {
28
- secretStringValue: SecretValue.unsafePlainText(props.secretStringValue || "")
29
+ secretStringValue: SecretValue.unsafePlainText(props.secretStringValue)
29
30
  }
30
31
  : {};
31
32
  /**
@@ -47,7 +48,7 @@ export class Secret extends Construct {
47
48
  const secretOptions = {
48
49
  secretName: props.secretName,
49
50
  secretObjectValue: props.secretObjectValue,
50
- encryptionKey: this.secretsCustomerManagedKey.key,
51
+ encryptionKey: customerManagedKey.key,
51
52
  description: props.description,
52
53
  ...secretStringValue,
53
54
  ...generateSecretString,