@venturekit/infra 0.0.0-dev.20260514025219 → 0.0.0-dev.20260515022321
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.
- package/dist/cdk/app-stack.d.ts +330 -0
- package/dist/cdk/app-stack.d.ts.map +1 -0
- package/dist/cdk/app-stack.js +875 -0
- package/dist/cdk/app-stack.js.map +1 -0
- package/dist/cdk/config-stack.d.ts +104 -0
- package/dist/cdk/config-stack.d.ts.map +1 -0
- package/dist/cdk/config-stack.js +161 -0
- package/dist/cdk/config-stack.js.map +1 -0
- package/dist/cdk/data-stack.d.ts +198 -0
- package/dist/cdk/data-stack.d.ts.map +1 -0
- package/dist/cdk/data-stack.js +511 -0
- package/dist/cdk/data-stack.js.map +1 -0
- package/dist/cdk/edge-stack.d.ts +91 -0
- package/dist/cdk/edge-stack.d.ts.map +1 -0
- package/dist/cdk/edge-stack.js +364 -0
- package/dist/cdk/edge-stack.js.map +1 -0
- package/dist/cdk/identity-stack.d.ts +98 -0
- package/dist/cdk/identity-stack.d.ts.map +1 -0
- package/dist/cdk/identity-stack.js +254 -0
- package/dist/cdk/identity-stack.js.map +1 -0
- package/dist/cdk/index.d.ts +16 -0
- package/dist/cdk/index.d.ts.map +1 -1
- package/dist/cdk/index.js +17 -0
- package/dist/cdk/index.js.map +1 -1
- package/dist/cdk/messaging-stack.d.ts +109 -0
- package/dist/cdk/messaging-stack.d.ts.map +1 -0
- package/dist/cdk/messaging-stack.js +320 -0
- package/dist/cdk/messaging-stack.js.map +1 -0
- package/dist/cdk/network-stack.d.ts +87 -0
- package/dist/cdk/network-stack.d.ts.map +1 -0
- package/dist/cdk/network-stack.js +265 -0
- package/dist/cdk/network-stack.js.map +1 -0
- package/dist/cdk/shared/cross-stack-refs.d.ts +278 -0
- package/dist/cdk/shared/cross-stack-refs.d.ts.map +1 -0
- package/dist/cdk/shared/cross-stack-refs.js +326 -0
- package/dist/cdk/shared/cross-stack-refs.js.map +1 -0
- package/dist/cdk/shared/lambda-helpers.d.ts +82 -0
- package/dist/cdk/shared/lambda-helpers.d.ts.map +1 -0
- package/dist/cdk/shared/lambda-helpers.js +201 -0
- package/dist/cdk/shared/lambda-helpers.js.map +1 -0
- package/dist/cdk/shared/ssm-keys.d.ts +460 -0
- package/dist/cdk/shared/ssm-keys.d.ts.map +1 -0
- package/dist/cdk/shared/ssm-keys.js +291 -0
- package/dist/cdk/shared/ssm-keys.js.map +1 -0
- package/dist/cdk/stack.d.ts +3 -11
- package/dist/cdk/stack.d.ts.map +1 -1
- package/dist/cdk/stack.js +184 -41
- package/dist/cdk/stack.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier 4 — Messaging stack.
|
|
3
|
+
*
|
|
4
|
+
* Owns the durable, persistent message-routing infrastructure. By
|
|
5
|
+
* design every resource here can outlive an app-stack tear-down:
|
|
6
|
+
* after `vk deploy` rebuilds the app stack, the new consumer
|
|
7
|
+
* Lambdas pick up exactly where the old ones left off because the
|
|
8
|
+
* queue + its in-flight messages survived.
|
|
9
|
+
*
|
|
10
|
+
* Resources:
|
|
11
|
+
*
|
|
12
|
+
* - One `AWS::SQS::Queue` + matching DLQ per `queues[]` intent.
|
|
13
|
+
* Encryption SQS_MANAGED, RETAIN under strict.
|
|
14
|
+
* - One Notify pipeline per `notify[]` intent:
|
|
15
|
+
* - SNS events topic (SES configuration-set destination)
|
|
16
|
+
* - SES `EmailIdentity` (domain or single-address)
|
|
17
|
+
* - Optional Route53 DKIM CNAMEs when `hostedZoneId` is set
|
|
18
|
+
* - SES `ConfigurationSet` + `EventDestination` publishing
|
|
19
|
+
* to the SNS topic
|
|
20
|
+
* - WhatsApp Cloud API token Secrets Manager placeholder
|
|
21
|
+
* when `'whatsapp'` is in `channels`
|
|
22
|
+
* - Two dedicated DLQs: dispatcher-DLQ and bounce-DLQ. The
|
|
23
|
+
* consumer Lambdas live in the app stack but their
|
|
24
|
+
* on-failure DLQs need RETAIN-class durability so
|
|
25
|
+
* operators can drain them on the rare delivery failure.
|
|
26
|
+
*
|
|
27
|
+
* # Lifecycle position
|
|
28
|
+
*
|
|
29
|
+
* Updated occasionally (~monthly): a new queue, a notify-channel
|
|
30
|
+
* toggle, a domain rotation. The contents (in-flight messages)
|
|
31
|
+
* are operationally critical — losing a queue with N messages in
|
|
32
|
+
* flight is a permanent message loss event. Both `DeletionPolicy:
|
|
33
|
+
* Retain` and AWS's lack of a queue-level "deletion protection"
|
|
34
|
+
* flag mean RETAIN is the only durability lever; we set it
|
|
35
|
+
* unconditionally under strict dataSafety.
|
|
36
|
+
*
|
|
37
|
+
* # Public surface (via SSM)
|
|
38
|
+
*
|
|
39
|
+
* - `messagingKeys.queueArn / queueUrl / queueDlqArn /
|
|
40
|
+
* queueVisibilityTimeoutSeconds` per `queues[]` intent
|
|
41
|
+
* - `messagingKeys.notifyDispatcherDlqArn /
|
|
42
|
+
* notifyBounceDlqArn` per `notify[]` intent
|
|
43
|
+
* - `configKeys.notifyEventsTopicArn /
|
|
44
|
+
* notifyConfigurationSetName / whatsappTokenSecretArn` per
|
|
45
|
+
* notify intent. (These straddle the messaging-vs-config
|
|
46
|
+
* boundary in the SSM key namespace because the operator pastes
|
|
47
|
+
* the WhatsApp token by hand and the SES configuration-set name
|
|
48
|
+
* is operator-facing identity, not just plumbing — but they're
|
|
49
|
+
* created here because they're inseparable from the SES /
|
|
50
|
+
* SNS topology.)
|
|
51
|
+
*
|
|
52
|
+
* # What this stack does NOT do
|
|
53
|
+
*
|
|
54
|
+
* - **No consumer Lambdas, no event-source mappings.** The Lambda
|
|
55
|
+
* that pulls from the queue lives in the app stack. The ESM
|
|
56
|
+
* binding it to the queue ALSO lives in the app stack — that
|
|
57
|
+
* way an app-stack redeploy can re-create the ESM cleanly without
|
|
58
|
+
* touching the persistent queue, which is the whole point of the
|
|
59
|
+
* split.
|
|
60
|
+
*
|
|
61
|
+
* - **No EventBridge `Rule`s.** Schedules + their Lambda targets
|
|
62
|
+
* stay together in the app stack — the Rule + the Lambda are
|
|
63
|
+
* inseparable by CDK's permission-grant mechanism, and a Rule on
|
|
64
|
+
* its own (with no targets) is dead infrastructure.
|
|
65
|
+
*
|
|
66
|
+
* - **No IAM grants.** App-stack Lambda-role wiring grants
|
|
67
|
+
* `sqs:SendMessage` / `sqs:ReceiveMessage` / `sns:Publish` /
|
|
68
|
+
* `ses:SendEmail` etc. on the imported messaging-tier resources.
|
|
69
|
+
*
|
|
70
|
+
* # Why the dispatcher / bounce DLQs live HERE not in the app stack
|
|
71
|
+
*
|
|
72
|
+
* Two reasons:
|
|
73
|
+
*
|
|
74
|
+
* 1. They're long-lived diagnostic surfaces. An app-stack
|
|
75
|
+
* redeploy that drops them means losing every accumulated
|
|
76
|
+
* delivery-failure record, which is exactly when the operator
|
|
77
|
+
* needs them most.
|
|
78
|
+
* 2. They're tier-stable. The dispatcher Lambda might rev
|
|
79
|
+
* monthly; its DLQ doesn't.
|
|
80
|
+
*/
|
|
81
|
+
import * as cdk from 'aws-cdk-lib';
|
|
82
|
+
import * as sqs from 'aws-cdk-lib/aws-sqs';
|
|
83
|
+
import * as sns from 'aws-cdk-lib/aws-sns';
|
|
84
|
+
import * as ses from 'aws-cdk-lib/aws-ses';
|
|
85
|
+
import * as route53 from 'aws-cdk-lib/aws-route53';
|
|
86
|
+
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
|
|
87
|
+
import { DATA_SAFETY_CONFIG } from '@venturekit/core';
|
|
88
|
+
import { writeSsm } from './shared/cross-stack-refs.js';
|
|
89
|
+
import { messagingKeys, configKeys } from './shared/ssm-keys.js';
|
|
90
|
+
export class VentureMessagingStack extends cdk.Stack {
|
|
91
|
+
queues = new Map();
|
|
92
|
+
notifyEventsTopics = new Map();
|
|
93
|
+
notifyDispatcherDlqs = new Map();
|
|
94
|
+
notifyBounceDlqs = new Map();
|
|
95
|
+
whatsappTokenSecrets = new Map();
|
|
96
|
+
isStrictRetain;
|
|
97
|
+
removalPolicy;
|
|
98
|
+
constructor(scope, id, props) {
|
|
99
|
+
super(scope, id, props);
|
|
100
|
+
const { projectName, stage, envConfig, infrastructure } = props;
|
|
101
|
+
this.isStrictRetain = DATA_SAFETY_CONFIG[envConfig.dataSafety].removalPolicy === 'retain';
|
|
102
|
+
this.removalPolicy = this.isStrictRetain ? cdk.RemovalPolicy.RETAIN : cdk.RemovalPolicy.DESTROY;
|
|
103
|
+
if (infrastructure.queues) {
|
|
104
|
+
for (const intent of infrastructure.queues) {
|
|
105
|
+
this.createQueue(intent, projectName, stage);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (infrastructure.notify) {
|
|
109
|
+
for (const intent of infrastructure.notify) {
|
|
110
|
+
this.createNotify(intent, projectName, stage);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// ─── SQS ─────────────────────────────────────────────────────────────
|
|
115
|
+
createQueue(intent, projectName, stage) {
|
|
116
|
+
const logicalId = `queue-${intent.id}`;
|
|
117
|
+
const fifoSuffix = intent.type === 'fifo' ? '.fifo' : '';
|
|
118
|
+
// The DLQ name is suffixed `-dlq`; under FIFO both queues need
|
|
119
|
+
// the `.fifo` suffix and FIFO=true.
|
|
120
|
+
const dlq = new sqs.Queue(this, `${logicalId}-dlq`, {
|
|
121
|
+
queueName: `${projectName}-${intent.id}-dlq-${stage}${fifoSuffix}`,
|
|
122
|
+
fifo: intent.type === 'fifo',
|
|
123
|
+
retentionPeriod: cdk.Duration.days(14),
|
|
124
|
+
encryption: sqs.QueueEncryption.SQS_MANAGED,
|
|
125
|
+
// DLQs are the durable record of every message a consumer
|
|
126
|
+
// failed to process. CDK's default removalPolicy for sqs.Queue
|
|
127
|
+
// is DESTROY; under strict dataSafety we promote to RETAIN so
|
|
128
|
+
// post-incident investigation survives any redeploy.
|
|
129
|
+
removalPolicy: this.removalPolicy,
|
|
130
|
+
});
|
|
131
|
+
// Visibility timeout: explicit `visibilityTimeoutSeconds` wins,
|
|
132
|
+
// otherwise compute as 6×handler-timeout (AWS recommended floor
|
|
133
|
+
// for the consumer-Lambda path). The 30s default `intent.timeout`
|
|
134
|
+
// produces 180s VTO, which is plenty of headroom for handlers
|
|
135
|
+
// that occasionally spike.
|
|
136
|
+
const visibilityTimeoutSeconds = intent.visibilityTimeoutSeconds
|
|
137
|
+
?? (intent.timeout ?? 30) * 6;
|
|
138
|
+
const queue = new sqs.Queue(this, logicalId, {
|
|
139
|
+
queueName: `${projectName}-${intent.id}-${stage}${fifoSuffix}`,
|
|
140
|
+
fifo: intent.type === 'fifo',
|
|
141
|
+
visibilityTimeout: cdk.Duration.seconds(visibilityTimeoutSeconds),
|
|
142
|
+
retentionPeriod: cdk.Duration.days(intent.retentionDays ?? 4),
|
|
143
|
+
encryption: sqs.QueueEncryption.SQS_MANAGED,
|
|
144
|
+
deadLetterQueue: {
|
|
145
|
+
queue: dlq,
|
|
146
|
+
maxReceiveCount: intent.maxReceiveCount ?? 3,
|
|
147
|
+
},
|
|
148
|
+
// Same RETAIN rationale as the DLQ. With messaging in its own
|
|
149
|
+
// stack, RETAIN means the queue + every in-flight message
|
|
150
|
+
// survives even an app-stack tear-down — the new app-stack's
|
|
151
|
+
// ESM picks up where the old one left off.
|
|
152
|
+
removalPolicy: this.removalPolicy,
|
|
153
|
+
});
|
|
154
|
+
this.queues.set(intent.id, { queue, dlq });
|
|
155
|
+
writeSsm(this, messagingKeys.queueArn(projectName, stage, intent.id), queue.queueArn, {
|
|
156
|
+
description: `SQS queue ARN for '${intent.id}' — IAM scoping target.`,
|
|
157
|
+
});
|
|
158
|
+
writeSsm(this, messagingKeys.queueUrl(projectName, stage, intent.id), queue.queueUrl, {
|
|
159
|
+
description: `SQS queue URL — what SendMessage callers need.`,
|
|
160
|
+
});
|
|
161
|
+
writeSsm(this, messagingKeys.queueDlqArn(projectName, stage, intent.id), dlq.queueArn, {
|
|
162
|
+
description: `Dead-letter queue ARN for '${intent.id}'.`,
|
|
163
|
+
});
|
|
164
|
+
writeSsm(this, messagingKeys.queueVisibilityTimeoutSeconds(projectName, stage, intent.id), String(visibilityTimeoutSeconds), {
|
|
165
|
+
description: `Primary queue VTO seconds. App stack reads this to enforce ` +
|
|
166
|
+
`the 'queue.visibilityTimeout >= 6 * fn.timeout' invariant ` +
|
|
167
|
+
`at synth time when the queue lives in another stack.`,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
// ─── Notify (SES + SNS + WhatsApp + DLQs) ────────────────────────────
|
|
171
|
+
createNotify(intent, projectName, stage) {
|
|
172
|
+
const logicalId = `notify-${intent.id}`;
|
|
173
|
+
const channels = Array.isArray(intent.channels) ? intent.channels : [];
|
|
174
|
+
const configurationSetName = intent.configurationSetName ?? `${projectName}-${stage}-notify-${intent.id}`;
|
|
175
|
+
// ── SNS events topic ─────────────────────────────────────────
|
|
176
|
+
// Receives every SES event for this configuration set. Subscribed
|
|
177
|
+
// by the bounce-handler Lambda (in app stack) and optionally by
|
|
178
|
+
// operator-attached observability tools. We don't pin a CMK —
|
|
179
|
+
// AWS-managed encryption is fine for events that contain at most
|
|
180
|
+
// recipient PII, and a per-topic CMK would add cost + key-policy
|
|
181
|
+
// maintenance for no operational benefit.
|
|
182
|
+
const eventsTopic = new sns.Topic(this, `${logicalId}-events`, {
|
|
183
|
+
topicName: `${projectName}-${stage}-notify-${intent.id}-events`,
|
|
184
|
+
displayName: `VentureKit notify events for ${intent.id} (${stage})`,
|
|
185
|
+
});
|
|
186
|
+
if (this.isStrictRetain) {
|
|
187
|
+
const cfn = eventsTopic.node.defaultChild;
|
|
188
|
+
cfn.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.RETAIN;
|
|
189
|
+
cfn.cfnOptions.updateReplacePolicy = cdk.CfnDeletionPolicy.RETAIN;
|
|
190
|
+
}
|
|
191
|
+
this.notifyEventsTopics.set(intent.id, eventsTopic);
|
|
192
|
+
writeSsm(this, configKeys.notifyEventsTopicArn(projectName, stage, intent.id), eventsTopic.topicArn, { description: `SES events SNS topic for notify '${intent.id}'.` });
|
|
193
|
+
// ── SES email identity ───────────────────────────────────────
|
|
194
|
+
if (intent.domain) {
|
|
195
|
+
const domainIdentity = new ses.EmailIdentity(this, `${logicalId}-domain`, {
|
|
196
|
+
identity: ses.Identity.domain(intent.domain),
|
|
197
|
+
dkimSigning: true,
|
|
198
|
+
// Bounce/complaint feedback flows through the configuration
|
|
199
|
+
// set event destination instead — no need for SES to forward
|
|
200
|
+
// every bounce to the operator's inbox.
|
|
201
|
+
feedbackForwarding: false,
|
|
202
|
+
});
|
|
203
|
+
// CDK exposes the three DKIM token pairs as discrete fields,
|
|
204
|
+
// not arrays. Tuple them so the loop below can stay uniform.
|
|
205
|
+
const dkimTokens = [
|
|
206
|
+
{ name: domainIdentity.dkimDnsTokenName1, value: domainIdentity.dkimDnsTokenValue1 },
|
|
207
|
+
{ name: domainIdentity.dkimDnsTokenName2, value: domainIdentity.dkimDnsTokenValue2 },
|
|
208
|
+
{ name: domainIdentity.dkimDnsTokenName3, value: domainIdentity.dkimDnsTokenValue3 },
|
|
209
|
+
];
|
|
210
|
+
if (intent.hostedZoneId) {
|
|
211
|
+
// Auto-publish the three DKIM CNAMEs when we own the zone.
|
|
212
|
+
// Route53 charges $0.50/zone + $0.40/M queries — these
|
|
213
|
+
// records are queried only by SES so the cost is negligible.
|
|
214
|
+
const zone = route53.HostedZone.fromHostedZoneAttributes(this, `${logicalId}-zone`, { hostedZoneId: intent.hostedZoneId, zoneName: intent.domain });
|
|
215
|
+
dkimTokens.forEach((tok, i) => {
|
|
216
|
+
new route53.CnameRecord(this, `${logicalId}-dkim-record-${i + 1}`, {
|
|
217
|
+
zone,
|
|
218
|
+
// SES tokens are unqualified labels; Route53 appends the
|
|
219
|
+
// zone automatically when `recordName` is unqualified.
|
|
220
|
+
recordName: `${tok.name}._domainkey`,
|
|
221
|
+
domainName: `${tok.value}.dkim.amazonses.com`,
|
|
222
|
+
ttl: cdk.Duration.minutes(5),
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
// When `hostedZoneId` is unset, the operator must publish the
|
|
227
|
+
// three DKIM CNAMEs themselves. We surface the values via SSM
|
|
228
|
+
// (under a doc-only key) on a future iteration; today the
|
|
229
|
+
// operator reads them from `aws ses describe-email-identity`.
|
|
230
|
+
}
|
|
231
|
+
else if (intent.defaultFrom) {
|
|
232
|
+
new ses.EmailIdentity(this, `${logicalId}-email`, {
|
|
233
|
+
identity: ses.Identity.email(intent.defaultFrom),
|
|
234
|
+
// Single-address identities don't support DKIM (SES requires
|
|
235
|
+
// a verified domain for that).
|
|
236
|
+
feedbackForwarding: false,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
throw new Error(`[venturekit] notify intent '${intent.id}' must declare either ` +
|
|
241
|
+
`'defaultFrom' (single-address SES identity) or 'domain' (DomainIdentity).`);
|
|
242
|
+
}
|
|
243
|
+
// ── Configuration set + event destination ────────────────────
|
|
244
|
+
const configSet = new ses.ConfigurationSet(this, `${logicalId}-config-set`, {
|
|
245
|
+
configurationSetName,
|
|
246
|
+
sendingEnabled: true,
|
|
247
|
+
// Reputation metrics surface deliverability stats in CloudWatch
|
|
248
|
+
// — free, useful for operators chasing soft-bounce rates.
|
|
249
|
+
reputationMetrics: true,
|
|
250
|
+
tlsPolicy: ses.ConfigurationSetTlsPolicy.REQUIRE,
|
|
251
|
+
});
|
|
252
|
+
new ses.ConfigurationSetEventDestination(this, `${logicalId}-event-dest`, {
|
|
253
|
+
configurationSet: configSet,
|
|
254
|
+
destination: ses.EventDestination.snsTopic(eventsTopic),
|
|
255
|
+
// Subscribe to bounce/complaint always (suppression logic
|
|
256
|
+
// depends on them) plus delivery/open/click for observability.
|
|
257
|
+
// REJECT is implicit — SES throws synchronously and the
|
|
258
|
+
// dispatcher captures it without an event.
|
|
259
|
+
events: [
|
|
260
|
+
ses.EmailSendingEvent.SEND,
|
|
261
|
+
ses.EmailSendingEvent.REJECT,
|
|
262
|
+
ses.EmailSendingEvent.BOUNCE,
|
|
263
|
+
ses.EmailSendingEvent.COMPLAINT,
|
|
264
|
+
ses.EmailSendingEvent.DELIVERY,
|
|
265
|
+
ses.EmailSendingEvent.OPEN,
|
|
266
|
+
ses.EmailSendingEvent.CLICK,
|
|
267
|
+
],
|
|
268
|
+
enabled: true,
|
|
269
|
+
});
|
|
270
|
+
writeSsm(this, configKeys.notifyConfigurationSetName(projectName, stage, intent.id), configurationSetName, { description: `SES configuration set name — every SendEmail uses it.` });
|
|
271
|
+
// ── WhatsApp token secret ────────────────────────────────────
|
|
272
|
+
if (channels.includes('whatsapp')) {
|
|
273
|
+
if (!intent.whatsapp?.phoneNumberId) {
|
|
274
|
+
throw new Error(`[venturekit] notify intent '${intent.id}' has 'whatsapp' channel ` +
|
|
275
|
+
`but no 'whatsapp.phoneNumberId'. Set it from Meta Business Suite ` +
|
|
276
|
+
`→ WhatsApp → API Setup.`);
|
|
277
|
+
}
|
|
278
|
+
const secret = new secretsmanager.Secret(this, `${logicalId}-whatsapp-token`, {
|
|
279
|
+
secretName: `venturekit/${projectName}/${stage}/notify-${intent.id}-whatsapp-token`,
|
|
280
|
+
description: `Meta WhatsApp Cloud API access token for notify '${intent.id}'. ` +
|
|
281
|
+
`Set the value via the Secrets Manager console after first deploy.`,
|
|
282
|
+
secretStringValue: cdk.SecretValue.unsafePlainText('PLACEHOLDER_SET_VALUE_AFTER_DEPLOY'),
|
|
283
|
+
removalPolicy: this.removalPolicy,
|
|
284
|
+
});
|
|
285
|
+
if (this.isStrictRetain) {
|
|
286
|
+
const cfn = secret.node.defaultChild;
|
|
287
|
+
cfn.cfnOptions.updateReplacePolicy = cdk.CfnDeletionPolicy.RETAIN;
|
|
288
|
+
}
|
|
289
|
+
this.whatsappTokenSecrets.set(intent.id, secret);
|
|
290
|
+
writeSsm(this, configKeys.whatsappTokenSecretArn(projectName, stage, intent.id), secret.secretArn, {
|
|
291
|
+
description: `WhatsApp token Secret ARN. Operators populate via ` +
|
|
292
|
+
`'aws secretsmanager put-secret-value'.`,
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
// ── Dispatcher + bounce DLQs ─────────────────────────────────
|
|
296
|
+
// The dispatcher Lambda (cron-triggered, drains the outbox table
|
|
297
|
+
// and pushes through SES/WhatsApp) and the bounce-handler Lambda
|
|
298
|
+
// (subscribed to the SNS events topic) both live in the app stack.
|
|
299
|
+
// Their on-failure DLQs live HERE because they accumulate
|
|
300
|
+
// diagnostic records across redeploys; losing them is exactly
|
|
301
|
+
// what RETAIN is for.
|
|
302
|
+
const dispatcherDlq = new sqs.Queue(this, `${logicalId}-dispatcher-dlq`, {
|
|
303
|
+
queueName: `${projectName}-${stage}-notify-${intent.id}-dispatcher-dlq`,
|
|
304
|
+
retentionPeriod: cdk.Duration.days(14),
|
|
305
|
+
encryption: sqs.QueueEncryption.SQS_MANAGED,
|
|
306
|
+
removalPolicy: this.removalPolicy,
|
|
307
|
+
});
|
|
308
|
+
const bounceDlq = new sqs.Queue(this, `${logicalId}-bounce-dlq`, {
|
|
309
|
+
queueName: `${projectName}-${stage}-notify-${intent.id}-bounce-dlq`,
|
|
310
|
+
retentionPeriod: cdk.Duration.days(14),
|
|
311
|
+
encryption: sqs.QueueEncryption.SQS_MANAGED,
|
|
312
|
+
removalPolicy: this.removalPolicy,
|
|
313
|
+
});
|
|
314
|
+
this.notifyDispatcherDlqs.set(intent.id, dispatcherDlq);
|
|
315
|
+
this.notifyBounceDlqs.set(intent.id, bounceDlq);
|
|
316
|
+
writeSsm(this, messagingKeys.notifyDispatcherDlqArn(projectName, stage, intent.id), dispatcherDlq.queueArn, { description: `Dispatcher Lambda on-failure DLQ ARN.` });
|
|
317
|
+
writeSsm(this, messagingKeys.notifyBounceDlqArn(projectName, stage, intent.id), bounceDlq.queueArn, { description: `Bounce-handler Lambda on-failure DLQ ARN.` });
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
//# sourceMappingURL=messaging-stack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messaging-stack.js","sourceRoot":"","sources":["../../src/cdk/messaging-stack.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier 0 — Network stack.
|
|
3
|
+
*
|
|
4
|
+
* Owns: VPC, all subnets (public / private-with-egress / isolated),
|
|
5
|
+
* NAT gateways or fck-nat instances, route tables, the gateway VPC
|
|
6
|
+
* endpoints (S3, DynamoDB), the optional interface endpoints
|
|
7
|
+
* (Secrets Manager — by default off until preset opts in), and the
|
|
8
|
+
* VPC flow log destination.
|
|
9
|
+
*
|
|
10
|
+
* # Lifecycle position
|
|
11
|
+
*
|
|
12
|
+
* Updated almost never (~once a year, when AWS rolls a new fck-nat
|
|
13
|
+
* AMI or the operator adds an AZ). Survives stack delete because
|
|
14
|
+
* everything is RETAIN. The data tier (RDS in private subnets) and
|
|
15
|
+
* the app tier (Lambdas in private subnets) both depend on the
|
|
16
|
+
* network tier's published surface; deleting the network stack
|
|
17
|
+
* orphans every subnet ID + VPC ID — recoverable via `cdk import`,
|
|
18
|
+
* never automatic.
|
|
19
|
+
*
|
|
20
|
+
* # Public surface (via SSM)
|
|
21
|
+
*
|
|
22
|
+
* Published exclusively under `networkKeys` in `shared/ssm-keys.ts`:
|
|
23
|
+
*
|
|
24
|
+
* - `vpcId` — the singular VPC ID
|
|
25
|
+
* - `availabilityZones` — comma-joined, ordered
|
|
26
|
+
* - `privateSubnetIds`, `publicSubnetIds`, `isolatedSubnetIds` —
|
|
27
|
+
* comma-joined, ordered to match `availabilityZones`
|
|
28
|
+
*
|
|
29
|
+
* That's it. Consumers never reach in for individual subnets, NAT
|
|
30
|
+
* IDs, or route table IDs — those are private to this stack.
|
|
31
|
+
*
|
|
32
|
+
* # Why no exports?
|
|
33
|
+
*
|
|
34
|
+
* `cdk.CfnOutput` + `Fn::ImportValue` carries CFN's "consumed export
|
|
35
|
+
* cannot be modified" lock. SSM dynamic references don't. See the
|
|
36
|
+
* long-form rationale in `shared/ssm-keys.ts`.
|
|
37
|
+
*
|
|
38
|
+
* # Free-tier handling
|
|
39
|
+
*
|
|
40
|
+
* On the `free` preset, no VPC is provisioned at all (the preset
|
|
41
|
+
* runs DynamoDB + storage-only Lambdas with no in-VPC dependencies,
|
|
42
|
+
* which keeps the deploy at $0/month). The CLI's stack generator
|
|
43
|
+
* therefore must not instantiate `VentureNetworkStack` when the
|
|
44
|
+
* preset resolves to `free` AND no intent demands a VPC. This stack
|
|
45
|
+
* itself never inspects the preset — it always provisions a VPC
|
|
46
|
+
* when constructed. The instantiation gate lives in the generator.
|
|
47
|
+
*/
|
|
48
|
+
import * as cdk from 'aws-cdk-lib';
|
|
49
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
50
|
+
import { Construct } from 'constructs';
|
|
51
|
+
import { type EnvConfig } from '@venturekit/core';
|
|
52
|
+
export interface VentureNetworkStackProps extends cdk.StackProps {
|
|
53
|
+
/**
|
|
54
|
+
* Project name — fed into every resource name and every SSM key
|
|
55
|
+
* for tenant isolation across multi-project AWS accounts.
|
|
56
|
+
*/
|
|
57
|
+
projectName: string;
|
|
58
|
+
/** Stage / well-known env (`dev` | `stage` | `prod` | …). */
|
|
59
|
+
stage: string;
|
|
60
|
+
/**
|
|
61
|
+
* Fully-resolved environment config from
|
|
62
|
+
* `resolveEnvConfig(stage, { preset })`. The network stack reads
|
|
63
|
+
* `vpc.*` (CIDR, subnet masks, NAT type, AZ count, endpoint
|
|
64
|
+
* toggles) and `dataSafety` (drives `removalPolicy` on the flow
|
|
65
|
+
* log group).
|
|
66
|
+
*/
|
|
67
|
+
envConfig: EnvConfig;
|
|
68
|
+
}
|
|
69
|
+
export declare class VentureNetworkStack extends cdk.Stack {
|
|
70
|
+
/**
|
|
71
|
+
* In-process VPC reference for sibling stacks deployed in the
|
|
72
|
+
* same `cdk.App` (the standard `cdk deploy --all` case). Sibling
|
|
73
|
+
* stacks that take a direct CDK reference avoid one round-trip
|
|
74
|
+
* through SSM at synth time and get full CDK-typed access to the
|
|
75
|
+
* VPC abstraction, including AZ + subnet ordering.
|
|
76
|
+
*
|
|
77
|
+
* Cross-deploy and cross-account consumers must instead read the
|
|
78
|
+
* SSM parameters and reconstruct via `importVpc` from
|
|
79
|
+
* `shared/cross-stack-refs.ts` — that path uses
|
|
80
|
+
* `Vpc.fromVpcAttributes` which has slightly fewer affordances
|
|
81
|
+
* than the live reference (no `.selectSubnets({ subnetGroupName })`,
|
|
82
|
+
* for example).
|
|
83
|
+
*/
|
|
84
|
+
readonly vpc: ec2.Vpc;
|
|
85
|
+
constructor(scope: Construct, id: string, props: VentureNetworkStackProps);
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=network-stack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network-stack.d.ts","sourceRoot":"","sources":["../../src/cdk/network-stack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,KAAK,GAAG,MAAM,aAAa,CAAC;AACnC,OAAO,KAAK,GAAG,MAAM,qBAAqB,CAAC;AAE3C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAItE,MAAM,WAAW,wBAAyB,SAAQ,GAAG,CAAC,UAAU;IAC9D;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IAEd;;;;;;OAMG;IACH,SAAS,EAAE,SAAS,CAAC;CACtB;AAwBD,qBAAa,mBAAoB,SAAQ,GAAG,CAAC,KAAK;IAChD;;;;;;;;;;;;;OAaG;IACH,SAAgB,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC;gBAEjB,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,wBAAwB;CAwM1E"}
|