@venturekit/infra 0.0.48 → 0.0.51

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 (72) hide show
  1. package/README.md +34 -0
  2. package/dist/cdk/app-stack.d.ts +58 -5
  3. package/dist/cdk/app-stack.d.ts.map +1 -1
  4. package/dist/cdk/app-stack.js +218 -43
  5. package/dist/cdk/app-stack.js.map +1 -1
  6. package/dist/cdk/compute-stack.d.ts +3 -0
  7. package/dist/cdk/compute-stack.d.ts.map +1 -1
  8. package/dist/cdk/compute-stack.js +16 -1
  9. package/dist/cdk/compute-stack.js.map +1 -1
  10. package/dist/cdk/config-stack.d.ts.map +1 -1
  11. package/dist/cdk/config-stack.js +2 -0
  12. package/dist/cdk/config-stack.js.map +1 -1
  13. package/dist/cdk/data-stack.d.ts +15 -1
  14. package/dist/cdk/data-stack.d.ts.map +1 -1
  15. package/dist/cdk/data-stack.js +120 -18
  16. package/dist/cdk/data-stack.js.map +1 -1
  17. package/dist/cdk/edge-stack.d.ts +2 -0
  18. package/dist/cdk/edge-stack.d.ts.map +1 -1
  19. package/dist/cdk/edge-stack.js +15 -0
  20. package/dist/cdk/edge-stack.js.map +1 -1
  21. package/dist/cdk/identity-stack.d.ts.map +1 -1
  22. package/dist/cdk/identity-stack.js +13 -3
  23. package/dist/cdk/identity-stack.js.map +1 -1
  24. package/dist/cdk/migration-runner.d.ts +16 -0
  25. package/dist/cdk/migration-runner.d.ts.map +1 -1
  26. package/dist/cdk/migration-runner.js +22 -2
  27. package/dist/cdk/migration-runner.js.map +1 -1
  28. package/dist/cdk/network-stack.d.ts +8 -0
  29. package/dist/cdk/network-stack.d.ts.map +1 -1
  30. package/dist/cdk/network-stack.js +20 -0
  31. package/dist/cdk/network-stack.js.map +1 -1
  32. package/dist/cdk/services-stack.d.ts +5 -0
  33. package/dist/cdk/services-stack.d.ts.map +1 -1
  34. package/dist/cdk/services-stack.js +30 -5
  35. package/dist/cdk/services-stack.js.map +1 -1
  36. package/dist/cdk/shared/admin-routes.d.ts +8 -9
  37. package/dist/cdk/shared/admin-routes.d.ts.map +1 -1
  38. package/dist/cdk/shared/admin-routes.js +12 -38
  39. package/dist/cdk/shared/admin-routes.js.map +1 -1
  40. package/dist/cdk/shared/internal-routes.d.ts +17 -0
  41. package/dist/cdk/shared/internal-routes.d.ts.map +1 -0
  42. package/dist/cdk/shared/internal-routes.js +127 -0
  43. package/dist/cdk/shared/internal-routes.js.map +1 -0
  44. package/dist/cdk/shared/lambda-helpers.d.ts +1 -14
  45. package/dist/cdk/shared/lambda-helpers.d.ts.map +1 -1
  46. package/dist/cdk/shared/lambda-helpers.js +2 -24
  47. package/dist/cdk/shared/lambda-helpers.js.map +1 -1
  48. package/dist/cdk/shared/otel-layer.d.ts +23 -0
  49. package/dist/cdk/shared/otel-layer.d.ts.map +1 -0
  50. package/dist/cdk/shared/otel-layer.js +77 -0
  51. package/dist/cdk/shared/otel-layer.js.map +1 -0
  52. package/dist/cdk/shared/ssm-keys.d.ts +50 -4
  53. package/dist/cdk/shared/ssm-keys.d.ts.map +1 -1
  54. package/dist/cdk/shared/ssm-keys.js +30 -2
  55. package/dist/cdk/shared/ssm-keys.js.map +1 -1
  56. package/dist/cdk/shared/websocket-construct.d.ts +8 -0
  57. package/dist/cdk/shared/websocket-construct.d.ts.map +1 -1
  58. package/dist/cdk/shared/websocket-construct.js +7 -2
  59. package/dist/cdk/shared/websocket-construct.js.map +1 -1
  60. package/dist/cdk/shared-network-stack.d.ts +44 -0
  61. package/dist/cdk/shared-network-stack.d.ts.map +1 -0
  62. package/dist/cdk/shared-network-stack.js +61 -0
  63. package/dist/cdk/shared-network-stack.js.map +1 -0
  64. package/dist/index.d.ts +2 -0
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +1 -0
  67. package/dist/index.js.map +1 -1
  68. package/dist/venture.d.ts +8 -1
  69. package/dist/venture.d.ts.map +1 -1
  70. package/dist/venture.js +9 -0
  71. package/dist/venture.js.map +1 -1
  72. package/package.json +2 -2
package/README.md CHANGED
@@ -294,6 +294,40 @@ Changing `natType` on an existing deployment causes CloudFormation to
294
294
  replace the NAT resource (brief data-plane outage during deploy). The
295
295
  VPC itself is not replaced and all other resources stay put.
296
296
 
