@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.
Files changed (49) hide show
  1. package/dist/cdk/app-stack.d.ts +330 -0
  2. package/dist/cdk/app-stack.d.ts.map +1 -0
  3. package/dist/cdk/app-stack.js +875 -0
  4. package/dist/cdk/app-stack.js.map +1 -0
  5. package/dist/cdk/config-stack.d.ts +104 -0
  6. package/dist/cdk/config-stack.d.ts.map +1 -0
  7. package/dist/cdk/config-stack.js +161 -0
  8. package/dist/cdk/config-stack.js.map +1 -0
  9. package/dist/cdk/data-stack.d.ts +198 -0
  10. package/dist/cdk/data-stack.d.ts.map +1 -0
  11. package/dist/cdk/data-stack.js +511 -0
  12. package/dist/cdk/data-stack.js.map +1 -0
  13. package/dist/cdk/edge-stack.d.ts +91 -0
  14. package/dist/cdk/edge-stack.d.ts.map +1 -0
  15. package/dist/cdk/edge-stack.js +364 -0
  16. package/dist/cdk/edge-stack.js.map +1 -0
  17. package/dist/cdk/identity-stack.d.ts +98 -0
  18. package/dist/cdk/identity-stack.d.ts.map +1 -0
  19. package/dist/cdk/identity-stack.js +254 -0
  20. package/dist/cdk/identity-stack.js.map +1 -0
  21. package/dist/cdk/index.d.ts +16 -0
  22. package/dist/cdk/index.d.ts.map +1 -1
  23. package/dist/cdk/index.js +17 -0
  24. package/dist/cdk/index.js.map +1 -1
  25. package/dist/cdk/messaging-stack.d.ts +109 -0
  26. package/dist/cdk/messaging-stack.d.ts.map +1 -0
  27. package/dist/cdk/messaging-stack.js +320 -0
  28. package/dist/cdk/messaging-stack.js.map +1 -0
  29. package/dist/cdk/network-stack.d.ts +87 -0
  30. package/dist/cdk/network-stack.d.ts.map +1 -0
  31. package/dist/cdk/network-stack.js +265 -0
  32. package/dist/cdk/network-stack.js.map +1 -0
  33. package/dist/cdk/shared/cross-stack-refs.d.ts +278 -0
  34. package/dist/cdk/shared/cross-stack-refs.d.ts.map +1 -0
  35. package/dist/cdk/shared/cross-stack-refs.js +326 -0
  36. package/dist/cdk/shared/cross-stack-refs.js.map +1 -0
  37. package/dist/cdk/shared/lambda-helpers.d.ts +82 -0
  38. package/dist/cdk/shared/lambda-helpers.d.ts.map +1 -0
  39. package/dist/cdk/shared/lambda-helpers.js +201 -0
  40. package/dist/cdk/shared/lambda-helpers.js.map +1 -0
  41. package/dist/cdk/shared/ssm-keys.d.ts +460 -0
  42. package/dist/cdk/shared/ssm-keys.d.ts.map +1 -0
  43. package/dist/cdk/shared/ssm-keys.js +291 -0
  44. package/dist/cdk/shared/ssm-keys.js.map +1 -0
  45. package/dist/cdk/stack.d.ts +3 -11
  46. package/dist/cdk/stack.d.ts.map +1 -1
  47. package/dist/cdk/stack.js +184 -41
  48. package/dist/cdk/stack.js.map +1 -1
  49. 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"}