@openhi/constructs 0.0.115 → 0.0.116

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/lib/index.js CHANGED
@@ -816,6 +816,7 @@ __export(src_exports, {
816
816
  OpenHiRestApiService: () => OpenHiRestApiService,
817
817
  OpenHiService: () => OpenHiService,
818
818
  OpenHiStage: () => OpenHiStage,
819
+ OpenHiWebsiteService: () => OpenHiWebsiteService,
819
820
  OpsEventBus: () => OpsEventBus,
820
821
  OwningDeleteCascadeLambdas: () => OwningDeleteCascadeLambdas,
821
822
  OwningDeleteCascadeWorkflow: () => OwningDeleteCascadeWorkflow,
@@ -851,11 +852,13 @@ __export(src_exports, {
851
852
  SEED_SYSTEM_DATA_ACTOR_SYSTEM: () => SEED_SYSTEM_DATA_ACTOR_SYSTEM,
852
853
  SEED_SYSTEM_DATA_CONSUMER_NAME: () => SEED_SYSTEM_DATA_CONSUMER_NAME,
853
854
  SEED_SYSTEM_DATA_CONTROL_BUS_ENV_VAR: () => SEED_SYSTEM_DATA_CONTROL_BUS_ENV_VAR,
855
+ SSM_PARAM_NAME_FULL_DOMAIN: () => SSM_PARAM_NAME_FULL_DOMAIN,
854
856
  STATIC_HOSTING_SERVICE_TYPE: () => STATIC_HOSTING_SERVICE_TYPE,
855
857
  SeedDemoDataLambda: () => SeedDemoDataLambda,
856
858
  SeedDemoDataWorkflow: () => SeedDemoDataWorkflow,
857
859
  SeedSystemDataLambda: () => SeedSystemDataLambda,
858
860
  SeedSystemDataWorkflow: () => SeedSystemDataWorkflow,
861
+ StaticContent: () => StaticContent,
859
862
  StaticHosting: () => StaticHosting,
860
863
  USER_ONBOARDING_EVENT_SOURCE: () => USER_ONBOARDING_EVENT_SOURCE,
861
864
  UserOnboardingWorkflow: () => UserOnboardingWorkflow,
@@ -2272,11 +2275,24 @@ var import_constructs7 = require("constructs");
2272
2275
  var RootHostedZone = class extends import_constructs7.Construct {
2273
2276
  };
2274
2277
 
2278
+ // src/components/static-hosting/static-content.ts
2279
+ var import_aws_s32 = require("aws-cdk-lib/aws-s3");
2280
+ var import_aws_s3_deployment = require("aws-cdk-lib/aws-s3-deployment");
2281
+ var import_change_case2 = require("change-case");
2282
+ var import_constructs9 = require("constructs");
2283
+
2275
2284
  // src/components/static-hosting/static-hosting.ts
2285
+ var fs6 = __toESM(require("fs"));
2286
+ var path6 = __toESM(require("path"));
2287
+ var import_aws_cdk_lib10 = require("aws-cdk-lib");
2276
2288
  var import_aws_cloudfront = require("aws-cdk-lib/aws-cloudfront");
2277
2289
  var import_aws_cloudfront_origins = require("aws-cdk-lib/aws-cloudfront-origins");
2290
+ var import_aws_lambda6 = require("aws-cdk-lib/aws-lambda");
2291
+ var import_aws_lambda_nodejs6 = require("aws-cdk-lib/aws-lambda-nodejs");
2292
+ var import_aws_logs = require("aws-cdk-lib/aws-logs");
2293
+ var import_aws_route532 = require("aws-cdk-lib/aws-route53");
2294
+ var import_aws_route53_targets = require("aws-cdk-lib/aws-route53-targets");
2278
2295
  var import_aws_s3 = require("aws-cdk-lib/aws-s3");
2279
- var import_core = require("aws-cdk-lib/core");
2280
2296
  var import_constructs8 = require("constructs");
2281
2297
  var STATIC_HOSTING_SERVICE_TYPE = "website";
2282
2298
  var _StaticHosting = class _StaticHosting extends import_constructs8.Construct {
@@ -2284,6 +2300,7 @@ var _StaticHosting = class _StaticHosting extends import_constructs8.Construct {
2284
2300
  super(scope, id);
2285
2301
  const stack = OpenHiService.of(scope);
2286
2302
  const serviceType = props.serviceType ?? STATIC_HOSTING_SERVICE_TYPE;
2303
+ const hostingMode = props.hostingMode ?? "spa";
2287
2304
  this.bucket = new import_aws_s3.Bucket(this, "bucket", {
2288
2305
  blockPublicAccess: {
2289
2306
  blockPublicAcls: true,
@@ -2293,30 +2310,105 @@ var _StaticHosting = class _StaticHosting extends import_constructs8.Construct {
2293
2310
  },
2294
2311
  ...props.bucketProps
2295
2312
  });
2296
- const origin = import_aws_cloudfront_origins.S3BucketOrigin.withOriginAccessControl(this.bucket);
2313
+ const handlerJs = path6.join(
2314
+ __dirname,
2315
+ "static-hosting.viewer-request-handler.js"
2316
+ );
2317
+ const handlerTs = path6.join(
2318
+ __dirname,
2319
+ "static-hosting.viewer-request-handler.ts"
2320
+ );
2321
+ const handlerEntry = fs6.existsSync(handlerJs) ? handlerJs : handlerTs;
2322
+ this.viewerRequestHandler = new import_aws_lambda_nodejs6.NodejsFunction(
2323
+ this,
2324
+ "viewer-request-handler",
2325
+ {
2326
+ entry: handlerEntry,
2327
+ handler: hostingMode === "static" ? "staticHandler" : "spaHandler",
2328
+ memorySize: 128,
2329
+ runtime: import_aws_lambda6.Runtime.NODEJS_LATEST,
2330
+ logGroup: new import_aws_logs.LogGroup(this, "viewer-request-handler-log-group", {
2331
+ retention: import_aws_logs.RetentionDays.ONE_MONTH
2332
+ })
2333
+ }
2334
+ );
2297
2335
  const cachePolicy = new import_aws_cloudfront.CachePolicy(this, "cache-policy", {
2298
- cachePolicyName: `static-hosting-10s-${stack.branchHash}`,
2299
- comment: "Low TTL (10s) for static hosting; no invalidation",
2300
- defaultTtl: import_core.Duration.seconds(10),
2301
- minTtl: import_core.Duration.seconds(0),
2302
- maxTtl: import_core.Duration.seconds(10)
2336
+ cachePolicyName: `static-hosting-${stack.branchHash}`,
2337
+ comment: "Static hosting default: 60s default / 300s max, gzip+brotli.",
2338
+ defaultTtl: import_aws_cdk_lib10.Duration.seconds(60),
2339
+ minTtl: import_aws_cdk_lib10.Duration.seconds(0),
2340
+ maxTtl: import_aws_cdk_lib10.Duration.seconds(300),
2341
+ headerBehavior: import_aws_cloudfront.CacheHeaderBehavior.none(),
2342
+ queryStringBehavior: import_aws_cloudfront.CacheQueryStringBehavior.none(),
2343
+ cookieBehavior: import_aws_cloudfront.CacheCookieBehavior.none(),
2344
+ enableAcceptEncodingGzip: true,
2345
+ enableAcceptEncodingBrotli: true,
2346
+ ...props.cachePolicyProps
2347
+ });
2348
+ const oac = new import_aws_cloudfront.S3OriginAccessControl(this, "origin-access-control", {
2349
+ signing: import_aws_cloudfront.Signing.SIGV4_NO_OVERRIDE
2350
+ });
2351
+ const origin = import_aws_cloudfront_origins.S3BucketOrigin.withOriginAccessControl(this.bucket, {
2352
+ originAccessControl: oac,
2353
+ originAccessLevels: [import_aws_cloudfront.AccessLevel.READ]
2303
2354
  });
2355
+ const hasCustomDomain = props.certificate !== void 0 && props.hostedZone !== void 0 && props.domainNames !== void 0 && props.domainNames.length > 0;
2304
2356
  this.distribution = new import_aws_cloudfront.Distribution(this, "distribution", {
2357
+ comment: `Static hosting distribution for ${props.description ?? id}`,
2358
+ ...hasCustomDomain ? {
2359
+ certificate: props.certificate,
2360
+ domainNames: [...props.domainNames]
2361
+ } : {},
2362
+ defaultRootObject: "index.html",
2305
2363
  defaultBehavior: {
2306
2364
  origin,
2307
- cachePolicy
2365
+ viewerProtocolPolicy: import_aws_cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
2366
+ cachePolicy,
2367
+ allowedMethods: import_aws_cloudfront.AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
2368
+ edgeLambdas: [
2369
+ {
2370
+ functionVersion: this.viewerRequestHandler.currentVersion,
2371
+ eventType: import_aws_cloudfront.LambdaEdgeEventType.VIEWER_REQUEST,
2372
+ includeBody: false
2373
+ }
2374
+ ]
2308
2375
  },
2309
2376
  ...props.distributionProps
2310
2377
  });
2378
+ if (hasCustomDomain) {
2379
+ props.domainNames.forEach((domainName, index) => {
2380
+ new import_aws_route532.ARecord(this, `dns-record-${index}`, {
2381
+ zone: props.hostedZone,
2382
+ recordName: domainName,
2383
+ target: import_aws_route532.RecordTarget.fromAlias(
2384
+ new import_aws_route53_targets.CloudFrontTarget(this.distribution)
2385
+ )
2386
+ });
2387
+ });
2388
+ }
2311
2389
  new DiscoverableStringParameter(this, "bucket-arn-param", {
2312
2390
  ssmParamName: _StaticHosting.SSM_PARAM_NAME_BUCKET_ARN,
2313
2391
  serviceType,
2314
- stringValue: this.bucket.bucketArn
2392
+ stringValue: this.bucket.bucketArn,
2393
+ description: `Static hosting bucket ARN (${props.description ?? id})`
2315
2394
  });
2316
2395
  new DiscoverableStringParameter(this, "distribution-arn-param", {
2317
2396
  ssmParamName: _StaticHosting.SSM_PARAM_NAME_DISTRIBUTION_ARN,
2318
2397
  serviceType,
2319
- stringValue: this.distribution.distributionArn
2398
+ stringValue: this.distribution.distributionArn,
2399
+ description: `Static hosting distribution ARN (${props.description ?? id})`
2400
+ });
2401
+ new DiscoverableStringParameter(this, "distribution-domain-param", {
2402
+ ssmParamName: _StaticHosting.SSM_PARAM_NAME_DISTRIBUTION_DOMAIN,
2403
+ serviceType,
2404
+ stringValue: this.distribution.domainName,
2405
+ description: `Static hosting distribution domain (${props.description ?? id})`
2406
+ });
2407
+ new DiscoverableStringParameter(this, "distribution-id-param", {
2408
+ ssmParamName: _StaticHosting.SSM_PARAM_NAME_DISTRIBUTION_ID,
2409
+ serviceType,
2410
+ stringValue: this.distribution.distributionId,
2411
+ description: `Static hosting distribution ID (${props.description ?? id})`
2320
2412
  });
2321
2413
  }
2322
2414
  };
@@ -2328,13 +2420,51 @@ _StaticHosting.SSM_PARAM_NAME_BUCKET_ARN = "STATIC_HOSTING_BUCKET_ARN";
2328
2420
  * SSM parameter name for the CloudFront distribution ARN.
2329
2421
  */
2330
2422
  _StaticHosting.SSM_PARAM_NAME_DISTRIBUTION_ARN = "STATIC_HOSTING_DISTRIBUTION_ARN";
2423
+ /**
2424
+ * SSM parameter name for the CloudFront distribution domain
2425
+ * (e.g. dXXXXX.cloudfront.net).
2426
+ */
2427
+ _StaticHosting.SSM_PARAM_NAME_DISTRIBUTION_DOMAIN = "STATIC_HOSTING_DISTRIBUTION_DOMAIN";
2428
+ /**
2429
+ * SSM parameter name for the CloudFront distribution ID.
2430
+ */
2431
+ _StaticHosting.SSM_PARAM_NAME_DISTRIBUTION_ID = "STATIC_HOSTING_DISTRIBUTION_ID";
2331
2432
  var StaticHosting = _StaticHosting;
2332
2433
 
2434
+ // src/components/static-hosting/static-content.ts
2435
+ var StaticContent = class extends import_constructs9.Construct {
2436
+ constructor(scope, id, props) {
2437
+ super(scope, id);
2438
+ const stack = OpenHiService.of(scope);
2439
+ const {
2440
+ contentSourceDirectory,
2441
+ contentDestinationDirectory = "/",
2442
+ subDomain = stack.branchName,
2443
+ fullDomain,
2444
+ serviceType = STATIC_HOSTING_SERVICE_TYPE
2445
+ } = props;
2446
+ const keyPrefix = [(0, import_change_case2.paramCase)(subDomain), fullDomain].join(".");
2447
+ const bucketArn = DiscoverableStringParameter.valueForLookupName(this, {
2448
+ ssmParamName: StaticHosting.SSM_PARAM_NAME_BUCKET_ARN,
2449
+ serviceType
2450
+ });
2451
+ const bucket = import_aws_s32.Bucket.fromBucketArn(this, "bucket", bucketArn);
2452
+ const isTestEnv = process.env.JEST_WORKER_ID !== void 0;
2453
+ const sources = isTestEnv ? [] : [import_aws_s3_deployment.Source.asset(contentSourceDirectory)];
2454
+ new import_aws_s3_deployment.BucketDeployment(this, "deploy", {
2455
+ sources,
2456
+ destinationBucket: bucket,
2457
+ retainOnDelete: false,
2458
+ destinationKeyPrefix: `${keyPrefix}${contentDestinationDirectory}`
2459
+ });
2460
+ }
2461
+ };
2462
+
2333
2463
  // src/services/open-hi-auth-service.ts
2334
2464
  var import_aws_cognito4 = require("aws-cdk-lib/aws-cognito");
2335
2465
  var import_aws_iam6 = require("aws-cdk-lib/aws-iam");
2336
2466
  var import_aws_kms2 = require("aws-cdk-lib/aws-kms");
2337
- var import_core2 = require("aws-cdk-lib/core");
2467
+ var import_core = require("aws-cdk-lib/core");
2338
2468
 
2339
2469
  // src/services/open-hi-data-service.ts
2340
2470
  var import_config4 = __toESM(require_lib());
@@ -2344,7 +2474,7 @@ var kinesis = __toESM(require("aws-cdk-lib/aws-kinesis"));
2344
2474
  // src/services/open-hi-global-service.ts
2345
2475
  var import_aws_certificatemanager2 = require("aws-cdk-lib/aws-certificatemanager");
2346
2476
  var import_aws_events5 = require("aws-cdk-lib/aws-events");
2347
- var import_aws_route532 = require("aws-cdk-lib/aws-route53");
2477
+ var import_aws_route533 = require("aws-cdk-lib/aws-route53");
2348
2478
  var import_aws_ssm3 = require("aws-cdk-lib/aws-ssm");
2349
2479
 
2350
2480
  // src/workflows/control-plane/platform-deploy-bridge/events.ts
@@ -2357,18 +2487,18 @@ var OPENHI_TAG_KEY_PREFIX_ENV_VAR = "OPENHI_TAG_KEY_PREFIX";
2357
2487
  var PLATFORM_DEPLOY_BRIDGE_ACTOR_SYSTEM = "platform-deploy-bridge";
2358
2488
 
2359
2489
  // src/workflows/control-plane/platform-deploy-bridge/platform-deploy-bridge.ts
2360
- var import_constructs10 = require("constructs");
2490
+ var import_constructs11 = require("constructs");
2361
2491
 
2362
2492
  // src/workflows/control-plane/platform-deploy-bridge/platform-deploy-bridge-lambda.ts
2363
2493
  var import_node_fs6 = __toESM(require("fs"));
2364
2494
  var import_node_path6 = __toESM(require("path"));
2365
- var import_aws_cdk_lib10 = require("aws-cdk-lib");
2495
+ var import_aws_cdk_lib11 = require("aws-cdk-lib");
2366
2496
  var import_aws_events4 = require("aws-cdk-lib/aws-events");
2367
2497
  var import_aws_events_targets = require("aws-cdk-lib/aws-events-targets");
2368
2498
  var import_aws_iam2 = require("aws-cdk-lib/aws-iam");
2369
- var import_aws_lambda6 = require("aws-cdk-lib/aws-lambda");
2370
- var import_aws_lambda_nodejs6 = require("aws-cdk-lib/aws-lambda-nodejs");
2371
- var import_constructs9 = require("constructs");
2499
+ var import_aws_lambda7 = require("aws-cdk-lib/aws-lambda");
2500
+ var import_aws_lambda_nodejs7 = require("aws-cdk-lib/aws-lambda-nodejs");
2501
+ var import_constructs10 = require("constructs");
2372
2502
  var HANDLER_NAME6 = "platform-deploy-bridge.handler.js";
2373
2503
  function resolveHandlerEntry6(dirname) {
2374
2504
  const sameDir = import_node_path6.default.join(dirname, HANDLER_NAME6);
@@ -2377,7 +2507,7 @@ function resolveHandlerEntry6(dirname) {
2377
2507
  }
2378
2508
  return import_node_path6.default.join(dirname, "..", "..", "..", "..", "lib", HANDLER_NAME6);
2379
2509
  }
2380
- var PlatformDeployBridgeLambda = class extends import_constructs9.Construct {
2510
+ var PlatformDeployBridgeLambda = class extends import_constructs10.Construct {
2381
2511
  constructor(scope, props) {
2382
2512
  super(scope, "platform-deploy-bridge-lambda");
2383
2513
  const service = OpenHiService.of(this);
@@ -2386,15 +2516,15 @@ var PlatformDeployBridgeLambda = class extends import_constructs9.Construct {
2386
2516
  OPENHI_TAG_SUFFIX_REPO_NAME
2387
2517
  );
2388
2518
  const tagKeyPrefix = `${service.appName}:`;
2389
- const ownStackName = import_aws_cdk_lib10.Stack.of(this).stackName;
2390
- const ownSuffix = `-${service.serviceId}-${import_aws_cdk_lib10.Stack.of(this).account}-${import_aws_cdk_lib10.Stack.of(this).region}`;
2519
+ const ownStackName = import_aws_cdk_lib11.Stack.of(this).stackName;
2520
+ const ownSuffix = `-${service.serviceId}-${import_aws_cdk_lib11.Stack.of(this).account}-${import_aws_cdk_lib11.Stack.of(this).region}`;
2391
2521
  const sharedPrefix = ownStackName.endsWith(ownSuffix) ? ownStackName.slice(0, -ownSuffix.length) : service.branchHash;
2392
- const stackIdPrefix = `arn:aws:cloudformation:${import_aws_cdk_lib10.Stack.of(this).region}:${import_aws_cdk_lib10.Stack.of(this).account}:stack/${sharedPrefix}-`;
2393
- this.lambda = new import_aws_lambda_nodejs6.NodejsFunction(this, "handler", {
2522
+ const stackIdPrefix = `arn:aws:cloudformation:${import_aws_cdk_lib11.Stack.of(this).region}:${import_aws_cdk_lib11.Stack.of(this).account}:stack/${sharedPrefix}-`;
2523
+ this.lambda = new import_aws_lambda_nodejs7.NodejsFunction(this, "handler", {
2394
2524
  entry: resolveHandlerEntry6(__dirname),
2395
- runtime: import_aws_lambda6.Runtime.NODEJS_LATEST,
2525
+ runtime: import_aws_lambda7.Runtime.NODEJS_LATEST,
2396
2526
  memorySize: 256,
2397
- timeout: import_aws_cdk_lib10.Duration.seconds(30),
2527
+ timeout: import_aws_cdk_lib11.Duration.seconds(30),
2398
2528
  environment: {
2399
2529
  [CONTROL_EVENT_BUS_NAME_ENV_VAR]: props.controlEventBus.eventBusName,
2400
2530
  [OPENHI_REPO_TAG_KEY_ENV_VAR]: repoTagKey,
@@ -2406,7 +2536,7 @@ var PlatformDeployBridgeLambda = class extends import_constructs9.Construct {
2406
2536
  effect: import_aws_iam2.Effect.ALLOW,
2407
2537
  actions: ["cloudformation:DescribeStacks"],
2408
2538
  resources: [
2409
- `arn:aws:cloudformation:${import_aws_cdk_lib10.Stack.of(this).region}:${import_aws_cdk_lib10.Stack.of(this).account}:stack/*`
2539
+ `arn:aws:cloudformation:${import_aws_cdk_lib11.Stack.of(this).region}:${import_aws_cdk_lib11.Stack.of(this).account}:stack/*`
2410
2540
  ]
2411
2541
  })
2412
2542
  );
@@ -2425,7 +2555,7 @@ var PlatformDeployBridgeLambda = class extends import_constructs9.Construct {
2425
2555
  targets: [
2426
2556
  new import_aws_events_targets.LambdaFunction(this.lambda, {
2427
2557
  retryAttempts: 2,
2428
- maxEventAge: import_aws_cdk_lib10.Duration.hours(2)
2558
+ maxEventAge: import_aws_cdk_lib11.Duration.hours(2)
2429
2559
  })
2430
2560
  ]
2431
2561
  });
@@ -2433,7 +2563,7 @@ var PlatformDeployBridgeLambda = class extends import_constructs9.Construct {
2433
2563
  };
2434
2564
 
2435
2565
  // src/workflows/control-plane/platform-deploy-bridge/platform-deploy-bridge.ts
2436
- var PlatformDeployBridge = class extends import_constructs10.Construct {
2566
+ var PlatformDeployBridge = class extends import_constructs11.Construct {
2437
2567
  constructor(scope, props) {
2438
2568
  super(scope, "platform-deploy-bridge");
2439
2569
  this.bridgeLambda = new PlatformDeployBridgeLambda(this, {
@@ -2448,7 +2578,7 @@ var _OpenHiGlobalService = class _OpenHiGlobalService extends OpenHiService {
2448
2578
  * Returns an IHostedZone from the given attributes (no SSM). Use when the zone is imported from config.
2449
2579
  */
2450
2580
  static rootHostedZoneFromConstruct(scope, props) {
2451
- return import_aws_route532.HostedZone.fromHostedZoneAttributes(scope, "root-zone", props);
2581
+ return import_aws_route533.HostedZone.fromHostedZoneAttributes(scope, "root-zone", props);
2452
2582
  }
2453
2583
  /**
2454
2584
  * Returns an ICertificate by looking up the Global stack's wildcard cert ARN from SSM.
@@ -2472,7 +2602,7 @@ var _OpenHiGlobalService = class _OpenHiGlobalService extends OpenHiService {
2472
2602
  ssmParamName: ChildHostedZone.SSM_PARAM_NAME,
2473
2603
  serviceType: props.serviceType ?? _OpenHiGlobalService.SERVICE_TYPE
2474
2604
  });
2475
- return import_aws_route532.HostedZone.fromHostedZoneAttributes(scope, "child-zone", {
2605
+ return import_aws_route533.HostedZone.fromHostedZoneAttributes(scope, "child-zone", {
2476
2606
  hostedZoneId,
2477
2607
  zoneName: props.zoneName
2478
2608
  });
@@ -3138,13 +3268,13 @@ _validateFixturesAgainstTenantSpecs();
3138
3268
  // src/workflows/control-plane/seed-demo-data/seed-demo-data-lambda.ts
3139
3269
  var import_node_fs7 = __toESM(require("fs"));
3140
3270
  var import_node_path7 = __toESM(require("path"));
3141
- var import_aws_cdk_lib11 = require("aws-cdk-lib");
3271
+ var import_aws_cdk_lib12 = require("aws-cdk-lib");
3142
3272
  var import_aws_events6 = require("aws-cdk-lib/aws-events");
3143
3273
  var import_aws_events_targets2 = require("aws-cdk-lib/aws-events-targets");
3144
3274
  var import_aws_iam3 = require("aws-cdk-lib/aws-iam");
3145
- var import_aws_lambda7 = require("aws-cdk-lib/aws-lambda");
3146
- var import_aws_lambda_nodejs7 = require("aws-cdk-lib/aws-lambda-nodejs");
3147
- var import_constructs11 = require("constructs");
3275
+ var import_aws_lambda8 = require("aws-cdk-lib/aws-lambda");
3276
+ var import_aws_lambda_nodejs8 = require("aws-cdk-lib/aws-lambda-nodejs");
3277
+ var import_constructs12 = require("constructs");
3148
3278
 
3149
3279
  // src/workflows/control-plane/seed-demo-data/seed-demo-data.handler.ts
3150
3280
  var import_node_crypto = require("crypto");
@@ -6025,14 +6155,14 @@ function resolveHandlerEntry7(dirname) {
6025
6155
  }
6026
6156
  return import_node_path7.default.join(dirname, "..", "..", "..", "..", "lib", HANDLER_NAME7);
6027
6157
  }
6028
- var SeedDemoDataLambda = class extends import_constructs11.Construct {
6158
+ var SeedDemoDataLambda = class extends import_constructs12.Construct {
6029
6159
  constructor(scope, props) {
6030
6160
  super(scope, "seed-demo-data-lambda");
6031
- this.lambda = new import_aws_lambda_nodejs7.NodejsFunction(this, "handler", {
6161
+ this.lambda = new import_aws_lambda_nodejs8.NodejsFunction(this, "handler", {
6032
6162
  entry: resolveHandlerEntry7(__dirname),
6033
- runtime: import_aws_lambda7.Runtime.NODEJS_LATEST,
6163
+ runtime: import_aws_lambda8.Runtime.NODEJS_LATEST,
6034
6164
  memorySize: 512,
6035
- timeout: import_aws_cdk_lib11.Duration.minutes(2),
6165
+ timeout: import_aws_cdk_lib12.Duration.minutes(2),
6036
6166
  environment: {
6037
6167
  DYNAMO_TABLE_NAME: props.dataStoreTable.tableName,
6038
6168
  [SEED_DEMO_DATA_USER_POOL_ID_ENV_VAR]: props.userPool.userPoolId
@@ -6061,7 +6191,7 @@ var SeedDemoDataLambda = class extends import_constructs11.Construct {
6061
6191
  "cognito-idp:AdminSetUserPassword"
6062
6192
  ],
6063
6193
  resources: [
6064
- import_aws_cdk_lib11.Stack.of(this).formatArn({
6194
+ import_aws_cdk_lib12.Stack.of(this).formatArn({
6065
6195
  service: "cognito-idp",
6066
6196
  resource: "userpool",
6067
6197
  resourceName: props.userPool.userPoolId
@@ -6078,7 +6208,7 @@ var SeedDemoDataLambda = class extends import_constructs11.Construct {
6078
6208
  targets: [
6079
6209
  new import_aws_events_targets2.LambdaFunction(this.lambda, {
6080
6210
  retryAttempts: 2,
6081
- maxEventAge: import_aws_cdk_lib11.Duration.hours(2)
6211
+ maxEventAge: import_aws_cdk_lib12.Duration.hours(2)
6082
6212
  })
6083
6213
  ]
6084
6214
  });
@@ -6086,8 +6216,8 @@ var SeedDemoDataLambda = class extends import_constructs11.Construct {
6086
6216
  };
6087
6217
 
6088
6218
  // src/workflows/control-plane/seed-demo-data/seed-demo-data-workflow.ts
6089
- var import_constructs12 = require("constructs");
6090
- var SeedDemoDataWorkflow = class extends import_constructs12.Construct {
6219
+ var import_constructs13 = require("constructs");
6220
+ var SeedDemoDataWorkflow = class extends import_constructs13.Construct {
6091
6221
  constructor(scope, props) {
6092
6222
  super(scope, "seed-demo-data-workflow");
6093
6223
  this.seedDemoData = new SeedDemoDataLambda(this, {
@@ -6113,13 +6243,13 @@ var SEED_SYSTEM_DATA_CONTROL_BUS_ENV_VAR = "CONTROL_EVENT_BUS_NAME";
6113
6243
  var import_node_fs8 = __toESM(require("fs"));
6114
6244
  var import_node_path8 = __toESM(require("path"));
6115
6245
  var import_types13 = require("@openhi/types");
6116
- var import_aws_cdk_lib12 = require("aws-cdk-lib");
6246
+ var import_aws_cdk_lib13 = require("aws-cdk-lib");
6117
6247
  var import_aws_events7 = require("aws-cdk-lib/aws-events");
6118
6248
  var import_aws_events_targets3 = require("aws-cdk-lib/aws-events-targets");
6119
6249
  var import_aws_iam4 = require("aws-cdk-lib/aws-iam");
6120
- var import_aws_lambda8 = require("aws-cdk-lib/aws-lambda");
6121
- var import_aws_lambda_nodejs8 = require("aws-cdk-lib/aws-lambda-nodejs");
6122
- var import_constructs13 = require("constructs");
6250
+ var import_aws_lambda9 = require("aws-cdk-lib/aws-lambda");
6251
+ var import_aws_lambda_nodejs9 = require("aws-cdk-lib/aws-lambda-nodejs");
6252
+ var import_constructs14 = require("constructs");
6123
6253
  var HANDLER_NAME8 = "seed-system-data.handler.js";
6124
6254
  function resolveHandlerEntry8(dirname) {
6125
6255
  const sameDir = import_node_path8.default.join(dirname, HANDLER_NAME8);
@@ -6128,14 +6258,14 @@ function resolveHandlerEntry8(dirname) {
6128
6258
  }
6129
6259
  return import_node_path8.default.join(dirname, "..", "..", "..", "..", "lib", HANDLER_NAME8);
6130
6260
  }
6131
- var SeedSystemDataLambda = class extends import_constructs13.Construct {
6261
+ var SeedSystemDataLambda = class extends import_constructs14.Construct {
6132
6262
  constructor(scope, props) {
6133
6263
  super(scope, "seed-system-data-lambda");
6134
- this.lambda = new import_aws_lambda_nodejs8.NodejsFunction(this, "handler", {
6264
+ this.lambda = new import_aws_lambda_nodejs9.NodejsFunction(this, "handler", {
6135
6265
  entry: resolveHandlerEntry8(__dirname),
6136
- runtime: import_aws_lambda8.Runtime.NODEJS_LATEST,
6266
+ runtime: import_aws_lambda9.Runtime.NODEJS_LATEST,
6137
6267
  memorySize: 512,
6138
- timeout: import_aws_cdk_lib12.Duration.minutes(1),
6268
+ timeout: import_aws_cdk_lib13.Duration.minutes(1),
6139
6269
  environment: {
6140
6270
  DYNAMO_TABLE_NAME: props.dataStoreTable.tableName,
6141
6271
  [SEED_SYSTEM_DATA_CONTROL_BUS_ENV_VAR]: props.controlEventBus.eventBusName
@@ -6157,7 +6287,7 @@ var SeedSystemDataLambda = class extends import_constructs13.Construct {
6157
6287
  })
6158
6288
  );
6159
6289
  props.controlEventBus.grantPutEventsTo(this.lambda);
6160
- const hostStackName = import_aws_cdk_lib12.Stack.of(this).stackName;
6290
+ const hostStackName = import_aws_cdk_lib13.Stack.of(this).stackName;
6161
6291
  this.rule = new import_aws_events7.Rule(this, "rule", {
6162
6292
  eventBus: props.controlEventBus,
6163
6293
  eventPattern: {
@@ -6172,7 +6302,7 @@ var SeedSystemDataLambda = class extends import_constructs13.Construct {
6172
6302
  targets: [
6173
6303
  new import_aws_events_targets3.LambdaFunction(this.lambda, {
6174
6304
  retryAttempts: 2,
6175
- maxEventAge: import_aws_cdk_lib12.Duration.hours(2)
6305
+ maxEventAge: import_aws_cdk_lib13.Duration.hours(2)
6176
6306
  })
6177
6307
  ]
6178
6308
  });
@@ -6180,8 +6310,8 @@ var SeedSystemDataLambda = class extends import_constructs13.Construct {
6180
6310
  };
6181
6311
 
6182
6312
  // src/workflows/control-plane/seed-system-data/seed-system-data-workflow.ts
6183
- var import_constructs14 = require("constructs");
6184
- var SeedSystemDataWorkflow = class extends import_constructs14.Construct {
6313
+ var import_constructs15 = require("constructs");
6314
+ var SeedSystemDataWorkflow = class extends import_constructs15.Construct {
6185
6315
  constructor(scope, props) {
6186
6316
  super(scope, "seed-system-data-workflow");
6187
6317
  this.seedSystemData = new SeedSystemDataLambda(this, {
@@ -6334,13 +6464,13 @@ var buildProvisionDefaultWorkspaceRequestedDetail = (event) => {
6334
6464
  // src/workflows/control-plane/user-onboarding/provision-default-workspace-lambda.ts
6335
6465
  var import_node_fs9 = __toESM(require("fs"));
6336
6466
  var import_node_path9 = __toESM(require("path"));
6337
- var import_aws_cdk_lib13 = require("aws-cdk-lib");
6467
+ var import_aws_cdk_lib14 = require("aws-cdk-lib");
6338
6468
  var import_aws_events8 = require("aws-cdk-lib/aws-events");
6339
6469
  var import_aws_events_targets4 = require("aws-cdk-lib/aws-events-targets");
6340
6470
  var import_aws_iam5 = require("aws-cdk-lib/aws-iam");
6341
- var import_aws_lambda9 = require("aws-cdk-lib/aws-lambda");
6342
- var import_aws_lambda_nodejs9 = require("aws-cdk-lib/aws-lambda-nodejs");
6343
- var import_constructs15 = require("constructs");
6471
+ var import_aws_lambda10 = require("aws-cdk-lib/aws-lambda");
6472
+ var import_aws_lambda_nodejs10 = require("aws-cdk-lib/aws-lambda-nodejs");
6473
+ var import_constructs16 = require("constructs");
6344
6474
  var HANDLER_NAME9 = "provision-default-workspace.handler.js";
6345
6475
  function resolveHandlerEntry9(dirname) {
6346
6476
  const sameDir = import_node_path9.default.join(dirname, HANDLER_NAME9);
@@ -6349,12 +6479,12 @@ function resolveHandlerEntry9(dirname) {
6349
6479
  }
6350
6480
  return import_node_path9.default.join(dirname, "..", "..", "..", "..", "lib", HANDLER_NAME9);
6351
6481
  }
6352
- var ProvisionDefaultWorkspaceLambda = class extends import_constructs15.Construct {
6482
+ var ProvisionDefaultWorkspaceLambda = class extends import_constructs16.Construct {
6353
6483
  constructor(scope, props) {
6354
6484
  super(scope, "provision-default-workspace-lambda");
6355
- this.lambda = new import_aws_lambda_nodejs9.NodejsFunction(this, "handler", {
6485
+ this.lambda = new import_aws_lambda_nodejs10.NodejsFunction(this, "handler", {
6356
6486
  entry: resolveHandlerEntry9(__dirname),
6357
- runtime: import_aws_lambda9.Runtime.NODEJS_LATEST,
6487
+ runtime: import_aws_lambda10.Runtime.NODEJS_LATEST,
6358
6488
  memorySize: 1024,
6359
6489
  environment: {
6360
6490
  DYNAMO_TABLE_NAME: props.dataStoreTable.tableName
@@ -6381,7 +6511,7 @@ var ProvisionDefaultWorkspaceLambda = class extends import_constructs15.Construc
6381
6511
  targets: [
6382
6512
  new import_aws_events_targets4.LambdaFunction(this.lambda, {
6383
6513
  retryAttempts: 2,
6384
- maxEventAge: import_aws_cdk_lib13.Duration.hours(2)
6514
+ maxEventAge: import_aws_cdk_lib14.Duration.hours(2)
6385
6515
  })
6386
6516
  ]
6387
6517
  });
@@ -6389,8 +6519,8 @@ var ProvisionDefaultWorkspaceLambda = class extends import_constructs15.Construc
6389
6519
  };
6390
6520
 
6391
6521
  // src/workflows/control-plane/user-onboarding/user-onboarding-workflow.ts
6392
- var import_constructs16 = require("constructs");
6393
- var UserOnboardingWorkflow = class extends import_constructs16.Construct {
6522
+ var import_constructs17 = require("constructs");
6523
+ var UserOnboardingWorkflow = class extends import_constructs17.Construct {
6394
6524
  constructor(scope, props) {
6395
6525
  super(scope, "user-onboarding-workflow");
6396
6526
  this.provisionDefaultWorkspace = new ProvisionDefaultWorkspaceLambda(this, {
@@ -6608,7 +6738,7 @@ var _OpenHiAuthService = class _OpenHiAuthService extends OpenHiService {
6608
6738
  new import_aws_iam6.PolicyStatement({
6609
6739
  actions: ["cognito-idp:AdminUserGlobalSignOut"],
6610
6740
  resources: [
6611
- import_core2.Stack.of(this).formatArn({
6741
+ import_core.Stack.of(this).formatArn({
6612
6742
  service: "cognito-idp",
6613
6743
  resource: "userpool",
6614
6744
  resourceName: "*"
@@ -6668,16 +6798,16 @@ var import_aws_apigatewayv22 = require("aws-cdk-lib/aws-apigatewayv2");
6668
6798
  var import_aws_apigatewayv2_authorizers = require("aws-cdk-lib/aws-apigatewayv2-authorizers");
6669
6799
  var import_aws_apigatewayv2_integrations = require("aws-cdk-lib/aws-apigatewayv2-integrations");
6670
6800
  var import_aws_iam7 = require("aws-cdk-lib/aws-iam");
6671
- var import_aws_route533 = require("aws-cdk-lib/aws-route53");
6672
- var import_aws_route53_targets = require("aws-cdk-lib/aws-route53-targets");
6673
- var import_core3 = require("aws-cdk-lib/core");
6801
+ var import_aws_route534 = require("aws-cdk-lib/aws-route53");
6802
+ var import_aws_route53_targets2 = require("aws-cdk-lib/aws-route53-targets");
6803
+ var import_core2 = require("aws-cdk-lib/core");
6674
6804
 
6675
6805
  // src/data/lambda/cors-options-lambda.ts
6676
6806
  var import_node_fs10 = __toESM(require("fs"));
6677
6807
  var import_node_path10 = __toESM(require("path"));
6678
- var import_aws_lambda10 = require("aws-cdk-lib/aws-lambda");
6679
- var import_aws_lambda_nodejs10 = require("aws-cdk-lib/aws-lambda-nodejs");
6680
- var import_constructs17 = require("constructs");
6808
+ var import_aws_lambda11 = require("aws-cdk-lib/aws-lambda");
6809
+ var import_aws_lambda_nodejs11 = require("aws-cdk-lib/aws-lambda-nodejs");
6810
+ var import_constructs18 = require("constructs");
6681
6811
  var HANDLER_NAME10 = "cors-options-lambda.handler.js";
6682
6812
  function resolveHandlerEntry10(dirname) {
6683
6813
  const sameDir = import_node_path10.default.join(dirname, HANDLER_NAME10);
@@ -6687,12 +6817,12 @@ function resolveHandlerEntry10(dirname) {
6687
6817
  const fromLib = import_node_path10.default.join(dirname, "..", "..", "..", "lib", HANDLER_NAME10);
6688
6818
  return fromLib;
6689
6819
  }
6690
- var CorsOptionsLambda = class extends import_constructs17.Construct {
6820
+ var CorsOptionsLambda = class extends import_constructs18.Construct {
6691
6821
  constructor(scope, id = "cors-options-lambda") {
6692
6822
  super(scope, id);
6693
- this.lambda = new import_aws_lambda_nodejs10.NodejsFunction(this, "handler", {
6823
+ this.lambda = new import_aws_lambda_nodejs11.NodejsFunction(this, "handler", {
6694
6824
  entry: resolveHandlerEntry10(__dirname),
6695
- runtime: import_aws_lambda10.Runtime.NODEJS_LATEST,
6825
+ runtime: import_aws_lambda11.Runtime.NODEJS_LATEST,
6696
6826
  memorySize: 128
6697
6827
  });
6698
6828
  }
@@ -6701,9 +6831,9 @@ var CorsOptionsLambda = class extends import_constructs17.Construct {
6701
6831
  // src/data/lambda/rest-api-lambda.ts
6702
6832
  var import_node_fs11 = __toESM(require("fs"));
6703
6833
  var import_node_path11 = __toESM(require("path"));
6704
- var import_aws_lambda11 = require("aws-cdk-lib/aws-lambda");
6705
- var import_aws_lambda_nodejs11 = require("aws-cdk-lib/aws-lambda-nodejs");
6706
- var import_constructs18 = require("constructs");
6834
+ var import_aws_lambda12 = require("aws-cdk-lib/aws-lambda");
6835
+ var import_aws_lambda_nodejs12 = require("aws-cdk-lib/aws-lambda-nodejs");
6836
+ var import_constructs19 = require("constructs");
6707
6837
  var HANDLER_NAME11 = "rest-api-lambda.handler.js";
6708
6838
  function resolveHandlerEntry11(dirname) {
6709
6839
  const sameDir = import_node_path11.default.join(dirname, HANDLER_NAME11);
@@ -6713,12 +6843,12 @@ function resolveHandlerEntry11(dirname) {
6713
6843
  const fromLib = import_node_path11.default.join(dirname, "..", "..", "..", "lib", HANDLER_NAME11);
6714
6844
  return fromLib;
6715
6845
  }
6716
- var RestApiLambda = class extends import_constructs18.Construct {
6846
+ var RestApiLambda = class extends import_constructs19.Construct {
6717
6847
  constructor(scope, props) {
6718
6848
  super(scope, "rest-api-lambda");
6719
- this.lambda = new import_aws_lambda_nodejs11.NodejsFunction(this, "handler", {
6849
+ this.lambda = new import_aws_lambda_nodejs12.NodejsFunction(this, "handler", {
6720
6850
  entry: resolveHandlerEntry11(__dirname),
6721
- runtime: import_aws_lambda11.Runtime.NODEJS_LATEST,
6851
+ runtime: import_aws_lambda12.Runtime.NODEJS_LATEST,
6722
6852
  memorySize: 1024,
6723
6853
  environment: {
6724
6854
  DYNAMO_TABLE_NAME: props.dynamoTableName,
@@ -6796,7 +6926,7 @@ var _OpenHiRestApiService = class _OpenHiRestApiService extends OpenHiService {
6796
6926
  */
6797
6927
  createHostedZone() {
6798
6928
  const { config } = this.props;
6799
- return import_aws_route533.HostedZone.fromHostedZoneAttributes(this, "root-zone", {
6929
+ return import_aws_route534.HostedZone.fromHostedZoneAttributes(this, "root-zone", {
6800
6930
  hostedZoneId: config.hostedZoneId,
6801
6931
  zoneName: config.zoneName
6802
6932
  });
@@ -6936,11 +7066,11 @@ var _OpenHiRestApiService = class _OpenHiRestApiService extends OpenHiService {
6936
7066
  integration
6937
7067
  });
6938
7068
  const apiPrefix = this.branchName === "main" ? `api` : `api-${this.childZonePrefix}`;
6939
- new import_aws_route533.ARecord(this, "api-a-record", {
7069
+ new import_aws_route534.ARecord(this, "api-a-record", {
6940
7070
  zone: hostedZone,
6941
7071
  recordName: apiPrefix,
6942
- target: import_aws_route533.RecordTarget.fromAlias(
6943
- new import_aws_route53_targets.ApiGatewayv2DomainProperties(
7072
+ target: import_aws_route534.RecordTarget.fromAlias(
7073
+ new import_aws_route53_targets2.ApiGatewayv2DomainProperties(
6944
7074
  domainName.regionalDomainName,
6945
7075
  domainName.regionalHostedZoneId
6946
7076
  )
@@ -6977,7 +7107,7 @@ var _OpenHiRestApiService = class _OpenHiRestApiService extends OpenHiService {
6977
7107
  "Authorization"
6978
7108
  ],
6979
7109
  allowCredentials: cors.allowCredentials ?? true,
6980
- maxAge: cors.maxAge ?? import_core3.Duration.days(1),
7110
+ maxAge: cors.maxAge ?? import_core2.Duration.days(1),
6981
7111
  ...cors.exposeHeaders !== void 0 && {
6982
7112
  exposeHeaders: cors.exposeHeaders
6983
7113
  }
@@ -7039,6 +7169,158 @@ var _OpenHiGraphqlService = class _OpenHiGraphqlService extends OpenHiService {
7039
7169
  _OpenHiGraphqlService.SERVICE_TYPE = "graphql-api";
7040
7170
  var OpenHiGraphqlService = _OpenHiGraphqlService;
7041
7171
 
7172
+ // src/services/open-hi-website-service.ts
7173
+ var SSM_PARAM_NAME_FULL_DOMAIN = "WEBSITE_FULL_DOMAIN";
7174
+ var _OpenHiWebsiteService = class _OpenHiWebsiteService extends OpenHiService {
7175
+ /**
7176
+ * Looks up the static-hosting bucket ARN published by the release-branch
7177
+ * deploy of this service.
7178
+ */
7179
+ static bucketArnFromConstruct(scope) {
7180
+ return DiscoverableStringParameter.valueForLookupName(scope, {
7181
+ ssmParamName: StaticHosting.SSM_PARAM_NAME_BUCKET_ARN,
7182
+ serviceType: _OpenHiWebsiteService.SERVICE_TYPE
7183
+ });
7184
+ }
7185
+ /**
7186
+ * Looks up the CloudFront distribution ARN published by the release-branch
7187
+ * deploy of this service.
7188
+ */
7189
+ static distributionArnFromConstruct(scope) {
7190
+ return DiscoverableStringParameter.valueForLookupName(scope, {
7191
+ ssmParamName: StaticHosting.SSM_PARAM_NAME_DISTRIBUTION_ARN,
7192
+ serviceType: _OpenHiWebsiteService.SERVICE_TYPE
7193
+ });
7194
+ }
7195
+ /**
7196
+ * Looks up the CloudFront distribution domain
7197
+ * (e.g. dXXXXX.cloudfront.net) published by the release-branch deploy.
7198
+ */
7199
+ static distributionDomainFromConstruct(scope) {
7200
+ return DiscoverableStringParameter.valueForLookupName(scope, {
7201
+ ssmParamName: StaticHosting.SSM_PARAM_NAME_DISTRIBUTION_DOMAIN,
7202
+ serviceType: _OpenHiWebsiteService.SERVICE_TYPE
7203
+ });
7204
+ }
7205
+ /**
7206
+ * Looks up the CloudFront distribution ID published by the release-branch
7207
+ * deploy of this service.
7208
+ */
7209
+ static distributionIdFromConstruct(scope) {
7210
+ return DiscoverableStringParameter.valueForLookupName(scope, {
7211
+ ssmParamName: StaticHosting.SSM_PARAM_NAME_DISTRIBUTION_ID,
7212
+ serviceType: _OpenHiWebsiteService.SERVICE_TYPE
7213
+ });
7214
+ }
7215
+ /**
7216
+ * Looks up the website's full domain (e.g. www.example.com) published by
7217
+ * the release-branch deploy of this service.
7218
+ */
7219
+ static fullDomainFromConstruct(scope) {
7220
+ return DiscoverableStringParameter.valueForLookupName(scope, {
7221
+ ssmParamName: SSM_PARAM_NAME_FULL_DOMAIN,
7222
+ serviceType: _OpenHiWebsiteService.SERVICE_TYPE
7223
+ });
7224
+ }
7225
+ get serviceType() {
7226
+ return _OpenHiWebsiteService.SERVICE_TYPE;
7227
+ }
7228
+ constructor(ohEnv, props) {
7229
+ super(ohEnv, _OpenHiWebsiteService.SERVICE_TYPE, props);
7230
+ this.props = props;
7231
+ this.validateConfig(props);
7232
+ const hostedZone = this.createHostedZone();
7233
+ this.fullDomain = this.computeFullDomain(hostedZone);
7234
+ const shouldCreateHostingInfra = props.createHostingInfrastructure ?? this.branchName === this.defaultReleaseBranch;
7235
+ if (shouldCreateHostingInfra) {
7236
+ const certificate = this.createCertificate();
7237
+ this.staticHosting = this.createStaticHosting({
7238
+ certificate,
7239
+ hostedZone
7240
+ });
7241
+ this.createFullDomainParameter();
7242
+ }
7243
+ this.staticContent = this.createStaticContent();
7244
+ }
7245
+ /**
7246
+ * Validates that config required for the website stack is present.
7247
+ */
7248
+ validateConfig(props) {
7249
+ const { config } = props;
7250
+ if (!config) {
7251
+ throw new Error("Config is required");
7252
+ }
7253
+ if (!config.zoneName) {
7254
+ throw new Error("Zone name is required");
7255
+ }
7256
+ }
7257
+ /**
7258
+ * Looks up the child hosted zone published by the Global service.
7259
+ * Override to customize.
7260
+ */
7261
+ createHostedZone() {
7262
+ return OpenHiGlobalService.childHostedZoneFromConstruct(this, {
7263
+ zoneName: this.config.zoneName
7264
+ });
7265
+ }
7266
+ /**
7267
+ * Returns the wildcard certificate looked up from the Global service.
7268
+ * Override to customize.
7269
+ */
7270
+ createCertificate() {
7271
+ return OpenHiGlobalService.rootWildcardCertificateFromConstruct(this);
7272
+ }
7273
+ /**
7274
+ * Computes the full website domain from `domainPrefix` and the child
7275
+ * zone name.
7276
+ */
7277
+ computeFullDomain(hostedZone) {
7278
+ const prefix = this.props.domainPrefix ?? "www";
7279
+ return [prefix, hostedZone.zoneName].join(".");
7280
+ }
7281
+ /**
7282
+ * Creates the StaticHosting infrastructure (bucket + distribution +
7283
+ * Lambda@Edge + 4 SSM params + DNS).
7284
+ */
7285
+ createStaticHosting(deps) {
7286
+ return new StaticHosting(this, "static-hosting", {
7287
+ serviceType: _OpenHiWebsiteService.SERVICE_TYPE,
7288
+ certificate: deps.certificate,
7289
+ hostedZone: deps.hostedZone,
7290
+ domainNames: [this.fullDomain],
7291
+ description: `OpenHI website (${this.fullDomain})`
7292
+ });
7293
+ }
7294
+ /**
7295
+ * Creates the SSM parameter that publishes the website's full domain.
7296
+ * Look up via {@link OpenHiWebsiteService.fullDomainFromConstruct}.
7297
+ */
7298
+ createFullDomainParameter() {
7299
+ new DiscoverableStringParameter(this, "full-domain-param", {
7300
+ ssmParamName: SSM_PARAM_NAME_FULL_DOMAIN,
7301
+ serviceType: _OpenHiWebsiteService.SERVICE_TYPE,
7302
+ stringValue: this.fullDomain,
7303
+ description: "Full website domain (e.g. www.example.com)"
7304
+ });
7305
+ }
7306
+ /**
7307
+ * Creates the StaticContent uploader. Always created so feature-branch
7308
+ * deploys can publish content to their own sub-domain folder against the
7309
+ * release-branch bucket.
7310
+ */
7311
+ createStaticContent() {
7312
+ const { contentSourceDirectory, contentDestinationDirectory } = this.props;
7313
+ return new StaticContent(this, "static-content", {
7314
+ contentSourceDirectory,
7315
+ contentDestinationDirectory,
7316
+ fullDomain: this.fullDomain,
7317
+ serviceType: _OpenHiWebsiteService.SERVICE_TYPE
7318
+ });
7319
+ }
7320
+ };
7321
+ _OpenHiWebsiteService.SERVICE_TYPE = "website";
7322
+ var OpenHiWebsiteService = _OpenHiWebsiteService;
7323
+
7042
7324
  // src/workflows/control-plane/owning-delete-cascade/events.ts
7043
7325
  var import_workflows5 = __toESM(require_lib2());
7044
7326
  var OWNING_DELETE_CASCADE_CONSUMER_NAME = "owning-delete-cascade";
@@ -7049,11 +7331,11 @@ var OWNING_DELETE_OPS_EVENT_BUS_ENV_VAR = "OWNING_DELETE_OPS_EVENT_BUS_NAME";
7049
7331
  // src/workflows/control-plane/owning-delete-cascade/owning-delete-cascade-lambdas.ts
7050
7332
  var import_node_fs12 = __toESM(require("fs"));
7051
7333
  var import_node_path12 = __toESM(require("path"));
7052
- var import_aws_cdk_lib14 = require("aws-cdk-lib");
7334
+ var import_aws_cdk_lib15 = require("aws-cdk-lib");
7053
7335
  var import_aws_iam8 = require("aws-cdk-lib/aws-iam");
7054
- var import_aws_lambda12 = require("aws-cdk-lib/aws-lambda");
7055
- var import_aws_lambda_nodejs12 = require("aws-cdk-lib/aws-lambda-nodejs");
7056
- var import_constructs19 = require("constructs");
7336
+ var import_aws_lambda13 = require("aws-cdk-lib/aws-lambda");
7337
+ var import_aws_lambda_nodejs13 = require("aws-cdk-lib/aws-lambda-nodejs");
7338
+ var import_constructs20 = require("constructs");
7057
7339
  function resolveHandlerEntry12(dirname, handlerName) {
7058
7340
  const sameDir = import_node_path12.default.join(dirname, handlerName);
7059
7341
  if (import_node_fs12.default.existsSync(sameDir)) {
@@ -7062,18 +7344,18 @@ function resolveHandlerEntry12(dirname, handlerName) {
7062
7344
  const libDir = import_node_path12.default.join(dirname, "..", "..", "..", "..", "lib", handlerName);
7063
7345
  return { entry: libDir, handler: "handler" };
7064
7346
  }
7065
- var OwningDeleteCascadeLambdas = class extends import_constructs19.Construct {
7347
+ var OwningDeleteCascadeLambdas = class extends import_constructs20.Construct {
7066
7348
  constructor(scope, props) {
7067
7349
  super(scope, "owning-delete-cascade-lambdas");
7068
7350
  const listResolved = resolveHandlerEntry12(
7069
7351
  __dirname,
7070
7352
  "list-chunks.handler.js"
7071
7353
  );
7072
- this.listChunks = new import_aws_lambda_nodejs12.NodejsFunction(this, "list-chunks-handler", {
7354
+ this.listChunks = new import_aws_lambda_nodejs13.NodejsFunction(this, "list-chunks-handler", {
7073
7355
  entry: listResolved.entry,
7074
- runtime: import_aws_lambda12.Runtime.NODEJS_LATEST,
7356
+ runtime: import_aws_lambda13.Runtime.NODEJS_LATEST,
7075
7357
  memorySize: 512,
7076
- timeout: import_aws_cdk_lib14.Duration.minutes(1),
7358
+ timeout: import_aws_cdk_lib15.Duration.minutes(1),
7077
7359
  environment: {
7078
7360
  DYNAMO_TABLE_NAME: props.dataStoreTable.tableName
7079
7361
  }
@@ -7083,11 +7365,11 @@ var OwningDeleteCascadeLambdas = class extends import_constructs19.Construct {
7083
7365
  __dirname,
7084
7366
  "delete-chunk.handler.js"
7085
7367
  );
7086
- this.deleteChunk = new import_aws_lambda_nodejs12.NodejsFunction(this, "delete-chunk-handler", {
7368
+ this.deleteChunk = new import_aws_lambda_nodejs13.NodejsFunction(this, "delete-chunk-handler", {
7087
7369
  entry: deleteResolved.entry,
7088
- runtime: import_aws_lambda12.Runtime.NODEJS_LATEST,
7370
+ runtime: import_aws_lambda13.Runtime.NODEJS_LATEST,
7089
7371
  memorySize: 512,
7090
- timeout: import_aws_cdk_lib14.Duration.minutes(1),
7372
+ timeout: import_aws_cdk_lib15.Duration.minutes(1),
7091
7373
  environment: {
7092
7374
  DYNAMO_TABLE_NAME: props.dataStoreTable.tableName
7093
7375
  }
@@ -7102,11 +7384,11 @@ var OwningDeleteCascadeLambdas = class extends import_constructs19.Construct {
7102
7384
  __dirname,
7103
7385
  "finalize.handler.js"
7104
7386
  );
7105
- this.finalize = new import_aws_lambda_nodejs12.NodejsFunction(this, "finalize-handler", {
7387
+ this.finalize = new import_aws_lambda_nodejs13.NodejsFunction(this, "finalize-handler", {
7106
7388
  entry: finalizeResolved.entry,
7107
- runtime: import_aws_lambda12.Runtime.NODEJS_LATEST,
7389
+ runtime: import_aws_lambda13.Runtime.NODEJS_LATEST,
7108
7390
  memorySize: 512,
7109
- timeout: import_aws_cdk_lib14.Duration.minutes(1),
7391
+ timeout: import_aws_cdk_lib15.Duration.minutes(1),
7110
7392
  environment: {
7111
7393
  DYNAMO_TABLE_NAME: props.dataStoreTable.tableName,
7112
7394
  [OWNING_DELETE_OPS_EVENT_BUS_ENV_VAR]: props.opsEventBus.eventBusName
@@ -7124,13 +7406,13 @@ var OwningDeleteCascadeLambdas = class extends import_constructs19.Construct {
7124
7406
  };
7125
7407
 
7126
7408
  // src/workflows/control-plane/owning-delete-cascade/owning-delete-cascade-workflow.ts
7127
- var import_aws_cdk_lib15 = require("aws-cdk-lib");
7409
+ var import_aws_cdk_lib16 = require("aws-cdk-lib");
7128
7410
  var import_aws_events9 = require("aws-cdk-lib/aws-events");
7129
7411
  var import_aws_events_targets5 = require("aws-cdk-lib/aws-events-targets");
7130
7412
  var import_aws_stepfunctions = require("aws-cdk-lib/aws-stepfunctions");
7131
7413
  var import_aws_stepfunctions_tasks = require("aws-cdk-lib/aws-stepfunctions-tasks");
7132
- var import_constructs20 = require("constructs");
7133
- var OwningDeleteCascadeWorkflow = class extends import_constructs20.Construct {
7414
+ var import_constructs21 = require("constructs");
7415
+ var OwningDeleteCascadeWorkflow = class extends import_constructs21.Construct {
7134
7416
  constructor(scope, props) {
7135
7417
  super(scope, "owning-delete-cascade-workflow");
7136
7418
  this.lambdas = new OwningDeleteCascadeLambdas(this, {
@@ -7239,7 +7521,7 @@ var OwningDeleteCascadeWorkflow = class extends import_constructs20.Construct {
7239
7521
  }
7240
7522
  });
7241
7523
  const interPageWait = new import_aws_stepfunctions.Wait(this, "inter-page-wait", {
7242
- time: import_aws_stepfunctions.WaitTime.duration(import_aws_cdk_lib15.Duration.seconds(0))
7524
+ time: import_aws_stepfunctions.WaitTime.duration(import_aws_cdk_lib16.Duration.seconds(0))
7243
7525
  });
7244
7526
  const isExhausted = new import_aws_stepfunctions.Choice(this, "is-exhausted");
7245
7527
  const finalize = new import_aws_stepfunctions_tasks.LambdaInvoke(this, "finalize", {
@@ -7270,7 +7552,7 @@ var OwningDeleteCascadeWorkflow = class extends import_constructs20.Construct {
7270
7552
  // Long timeout because real-world cascades can run minutes when
7271
7553
  // a workspace has thousands of members. The stuck-cascade alarm
7272
7554
  // fires at 15 minutes; the state machine itself does not abort.
7273
- timeout: import_aws_cdk_lib15.Duration.hours(2)
7555
+ timeout: import_aws_cdk_lib16.Duration.hours(2)
7274
7556
  });
7275
7557
  this.rule = new import_aws_events9.Rule(this, "rule", {
7276
7558
  eventBus: props.dataEventBus,
@@ -7281,7 +7563,7 @@ var OwningDeleteCascadeWorkflow = class extends import_constructs20.Construct {
7281
7563
  targets: [
7282
7564
  new import_aws_events_targets5.SfnStateMachine(this.stateMachine, {
7283
7565
  retryAttempts: 2,
7284
- maxEventAge: import_aws_cdk_lib15.Duration.hours(2)
7566
+ maxEventAge: import_aws_cdk_lib16.Duration.hours(2)
7285
7567
  })
7286
7568
  ]
7287
7569
  });
@@ -7299,11 +7581,11 @@ var RENAME_CASCADE_OPS_EVENT_BUS_ENV_VAR = "RENAME_CASCADE_OPS_EVENT_BUS_NAME";
7299
7581
  // src/workflows/control-plane/rename-cascade/rename-cascade-lambdas.ts
7300
7582
  var import_node_fs13 = __toESM(require("fs"));
7301
7583
  var import_node_path13 = __toESM(require("path"));
7302
- var import_aws_cdk_lib16 = require("aws-cdk-lib");
7584
+ var import_aws_cdk_lib17 = require("aws-cdk-lib");
7303
7585
  var import_aws_iam9 = require("aws-cdk-lib/aws-iam");
7304
- var import_aws_lambda13 = require("aws-cdk-lib/aws-lambda");
7305
- var import_aws_lambda_nodejs13 = require("aws-cdk-lib/aws-lambda-nodejs");
7306
- var import_constructs21 = require("constructs");
7586
+ var import_aws_lambda14 = require("aws-cdk-lib/aws-lambda");
7587
+ var import_aws_lambda_nodejs14 = require("aws-cdk-lib/aws-lambda-nodejs");
7588
+ var import_constructs22 = require("constructs");
7307
7589
  function resolveHandlerEntry13(dirname, handlerName) {
7308
7590
  const sameDir = import_node_path13.default.join(dirname, handlerName);
7309
7591
  if (import_node_fs13.default.existsSync(sameDir)) {
@@ -7312,18 +7594,18 @@ function resolveHandlerEntry13(dirname, handlerName) {
7312
7594
  const libDir = import_node_path13.default.join(dirname, "..", "..", "..", "..", "lib", handlerName);
7313
7595
  return { entry: libDir, handler: "handler" };
7314
7596
  }
7315
- var RenameCascadeLambdas = class extends import_constructs21.Construct {
7597
+ var RenameCascadeLambdas = class extends import_constructs22.Construct {
7316
7598
  constructor(scope, props) {
7317
7599
  super(scope, "rename-cascade-lambdas");
7318
7600
  const listResolved = resolveHandlerEntry13(
7319
7601
  __dirname,
7320
7602
  "rename-list-targets.handler.js"
7321
7603
  );
7322
- this.listTargets = new import_aws_lambda_nodejs13.NodejsFunction(this, "list-targets-handler", {
7604
+ this.listTargets = new import_aws_lambda_nodejs14.NodejsFunction(this, "list-targets-handler", {
7323
7605
  entry: listResolved.entry,
7324
- runtime: import_aws_lambda13.Runtime.NODEJS_LATEST,
7606
+ runtime: import_aws_lambda14.Runtime.NODEJS_LATEST,
7325
7607
  memorySize: 512,
7326
- timeout: import_aws_cdk_lib16.Duration.minutes(1),
7608
+ timeout: import_aws_cdk_lib17.Duration.minutes(1),
7327
7609
  environment: {
7328
7610
  DYNAMO_TABLE_NAME: props.dataStoreTable.tableName
7329
7611
  }
@@ -7333,11 +7615,11 @@ var RenameCascadeLambdas = class extends import_constructs21.Construct {
7333
7615
  __dirname,
7334
7616
  "rename-rewrite-chunk.handler.js"
7335
7617
  );
7336
- this.rewriteChunk = new import_aws_lambda_nodejs13.NodejsFunction(this, "rewrite-chunk-handler", {
7618
+ this.rewriteChunk = new import_aws_lambda_nodejs14.NodejsFunction(this, "rewrite-chunk-handler", {
7337
7619
  entry: rewriteResolved.entry,
7338
- runtime: import_aws_lambda13.Runtime.NODEJS_LATEST,
7620
+ runtime: import_aws_lambda14.Runtime.NODEJS_LATEST,
7339
7621
  memorySize: 512,
7340
- timeout: import_aws_cdk_lib16.Duration.minutes(1),
7622
+ timeout: import_aws_cdk_lib17.Duration.minutes(1),
7341
7623
  environment: {
7342
7624
  DYNAMO_TABLE_NAME: props.dataStoreTable.tableName
7343
7625
  }
@@ -7352,11 +7634,11 @@ var RenameCascadeLambdas = class extends import_constructs21.Construct {
7352
7634
  __dirname,
7353
7635
  "rename-finalize.handler.js"
7354
7636
  );
7355
- this.finalize = new import_aws_lambda_nodejs13.NodejsFunction(this, "finalize-handler", {
7637
+ this.finalize = new import_aws_lambda_nodejs14.NodejsFunction(this, "finalize-handler", {
7356
7638
  entry: finalizeResolved.entry,
7357
- runtime: import_aws_lambda13.Runtime.NODEJS_LATEST,
7639
+ runtime: import_aws_lambda14.Runtime.NODEJS_LATEST,
7358
7640
  memorySize: 512,
7359
- timeout: import_aws_cdk_lib16.Duration.minutes(1),
7641
+ timeout: import_aws_cdk_lib17.Duration.minutes(1),
7360
7642
  environment: {
7361
7643
  [RENAME_CASCADE_OPS_EVENT_BUS_ENV_VAR]: props.opsEventBus.eventBusName
7362
7644
  }
@@ -7372,13 +7654,13 @@ var RenameCascadeLambdas = class extends import_constructs21.Construct {
7372
7654
  };
7373
7655
 
7374
7656
  // src/workflows/control-plane/rename-cascade/rename-cascade-workflow.ts
7375
- var import_aws_cdk_lib17 = require("aws-cdk-lib");
7657
+ var import_aws_cdk_lib18 = require("aws-cdk-lib");
7376
7658
  var import_aws_events10 = require("aws-cdk-lib/aws-events");
7377
7659
  var import_aws_events_targets6 = require("aws-cdk-lib/aws-events-targets");
7378
7660
  var import_aws_stepfunctions2 = require("aws-cdk-lib/aws-stepfunctions");
7379
7661
  var import_aws_stepfunctions_tasks2 = require("aws-cdk-lib/aws-stepfunctions-tasks");
7380
- var import_constructs22 = require("constructs");
7381
- var RenameCascadeWorkflow = class extends import_constructs22.Construct {
7662
+ var import_constructs23 = require("constructs");
7663
+ var RenameCascadeWorkflow = class extends import_constructs23.Construct {
7382
7664
  constructor(scope, props) {
7383
7665
  super(scope, "rename-cascade-workflow");
7384
7666
  this.lambdas = new RenameCascadeLambdas(this, {
@@ -7522,7 +7804,7 @@ var RenameCascadeWorkflow = class extends import_constructs22.Construct {
7522
7804
  // Long timeout — large renames may rewrite thousands of rows;
7523
7805
  // the `CascadeSlow` alarm fires at 300s p99 but the state
7524
7806
  // machine itself does not abort.
7525
- timeout: import_aws_cdk_lib17.Duration.hours(2)
7807
+ timeout: import_aws_cdk_lib18.Duration.hours(2)
7526
7808
  });
7527
7809
  this.rule = new import_aws_events10.Rule(this, "rule", {
7528
7810
  eventBus: props.dataEventBus,
@@ -7533,7 +7815,7 @@ var RenameCascadeWorkflow = class extends import_constructs22.Construct {
7533
7815
  targets: [
7534
7816
  new import_aws_events_targets6.SfnStateMachine(this.stateMachine, {
7535
7817
  retryAttempts: 2,
7536
- maxEventAge: import_aws_cdk_lib17.Duration.hours(2)
7818
+ maxEventAge: import_aws_cdk_lib18.Duration.hours(2)
7537
7819
  })
7538
7820
  ]
7539
7821
  });
@@ -7591,6 +7873,7 @@ var RenameCascadeWorkflow = class extends import_constructs22.Construct {
7591
7873
  OpenHiRestApiService,
7592
7874
  OpenHiService,
7593
7875
  OpenHiStage,
7876
+ OpenHiWebsiteService,
7594
7877
  OpsEventBus,
7595
7878
  OwningDeleteCascadeLambdas,
7596
7879
  OwningDeleteCascadeWorkflow,
@@ -7626,11 +7909,13 @@ var RenameCascadeWorkflow = class extends import_constructs22.Construct {
7626
7909
  SEED_SYSTEM_DATA_ACTOR_SYSTEM,
7627
7910
  SEED_SYSTEM_DATA_CONSUMER_NAME,
7628
7911
  SEED_SYSTEM_DATA_CONTROL_BUS_ENV_VAR,
7912
+ SSM_PARAM_NAME_FULL_DOMAIN,
7629
7913
  STATIC_HOSTING_SERVICE_TYPE,
7630
7914
  SeedDemoDataLambda,
7631
7915
  SeedDemoDataWorkflow,
7632
7916
  SeedSystemDataLambda,
7633
7917
  SeedSystemDataWorkflow,
7918
+ StaticContent,
7634
7919
  StaticHosting,
7635
7920
  USER_ONBOARDING_EVENT_SOURCE,
7636
7921
  UserOnboardingWorkflow,