297
+ ## OpenTelemetry tracing (`lambda.otel`)
298
+
299
+ Set `lambda.otel` in an environment config to trace every route, queue,
300
+ cron and function Lambda with the AWS Lambda Layer for OpenTelemetry:
301
+
302
+ ```typescript
303
+ // config/prod.ts
304
+ export const prod = {
305
+ preset: 'medium',
306
+ lambda: {
307
+ otel: {
308
+ enabled: true,
309
+ // serviceName: 'cms-api', // OTEL_SERVICE_NAME, default `<project>-<stage>`
310
+ // applicationSignals: true, // CloudWatch Application Signals metrics too
311
+ // layerArn: 'arn:aws:lambda:…', // pin a layer version
312
+ },
313
+ },
314
+ };
315
+ ```
316
+
317
+ The stack adds AWS's `AWSOpenTelemetryDistroJs` layer for its region (it
318
+ counts toward the 5-layer limit), sets `AWS_LAMBDA_EXEC_WRAPPER=/opt/otel-instrument`,
319
+ `OTEL_SERVICE_NAME` and `OTEL_AWS_APPLICATION_SIGNALS_ENABLED`, and turns
320
+ on X-Ray active tracing. HTTP, AWS SDK and `pg` calls are traced
321
+ automatically. Spans an app opens with the registered tracer go to X-Ray
322
+ too: `otelTracer()` from `@venturekit-pro/ai` gives one, and passing it to
323
+ the LLM gateway, the agent loop or the harness traces model calls, agents,
324
+ tools and graph nodes. With `applicationSignals: true` the execution roles
325
+ get `CloudWatchLambdaApplicationSignalsExecutionRolePolicy`; Application
326
+ Signals must be enabled once in the account (CloudWatch console). The
327
+ built-in layer versions are those AWS published in October 2026. Pin a
328
+ newer one with `layerArn`. A region with no published layer needs
329
+ `layerArn`.
330
+
297
331
  ## API
298
332
 
299
333
  ### `defineVenture(definition)`
@@ -87,6 +87,12 @@ export interface AppStackImports {
87
87
  * functions.
88
88
  */
89
89
  vpc?: ec2.IVpc;
90
+ /**
91
+ * The VPC's INTERNAL CLIENTS security group (network tier): every Lambda
92
+ * joins it, which is what admits it to the VPC's internal service ports
93
+ * (`expose: 'vpc'`) — its own venture's and, in a shared VPC, the others'.
94
+ */
95
+ internalClientsSecurityGroupId?: string;
90
96
  /**
91
97
  * HttpApi imported from the edge stack via
92
98
  * `HttpApi.fromHttpApiAttributes({ httpApiId, apiEndpoint })`.
@@ -218,7 +224,12 @@ export interface AppStackImports {
218
224
  host: string;
219
225
  port: string;
220
226
  name: string;
227
+ /** The secret functions connect with — the APP login when provisioned. */
221
228
  secretArn?: string;
229
+ /** The SYSTEM login's secret — only the functions `systemFunctions` selects read it. */
230
+ systemSecretArn?: string;
231
+ /** `databases[].logins.system.functions` patterns. */
232
+ systemFunctions?: string[];
222
233
  }>;
223
234
  /**
224
235
  * Per-database connection params (RDS SG id + numeric port) used
@@ -362,10 +373,26 @@ export declare class VentureAppStack extends cdk.Stack {
362
373
  * single-role layout, where the shared role holds the admin grants.
363
374
  */
364
375
  readonly authAdminRole?: iam.Role;
376
+ /**
377
+ * Execution roles of the functions that connect as the SYSTEM database
378
+ * login (`databases[].logins.system.functions`): the only roles that may
379
+ * read its secret. Kept apart from the shared role so no app-login
380
+ * function — whatever runs in it — can fetch the system credential.
381
+ */
382
+ readonly dbSystemRole?: iam.Role;
383
+ readonly authAdminDbSystemRole?: iam.Role;
384
+ /** `logins.system.functions` of the primary database. */
385
+ private readonly systemLoginPatterns;
386
+ /** The primary database's two secrets, when the two logins are provisioned. */
387
+ private readonly dbLoginSecrets?;
365
388
  /** `adminRoutes` patterns collected across every auth intent. */
366
389
  private readonly adminRoutePatterns;
390
+ /** `auth[].adminRoutes: 'all'` — the explicit legacy layout (admin grants on the shared role). */
391
+ private readonly legacyAdminGrants;
367
392
  /** Shared SG when a VPC is imported; undefined for VPC-less projects. */
368
393
  readonly lambdaSecurityGroup?: ec2.SecurityGroup;
394
+ /** The VPC's internal clients group (see `AppStackImports.internalClientsSecurityGroupId`). */
395
+ readonly internalClientsSecurityGroup?: ec2.ISecurityGroup;
369
396
  /** Internal HMAC signing secret for Lambda-to-Lambda `invoke()`. */
370
397
  readonly internalHmacSecret: secretsmanager.Secret;
371
398
  /**
@@ -410,8 +437,10 @@ export declare class VentureAppStack extends cdk.Stack {
410
437
  private readonly stage;
411
438
  /** Ids of the imported RDS databases — logical `DBInstanceIdentifier` alarm dimensions. */
412
439
  private readonly rdsDatabaseIds;
413
- /** `envConfig.lambda.layers`, attached to every route / queue / cron / function Lambda. */
440
+ /** `envConfig.lambda.layers` (+ the OpenTelemetry layer), attached to every route / queue / cron / function Lambda. */
414
441
  private readonly lambdaLayers;
442
+ /** X-Ray active tracing: `lambda.tracingEnabled`, or forced on by `lambda.otel`. */
443
+ private readonly tracingActive;
415
444
  /**
416
445
  * Resolved custom-sender KMS key ARN per declaring auth intent —
417
446
  * `imports.customSenderKmsKeyArnsByAuthId` merged with the
@@ -488,23 +517,47 @@ export declare class VentureAppStack extends cdk.Stack {
488
517
  * cross-stack pattern works the same as in-stack.
489
518
  */
490
519
  private createRouteFunction;
520
+ /** Every Lambda's groups: its own, and the VPC's internal clients group. */
521
+ private get lambdaSecurityGroups();
491
522
  /**
492
523
  * Every execution role in this stack: the shared role, plus the
493
524
  * auth-admin role when one exists. Baseline grants (secrets, S3,
494
525
  * SES, rate-limit table, …) are applied to all of them.
495
526
  */
496
527
  private get executionRoles();
528
+ /** The roles whose functions connect as the system database login. */
529
+ private get systemLoginRoles();
530
+ /**
531
+ * The role for a function: Cognito admin or not (`auth[].adminRoutes`),
532
+ * system database login or not (`databases[].logins.system.functions`).
533
+ */
534
+ private roleFor;
535
+ /** The database env a function running as `role` gets on top of the base env. */
536
+ private loginEnvFor;
497
537
  /**
498
- * Roles that receive the Cognito admin grants: only the auth-admin
499
- * role when `adminRoutes` are declared, otherwise the shared role
500
- * (historical layout).
538
+ * Roles that receive the Cognito admin grants: the shared role under
539
+ * the explicit legacy layout (`adminRoutes: 'all'`), the auth-admin role
540
+ * when routes are listed, and none otherwise.
501
541
  */
502
542
  private get cognitoAdminRoles();
503
543
  /** Apply one grant to every execution role. */
504
544
  private grantEachRole;
545
+ /**
546
+ * Caches: the data stack's cache security group admits THIS stack's
547
+ * Lambda security group only, and every Lambda gets the endpoint and
548
+ * its AUTH token's secret (`VENTURE_CACHE_<ID>_HOST` / `_PORT` /
549
+ * `_AUTH_SECRET_ARN`; `cacheConnection(id)` in `@venturekit/runtime`
550
+ * turns them into TLS + AUTH connection options).
551
+ */
552
+ private wireCaches;
553
+ /**
554
+ * Internal routes (`internal` intent): the pair secrets this venture keeps
555
+ * for its callers, and the rights to call the ventures it calls.
556
+ */
557
+ private wireInternalRoutes;
505
558
  /** The role a route Lambda runs as — auth-admin when its API path matches `adminRoutes`. */
506
559
  private roleForRoute;
507
- /** The role a standalone / queue / schedule Lambda runs as — auth-admin when `fn:<id>` matches. */
560
+ /** The role a standalone / queue / schedule Lambda runs as (`fn:<id>`). */
508
561
  private roleForFunction;
509
562
  /**
510
563
  * Build a Lambda function with the standard app-stack properties
@@ -1 +1 @@
1
- {"version":3,"file":"app-stack.d.ts","sourceRoot":"","sources":["../../src/cdk/app-stack.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app-stack.d.ts","sourceRoot":"","sources":["../../src/cdk/app-stack.ts"],"names":[],"mappings":"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"}
@@ -87,10 +87,13 @@ import * as cloudwatchActions from 'aws-cdk-lib/aws-cloudwatch-actions';
87
87
  import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
88
88
  import * as logs from 'aws-cdk-lib/aws-logs';
89
89
  import { DATA_SAFETY_CONFIG, isExternalAuthIntent, } from '@venturekit/core';
90
- import { collectAdminRoutePatterns, matchesAdminRoute } from './shared/admin-routes.js';
91
- import { readSsmString } from './shared/cross-stack-refs.js';
90
+ import { collectAdminRoutePatterns, matchesAdminRoute, usesLegacyAdminGrants } from './shared/admin-routes.js';
91
+ import { isInternalRoute, matchesFunctionPattern } from '@venturekit/core';
92
+ import { createInternalCallerSecrets, internalCallStatements } from './shared/internal-routes.js';
93
+ import { readSsmString, writeSsm } from './shared/cross-stack-refs.js';
94
+ import { APPLICATION_SIGNALS_POLICY, defaultOtelLayerArn, otelEnvironment } from './shared/otel-layer.js';
92
95
  import { grantCustomSenderInvoke, resolveCustomSender } from './shared/custom-sender.js';
93
- import { networkKeys, edgeKeys, identityKeys, dataKeys } from './shared/ssm-keys.js';
96
+ import { networkKeys, edgeKeys, identityKeys, dataKeys, internalKeys } from './shared/ssm-keys.js';
94
97
  import { bundleHandlerCodeWithEsbuild, inlineStubLambdaCode, toLambdaArchitecture, toLambdaRuntime, toLogRetention, clampLambdaFunctionName, uniqueLogGroupName, discoverFunctionFiles, } from './shared/lambda-helpers.js';
95
98
  import { discoverRouteFiles, } from './shared/route-discovery.js';
96
99
  import { discoverWsRoutes } from './shared/ws-discovery.js';
@@ -168,10 +171,26 @@ export class VentureAppStack extends cdk.Stack {
168
171
  * single-role layout, where the shared role holds the admin grants.
169
172
  */
170
173
  authAdminRole;
174
+ /**
175
+ * Execution roles of the functions that connect as the SYSTEM database
176
+ * login (`databases[].logins.system.functions`): the only roles that may
177
+ * read its secret. Kept apart from the shared role so no app-login
178
+ * function — whatever runs in it — can fetch the system credential.
179
+ */
180
+ dbSystemRole;
181
+ authAdminDbSystemRole;
182
+ /** `logins.system.functions` of the primary database. */
183
+ systemLoginPatterns;
184
+ /** The primary database's two secrets, when the two logins are provisioned. */
185
+ dbLoginSecrets;
171
186
  /** `adminRoutes` patterns collected across every auth intent. */
172
187
  adminRoutePatterns;
188
+ /** `auth[].adminRoutes: 'all'` — the explicit legacy layout (admin grants on the shared role). */
189
+ legacyAdminGrants;
173
190
  /** Shared SG when a VPC is imported; undefined for VPC-less projects. */
174
191
  lambdaSecurityGroup;
192
+ /** The VPC's internal clients group (see `AppStackImports.internalClientsSecurityGroupId`). */
193
+ internalClientsSecurityGroup;
175
194
  /** Internal HMAC signing secret for Lambda-to-Lambda `invoke()`. */
176
195
  internalHmacSecret;
177
196
  /**
@@ -216,8 +235,10 @@ export class VentureAppStack extends cdk.Stack {
216
235
  stage;
217
236
  /** Ids of the imported RDS databases — logical `DBInstanceIdentifier` alarm dimensions. */
218
237
  rdsDatabaseIds;
219
- /** `envConfig.lambda.layers`, attached to every route / queue / cron / function Lambda. */
238
+ /** `envConfig.lambda.layers` (+ the OpenTelemetry layer), attached to every route / queue / cron / function Lambda. */
220
239
  lambdaLayers;
240
+ /** X-Ray active tracing: `lambda.tracingEnabled`, or forced on by `lambda.otel`. */
241
+ tracingActive;
221
242
  /**
222
243
  * Resolved custom-sender KMS key ARN per declaring auth intent —
223
244
  * `imports.customSenderKmsKeyArnsByAuthId` merged with the
@@ -301,11 +322,24 @@ export class VentureAppStack extends cdk.Stack {
301
322
  this.stage = stage;
302
323
  this.rdsDatabaseIds = new Set(imports.databaseEndpointsById?.keys() ?? []);
303
324
  this.envConfig = envConfig;
304
- const layerArns = envConfig.lambda.layers ?? [];
325
+ const otel = envConfig.lambda.otel?.enabled ? envConfig.lambda.otel : undefined;
326
+ let otelLayerArn;
327
+ if (otel) {
328
+ const region = cdk.Stack.of(this).region;
329
+ otelLayerArn =
330
+ otel.layerArn ?? (cdk.Token.isUnresolved(region) ? undefined : defaultOtelLayerArn(region));
331
+ if (!otelLayerArn) {
332
+ throw new Error(cdk.Token.isUnresolved(region)
333
+ ? `[venturekit] lambda.otel: the stack has no concrete region to pick the AWS OpenTelemetry layer — set lambda.otel.layerArn.`
334
+ : `[venturekit] lambda.otel: AWS publishes no OpenTelemetry layer for '${region}' — set lambda.otel.layerArn.`);
335
+ }
336
+ }
337
+ this.tracingActive = envConfig.lambda.tracingEnabled || Boolean(otel);
338
+ const layerArns = [...(envConfig.lambda.layers ?? []), ...(otelLayerArn ? [otelLayerArn] : [])];
305
339
  if (layerArns.length > 5) {
306
- throw new Error(`[venturekit] lambda.layers has ${layerArns.length} ARNs; Lambda allows at most 5.`);
340
+ throw new Error(`[venturekit] lambda.layers has ${layerArns.length} ARNs${otel ? ' (with the OpenTelemetry layer)' : ''}; Lambda allows at most 5.`);
307
341
  }
308
- this.lambdaLayers = layerArns.map((arn, i) => lambda.LayerVersion.fromLayerVersionArn(this, `lambda-layer-${i}`, arn));
342
+ this.lambdaLayers = layerArns.map((arn, i) => lambda.LayerVersion.fromLayerVersionArn(this, arn === otelLayerArn && i === layerArns.length - 1 ? 'lambda-layer-otel' : `lambda-layer-${i}`, arn));
309
343
  this.skipBundling = props.skipBundling ?? false;
310
344
  this.projectDir = props.projectDir;
311
345
  // Stamp once per synth so every route Lambda in this deploy reports
@@ -344,7 +378,13 @@ export class VentureAppStack extends cdk.Stack {
344
378
  // CFN's 500-resource limit on large projects is the reason the
345
379
  // per-function layout was never adopted.
346
380
  this.adminRoutePatterns = collectAdminRoutePatterns(infrastructure.auth ?? []);
347
- if (this.adminRoutePatterns.length > 0) {
381
+ this.legacyAdminGrants = usesLegacyAdminGrants(infrastructure.auth ?? []);
382
+ if (this.legacyAdminGrants) {
383
+ cdk.Annotations.of(this).addWarning(`[venturekit] auth[].adminRoutes is 'all': every Lambda in ${projectName}/${stage} shares one role ` +
384
+ `that can create users, set passwords and edit attributes on the user pool. List the routes that ` +
385
+ `call @venturekit/auth/server admin flows (e.g. adminRoutes: ['/auth/**']) to confine those grants.`);
386
+ }
387
+ else if (this.adminRoutePatterns.length > 0) {
348
388
  this.authAdminRole = new iam.Role(this, 'AuthAdminRole', {
349
389
  assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
350
390
  description: `Execution role for ${projectName}-${stage} Lambdas allowed to call Cognito admin APIs (auth[].adminRoutes)`,
@@ -354,10 +394,33 @@ export class VentureAppStack extends cdk.Stack {
354
394
  });
355
395
  }
356
396
  else if ((infrastructure.auth ?? []).length > 0) {
357
- cdk.Annotations.of(this).addWarning(`[venturekit] auth intents declare no 'adminRoutes': every Lambda in ${projectName}/${stage} ` +
358
- `shares one role that can create users, set passwords and edit attributes on the user pool. ` +
359
- `List the routes that call @venturekit/auth/server admin flows (e.g. adminRoutes: ['/auth/**']) ` +
360
- `to confine those grants to them.`);
397
+ cdk.Annotations.of(this).addInfo(`[venturekit] auth intents declare no 'adminRoutes': no Lambda in ${projectName}/${stage} can call ` +
398
+ `Cognito admin APIs. Routes that run @venturekit/auth/server admin flows (sign-up, federated ` +
399
+ `sign-in, password reset, …) must be listed in auth[].adminRoutes.`);
400
+ }
401
+ // ─── System-login execution roles (databases[].logins) ──────
402
+ const primaryDb = imports.databaseEndpointsById?.values().next().value;
403
+ this.systemLoginPatterns = (primaryDb?.systemFunctions ?? []).map((p) => p.trim()).filter(Boolean);
404
+ if (primaryDb?.secretArn && primaryDb.systemSecretArn) {
405
+ this.dbLoginSecrets = { app: primaryDb.secretArn, system: primaryDb.systemSecretArn };
406
+ }
407
+ if (this.dbLoginSecrets && this.systemLoginPatterns.length > 0) {
408
+ const executionRole = (id, description) => new iam.Role(this, id, {
409
+ assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
410
+ description,
411
+ managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole')],
412
+ });
413
+ this.dbSystemRole = executionRole('DbSystemRole', `Execution role for ${projectName}-${stage} Lambdas on the system database login (databases[].logins.system)`);
414
+ if (this.authAdminRole) {
415
+ this.authAdminDbSystemRole = executionRole('AuthAdminDbSystemRole', `Execution role for ${projectName}-${stage} Lambdas with Cognito admin grants on the system database login`);
416
+ }
417
+ }
418
+ if (otel?.applicationSignals) {
419
+ // CloudWatch Application Signals: the layer publishes service
420
+ // metrics and traces under this role.
421
+ for (const role of this.executionRoles) {
422
+ role.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName(APPLICATION_SIGNALS_POLICY));
423
+ }
361
424
  }
362
425
  if (this.vpc) {
363
426
  // VPC-attached Lambdas need ENI-creation rights on cold start.
@@ -366,6 +429,9 @@ export class VentureAppStack extends cdk.Stack {
366
429
  for (const role of this.executionRoles) {
367
430
  role.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaVPCAccessExecutionRole'));
368
431
  }
432
+ if (imports.internalClientsSecurityGroupId) {
433
+ this.internalClientsSecurityGroup = ec2.SecurityGroup.fromSecurityGroupId(this, 'InternalClientsSg', imports.internalClientsSecurityGroupId);
434
+ }
369
435
  this.lambdaSecurityGroup = new ec2.SecurityGroup(this, 'LambdaSg', {
370
436
  vpc: this.vpc,
371
437
  description: `Shared SG for ${projectName}-${stage} Lambdas`,
@@ -476,7 +542,18 @@ export class VentureAppStack extends cdk.Stack {
476
542
  // `--enable-source-maps` makes thrown errors point to the
477
543
  // .ts source instead of bundled .js. Free win in CloudWatch.
478
544
  NODE_OPTIONS: '--enable-source-maps',
545
+ // `lambda.otel`: the wrapper starts the layer's OpenTelemetry SDK
546
+ // (it appends its own `--require` to NODE_OPTIONS at startup).
547
+ ...(otel
548
+ ? otelEnvironment({
549
+ serviceName: otel.serviceName ?? `${projectName}-${stage}`,
550
+ applicationSignals: otel.applicationSignals === true,
551
+ })
552
+ : {}),
479
553
  };
554
+ // Caches need the env map (endpoint + AUTH secret) and the Lambda SG.
555
+ this.wireCaches(infrastructure.caches ?? [], projectName, stage);
556
+ this.wireInternalRoutes(infrastructure.internal, projectName, stage);
480
557
  // ─── Cross-tier env injection (cheap, static keys only) ────
481
558
  // Per-intent keys go through helpers in sub-steps 9b/c/d. The
482
559
  // ones below are stack-wide singletons — primary DB, primary
@@ -503,6 +580,11 @@ export class VentureAppStack extends cdk.Stack {
503
580
  if (primaryIntent?.tenantRole) {
504
581
  this.baseEnvVars['DB_TENANT_ROLE'] = primaryIntent.tenantRole;
505
582
  }
583
+ // Two logins: every function is on the APP login unless its role is a
584
+ // system-login one (`loginEnvFor` switches the secret and DB_LOGIN).
585
+ if (primary.systemSecretArn) {
586
+ this.baseEnvVars['DB_LOGIN'] = 'app';
587
+ }
506
588
  }
507
589
  if (imports.storageBucketNamesById && imports.storageBucketNamesById.size > 0) {
508
590
  const [, primaryBucket] = imports.storageBucketNamesById.entries().next().value;
@@ -567,6 +649,13 @@ export class VentureAppStack extends cdk.Stack {
567
649
  this.baseEnvVars[`${prefix}_USER_POOL_ID`] = poolId;
568
650
  if (clientId)
569
651
  this.baseEnvVars[`${prefix}_APP_CLIENT_ID`] = clientId;
652
+ // The primary client's refresh-token rotation, so `refreshSession`
653
+ // takes the rotating flow (`@venturekit/auth` `loadAuthServerConfig`).
654
+ if (intent.clients?.[0]?.refreshTokenRotation?.enabled) {
655
+ this.baseEnvVars[`${prefix}_REFRESH_TOKEN_ROTATION`] = 'true';
656
+ if (intent === (infrastructure.auth ?? [])[0])
657
+ this.baseEnvVars['COGNITO_REFRESH_TOKEN_ROTATION'] = 'true';
658
+ }
570
659
  }
571
660
  this.baseEnvVars[`${prefix}_REGION`] = cdk.Stack.of(this).region;
572
661
  }
@@ -723,14 +812,14 @@ export class VentureAppStack extends cdk.Stack {
723
812
  this.baseEnvVars['COGNITO_CUSTOM_SENDER_KMS_KEY_ARN'] ??= keyArn;
724
813
  }
725
814
  // ─── Billing provider secret ARNs (billing intents) ─────
726
- // `@venturekit/billing`'s resolveZazuConfig() reads the API key,
815
+ // `@venturekit/billing`'s resolveManzaConfig() reads the API key,
727
816
  // account id, and webhook secret from the Secrets Manager entry named
728
- // by `ZAZU_SECRET_ARN`. Inject it here — the matching read grant is
817
+ // by `MANZA_SECRET_ARN`. Inject it here — the matching read grant is
729
818
  // attached in applyImportedGrants — so a project that declares a
730
819
  // billing intent needs no wiring of its own.
731
820
  //
732
821
  // The env var name is derived from the provider, not the intent id,
733
- // because the runtime resolver is provider-scoped (one Zazu account
822
+ // because the runtime resolver is provider-scoped (one Manza account
734
823
  // per stage). The first declared intent for a given provider wins,
735
824
  // mirroring COGNITO_FEDERATED_<PROVIDER>_SECRET_ARN.
736
825
  if (imports.billingSecretArnsById) {
@@ -738,7 +827,9 @@ export class VentureAppStack extends cdk.Stack {
738
827
  const intent = infrastructure.billing?.find((b) => b.id === id);
739
828
  if (!intent)
740
829
  continue;
741
- const key = `${intent.provider.toUpperCase()}_SECRET_ARN`;
830
+ // `'zazu'` is the deprecated name of `'manza'`.
831
+ const provider = intent.provider === 'zazu' ? 'manza' : intent.provider;
832
+ const key = `${provider.toUpperCase()}_SECRET_ARN`;
742
833
  if (!(key in this.baseEnvVars)) {
743
834
  this.baseEnvVars[key] = arn;
744
835
  }
@@ -785,7 +876,11 @@ export class VentureAppStack extends cdk.Stack {
785
876
  stage,
786
877
  envConfig,
787
878
  lambdaRole: this.lambdaRole,
879
+ roleFor: (routeKey) => this.roleFor({ wsRoute: routeKey }),
880
+ envFor: (routeKey) => this.loginEnvFor(this.roleFor({ wsRoute: routeKey })),
881
+ extraRoles: this.executionRoles.filter((r) => r !== this.lambdaRole),
788
882
  lambdaSecurityGroup: this.lambdaSecurityGroup,
883
+ extraSecurityGroups: this.internalClientsSecurityGroup ? [this.internalClientsSecurityGroup] : [],
789
884
  vpc: this.vpc,
790
885
  baseEnvVars: this.baseEnvVars,
791
886
  skipBundling: this.skipBundling,
@@ -1089,11 +1184,10 @@ export class VentureAppStack extends cdk.Stack {
1089
1184
  environment: {
1090
1185
  ...this.baseEnvVars,
1091
1186
  ...lambdaConfig.environmentVariables,
1187
+ ...this.loginEnvFor(this.roleForRoute(route.apiPath)),
1092
1188
  },
1093
1189
  logGroup,
1094
- tracing: lambdaConfig.tracingEnabled
1095
- ? lambda.Tracing.ACTIVE
1096
- : lambda.Tracing.DISABLED,
1190
+ tracing: this.tracingActive ? lambda.Tracing.ACTIVE : lambda.Tracing.DISABLED,
1097
1191
  reservedConcurrentExecutions: lambdaConfig.reservedConcurrency,
1098
1192
  role: this.roleForRoute(route.apiPath),
1099
1193
  // Attach to the VPC iff one exists. Route Lambdas without a VPC
@@ -1104,7 +1198,7 @@ export class VentureAppStack extends cdk.Stack {
1104
1198
  ? {
1105
1199
  vpc: this.vpc,
1106
1200
  vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
1107
- securityGroups: [this.lambdaSecurityGroup],
1201
+ securityGroups: this.lambdaSecurityGroups,
1108
1202
  }
1109
1203
  : {}),
1110
1204
  });
@@ -1115,6 +1209,10 @@ export class VentureAppStack extends cdk.Stack {
1115
1209
  cdk.Tags.of(fn).add('deployedAt', this.deployedAt);
1116
1210
  cdk.Tags.of(logGroup).add('deployedAt', this.deployedAt);
1117
1211
  this.routeLambdas.set(route.slug, fn);
1212
+ // An internal route is on no public API: other ventures invoke its
1213
+ // function directly (`internalFetch`), so a public request is a 404.
1214
+ if (isInternalRoute(route.apiPath))
1215
+ return;
1118
1216
  // Add the HttpRoute on the imported API. `HttpRouteKey.with`
1119
1217
  // builds the canonical `${METHOD} ${path}` string AWS uses
1120
1218
  // internally; passing path + method separately keeps us honest
@@ -1125,40 +1223,110 @@ export class VentureAppStack extends cdk.Stack {
1125
1223
  integration: new apigatewayv2Integrations.HttpLambdaIntegration(`${resourceId}-integration`, fn),
1126
1224
  });
1127
1225
  }
1226
+ /** Every Lambda's groups: its own, and the VPC's internal clients group. */
1227
+ get lambdaSecurityGroups() {
1228
+ return [this.lambdaSecurityGroup, ...(this.internalClientsSecurityGroup ? [this.internalClientsSecurityGroup] : [])];
1229
+ }
1128
1230
  /**
1129
1231
  * Every execution role in this stack: the shared role, plus the
1130
1232
  * auth-admin role when one exists. Baseline grants (secrets, S3,
1131
1233
  * SES, rate-limit table, …) are applied to all of them.
1132
1234
  */
1133
1235
  get executionRoles() {
1134
- return this.authAdminRole ? [this.lambdaRole, this.authAdminRole] : [this.lambdaRole];
1236
+ return [this.lambdaRole, this.authAdminRole, this.dbSystemRole, this.authAdminDbSystemRole].filter((r) => r !== undefined);
1237
+ }
1238
+ /** The roles whose functions connect as the system database login. */
1239
+ get systemLoginRoles() {
1240
+ return [this.dbSystemRole, this.authAdminDbSystemRole].filter((r) => r !== undefined);
1135
1241
  }
1136
1242
  /**
1137
- * Roles that receive the Cognito admin grants: only the auth-admin
1138
- * role when `adminRoutes` are declared, otherwise the shared role
1139
- * (historical layout).
1243
+ * The role for a function: Cognito admin or not (`auth[].adminRoutes`),
1244
+ * system database login or not (`databases[].logins.system.functions`).
1245
+ */
1246
+ roleFor(subject) {
1247
+ const admin = Boolean(this.authAdminRole) && matchesAdminRoute(this.adminRoutePatterns, subject);
1248
+ const system = Boolean(this.dbSystemRole) && matchesFunctionPattern(this.systemLoginPatterns, subject);
1249
+ if (admin && system)
1250
+ return this.authAdminDbSystemRole;
1251
+ if (admin)
1252
+ return this.authAdminRole;
1253
+ if (system)
1254
+ return this.dbSystemRole;
1255
+ return this.lambdaRole;
1256
+ }
1257
+ /** The database env a function running as `role` gets on top of the base env. */
1258
+ loginEnvFor(role) {
1259
+ if (!this.dbLoginSecrets || !role || !this.systemLoginRoles.includes(role))
1260
+ return {};
1261
+ return { DB_SECRET_ARN: this.dbLoginSecrets.system, DB_LOGIN: 'system' };
1262
+ }
1263
+ /**
1264
+ * Roles that receive the Cognito admin grants: the shared role under
1265
+ * the explicit legacy layout (`adminRoutes: 'all'`), the auth-admin role
1266
+ * when routes are listed, and none otherwise.
1140
1267
  */
1141
1268
  get cognitoAdminRoles() {
1142
- return this.authAdminRole ? [this.authAdminRole] : [this.lambdaRole];
1269
+ if (this.legacyAdminGrants)
1270
+ return [this.lambdaRole, ...(this.dbSystemRole ? [this.dbSystemRole] : [])];
1271
+ return [this.authAdminRole, this.authAdminDbSystemRole].filter((r) => r !== undefined);
1143
1272
  }
1144
1273
  /** Apply one grant to every execution role. */
1145
1274
  grantEachRole(grant) {
1146
1275
  for (const role of this.executionRoles)
1147
1276
  grant(role);
1148
1277
  }
1278
+ /**
1279
+ * Caches: the data stack's cache security group admits THIS stack's
1280
+ * Lambda security group only, and every Lambda gets the endpoint and
1281
+ * its AUTH token's secret (`VENTURE_CACHE_<ID>_HOST` / `_PORT` /
1282
+ * `_AUTH_SECRET_ARN`; `cacheConnection(id)` in `@venturekit/runtime`
1283
+ * turns them into TLS + AUTH connection options).
1284
+ */
1285
+ wireCaches(caches, projectName, stage) {
1286
+ if (!this.lambdaSecurityGroup)
1287
+ return;
1288
+ for (const cache of caches) {
1289
+ const cacheSg = ec2.SecurityGroup.fromSecurityGroupId(this, `imported-cache-sg-${cache.id}`, readSsmString(this, dataKeys.cacheSecurityGroupId(projectName, stage, cache.id)), { mutable: true });
1290
+ cacheSg.connections.allowFrom(this.lambdaSecurityGroup, ec2.Port.tcp(6379), `Allow ${projectName}-${stage} Lambdas to connect to cache ${cache.id}`);
1291
+ const prefix = `VENTURE_CACHE_${upperSnake(cache.id)}`;
1292
+ const secretArn = readSsmString(this, dataKeys.cacheAuthSecretArn(projectName, stage, cache.id));
1293
+ this.baseEnvVars[`${prefix}_HOST`] = readSsmString(this, dataKeys.cacheEndpoint(projectName, stage, cache.id));
1294
+ this.baseEnvVars[`${prefix}_PORT`] = readSsmString(this, dataKeys.cachePort(projectName, stage, cache.id));
1295
+ this.baseEnvVars[`${prefix}_AUTH_SECRET_ARN`] = secretArn;
1296
+ const secret = secretsmanager.Secret.fromSecretCompleteArn(this, `imported-cache-auth-${cache.id}`, secretArn);
1297
+ this.grantEachRole((role) => secret.grantRead(role));
1298
+ }
1299
+ }
1300
+ /**
1301
+ * Internal routes (`internal` intent): the pair secrets this venture keeps
1302
+ * for its callers, and the rights to call the ventures it calls.
1303
+ */
1304
+ wireInternalRoutes(internal, projectName, stage) {
1305
+ const secrets = createInternalCallerSecrets(this, projectName, stage, internal, this.isStrictRetain);
1306
+ if (secrets.size > 0) {
1307
+ for (const [caller, secret] of secrets) {
1308
+ this.grantEachRole((role) => secret.grantRead(role));
1309
+ // What the caller's `vk deploy` checks before deploying (`verifyInternalCalls`).
1310
+ writeSsm(this, internalKeys.callerSecretArn(projectName, stage, caller), secret.secretArn, {
1311
+ description: `Pair secret ${caller} → ${projectName} internal routes`,
1312
+ });
1313
+ }
1314
+ this.baseEnvVars.VENTURE_INTERNAL_CALLER_SECRET_ARNS = JSON.stringify(Object.fromEntries([...secrets].map(([caller, secret]) => [caller, secret.secretArn])));
1315
+ // Who may call — what a caller's `vk deploy` checks it is part of.
1316
+ writeSsm(this, internalKeys.callers(projectName, stage), [...secrets.keys()].join(','), {
1317
+ description: `Ventures allowed to call ${projectName} internal routes`,
1318
+ });
1319
+ }
1320
+ const statements = internalCallStatements(this, projectName, stage, internal);
1321
+ this.grantEachRole((role) => statements.forEach((s) => role.addToPolicy(s)));
1322
+ }
1149
1323
  /** The role a route Lambda runs as — auth-admin when its API path matches `adminRoutes`. */
1150
1324
  roleForRoute(apiPath) {
1151
- if (this.authAdminRole && matchesAdminRoute(this.adminRoutePatterns, { apiPath })) {
1152
- return this.authAdminRole;
1153
- }
1154
- return this.lambdaRole;
1325
+ return this.roleFor({ apiPath });
1155
1326
  }
1156
- /** The role a standalone / queue / schedule Lambda runs as — auth-admin when `fn:<id>` matches. */
1327
+ /** The role a standalone / queue / schedule Lambda runs as (`fn:<id>`). */
1157
1328
  roleForFunction(id) {
1158
- if (this.authAdminRole && matchesAdminRoute(this.adminRoutePatterns, { functionId: id })) {
1159
- return this.authAdminRole;
1160
- }
1161
- return this.lambdaRole;
1329
+ return this.roleFor({ functionId: id });
1162
1330
  }
1163
1331
  /**
1164
1332
  * Build a Lambda function with the standard app-stack properties
@@ -1190,14 +1358,8 @@ export class VentureAppStack extends cdk.Stack {
1190
1358
  memorySize: lambdaConfig.memoryMb,
1191
1359
  timeout: cdk.Duration.seconds(lambdaConfig.timeoutSec),
1192
1360
  description,
1193
- environment: {
1194
- ...this.baseEnvVars,
1195
- ...lambdaConfig.environmentVariables,
1196
- },
1197
1361
  logGroup,
1198
- tracing: lambdaConfig.tracingEnabled
1199
- ? lambda.Tracing.ACTIVE
1200
- : lambda.Tracing.DISABLED,
1362
+ tracing: this.tracingActive ? lambda.Tracing.ACTIVE : lambda.Tracing.DISABLED,
1201
1363
  reservedConcurrentExecutions: lambdaConfig.reservedConcurrency,
1202
1364
  role: this.lambdaRole,
1203
1365
  ...(this.vpc && this.lambdaSecurityGroup
@@ -1208,6 +1370,11 @@ export class VentureAppStack extends cdk.Stack {
1208
1370
  }
1209
1371
  : {}),
1210
1372
  ...overrides,
1373
+ // The database login follows the role (a system-login role reads the system secret).
1374
+ environment: {
1375
+ ...(overrides.environment ?? { ...this.baseEnvVars, ...lambdaConfig.environmentVariables }),
1376
+ ...this.loginEnvFor(overrides.role),
1377
+ },
1211
1378
  });
1212
1379
  }
1213
1380
  /**
@@ -1610,7 +1777,14 @@ export class VentureAppStack extends cdk.Stack {
1610
1777
  if (!db.secretArn)
1611
1778
  continue;
1612
1779
  const importedSecret = secretsmanager.Secret.fromSecretCompleteArn(this, `imported-db-secret-${id}`, db.secretArn);
1780
+ // The app login's secret to every role; the system login's to the
1781
+ // system-login roles ONLY.
1613
1782
  this.grantEachRole((role) => importedSecret.grantRead(role));
1783
+ if (db.systemSecretArn && this.systemLoginRoles.length > 0) {
1784
+ const systemSecret = secretsmanager.Secret.fromSecretCompleteArn(this, `imported-db-system-secret-${id}`, db.systemSecretArn);
1785
+ for (const role of this.systemLoginRoles)
1786
+ systemSecret.grantRead(role);
1787
+ }
1614
1788
  }
1615
1789
  }
1616
1790
  // ── Federated provider secrets ────────────────────────────
@@ -1679,8 +1853,9 @@ export class VentureAppStack extends cdk.Stack {
1679
1853
  }
1680
1854
  }
1681
1855
  // ── Cognito admin actions per user pool ──────────────────
1682
- // Attached to the auth-admin role only when `adminRoutes` are
1683
- // declared (see the constructor), otherwise to the shared role.
1856
+ // Attached to the auth-admin role when `adminRoutes` lists routes,
1857
+ // to the shared role under `adminRoutes: 'all'`, and to no role
1858
+ // otherwise (see `cognitoAdminRoles`).
1684
1859
  if (imports.userPoolArnsByAuthId) {
1685
1860
  for (const [, poolArn] of imports.userPoolArnsByAuthId) {
1686
1861
  // Scope to the Cognito admin actions `@venturekit/auth/server`