@openhi/constructs 0.0.104 → 0.0.106

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 (83) hide show
  1. package/README.md +14 -0
  2. package/lib/chunk-2PM2NGXI.mjs +31 -0
  3. package/lib/chunk-2PM2NGXI.mjs.map +1 -0
  4. package/lib/chunk-AGF3RAAZ.mjs +20 -0
  5. package/lib/chunk-AGF3RAAZ.mjs.map +1 -0
  6. package/lib/chunk-AO3E22CS.mjs +108 -0
  7. package/lib/chunk-AO3E22CS.mjs.map +1 -0
  8. package/lib/chunk-CHPEQRXU.mjs +45 -0
  9. package/lib/chunk-CHPEQRXU.mjs.map +1 -0
  10. package/lib/chunk-JUNL76HF.mjs +428 -0
  11. package/lib/chunk-JUNL76HF.mjs.map +1 -0
  12. package/lib/chunk-L6UAP4KP.mjs +27 -0
  13. package/lib/chunk-L6UAP4KP.mjs.map +1 -0
  14. package/lib/{chunk-3QS3WKRC.mjs → chunk-LZOMFHX3.mjs} +9 -2
  15. package/lib/chunk-QMIOLLAS.mjs +531 -0
  16. package/lib/chunk-QMIOLLAS.mjs.map +1 -0
  17. package/lib/chunk-SYBADQXI.mjs +607 -0
  18. package/lib/chunk-SYBADQXI.mjs.map +1 -0
  19. package/lib/chunk-VXX4I3EF.mjs +19 -0
  20. package/lib/chunk-VXX4I3EF.mjs.map +1 -0
  21. package/lib/{chunk-MLTYFMSE.mjs → chunk-VYDIGFIX.mjs} +74 -29
  22. package/lib/chunk-VYDIGFIX.mjs.map +1 -0
  23. package/lib/chunk-YU2HRNUP.mjs +33 -0
  24. package/lib/chunk-YU2HRNUP.mjs.map +1 -0
  25. package/lib/chunk-YZZDUJHI.mjs +37 -0
  26. package/lib/chunk-YZZDUJHI.mjs.map +1 -0
  27. package/lib/cors-options-lambda.handler.mjs +1 -1
  28. package/lib/data-store-postgres-replication.handler.mjs +1 -1
  29. package/lib/events-BfrkMoBD.d.mts +44 -0
  30. package/lib/events-BfrkMoBD.d.ts +44 -0
  31. package/lib/events-CVA3_eEB.d.mts +23 -0
  32. package/lib/events-CVA3_eEB.d.ts +23 -0
  33. package/lib/events-DGep6C7w.d.mts +207 -0
  34. package/lib/events-DGep6C7w.d.ts +207 -0
  35. package/lib/firehose-archive-transform.handler.mjs +1 -1
  36. package/lib/index.d.mts +508 -29
  37. package/lib/index.d.ts +773 -30
  38. package/lib/index.js +2536 -105
  39. package/lib/index.js.map +1 -1
  40. package/lib/index.mjs +899 -106
  41. package/lib/index.mjs.map +1 -1
  42. package/lib/openhi-context-CaBH8SFo.d.mts +39 -0
  43. package/lib/openhi-context-CaBH8SFo.d.ts +39 -0
  44. package/lib/platform-deploy-bridge.handler.d.mts +14 -0
  45. package/lib/platform-deploy-bridge.handler.d.ts +14 -0
  46. package/lib/platform-deploy-bridge.handler.js +762 -0
  47. package/lib/platform-deploy-bridge.handler.js.map +1 -0
  48. package/lib/platform-deploy-bridge.handler.mjs +134 -0
  49. package/lib/platform-deploy-bridge.handler.mjs.map +1 -0
  50. package/lib/post-authentication.handler.mjs +1 -1
  51. package/lib/post-confirmation.handler.js +50 -904
  52. package/lib/post-confirmation.handler.js.map +1 -1
  53. package/lib/post-confirmation.handler.mjs +37 -112
  54. package/lib/post-confirmation.handler.mjs.map +1 -1
  55. package/lib/pre-token-generation.handler.js +135 -55
  56. package/lib/pre-token-generation.handler.js.map +1 -1
  57. package/lib/pre-token-generation.handler.mjs +25 -32
  58. package/lib/pre-token-generation.handler.mjs.map +1 -1
  59. package/lib/provision-default-workspace.handler.d.mts +13 -0
  60. package/lib/provision-default-workspace.handler.d.ts +13 -0
  61. package/lib/provision-default-workspace.handler.js +1172 -0
  62. package/lib/provision-default-workspace.handler.js.map +1 -0
  63. package/lib/provision-default-workspace.handler.mjs +175 -0
  64. package/lib/provision-default-workspace.handler.mjs.map +1 -0
  65. package/lib/rest-api-lambda.handler.js +114 -59
  66. package/lib/rest-api-lambda.handler.js.map +1 -1
  67. package/lib/rest-api-lambda.handler.mjs +60 -587
  68. package/lib/rest-api-lambda.handler.mjs.map +1 -1
  69. package/lib/seed-demo-data.handler.d.mts +107 -0
  70. package/lib/seed-demo-data.handler.d.ts +107 -0
  71. package/lib/seed-demo-data.handler.js +2037 -0
  72. package/lib/seed-demo-data.handler.js.map +1 -0
  73. package/lib/seed-demo-data.handler.mjs +23 -0
  74. package/lib/seed-demo-data.handler.mjs.map +1 -0
  75. package/lib/seed-system-data.handler.d.mts +64 -0
  76. package/lib/seed-system-data.handler.d.ts +64 -0
  77. package/lib/seed-system-data.handler.js +1631 -0
  78. package/lib/seed-system-data.handler.js.map +1 -0
  79. package/lib/seed-system-data.handler.mjs +135 -0
  80. package/lib/seed-system-data.handler.mjs.map +1 -0
  81. package/package.json +4 -2
  82. package/lib/chunk-MLTYFMSE.mjs.map +0 -1
  83. /package/lib/{chunk-3QS3WKRC.mjs.map → chunk-LZOMFHX3.mjs.map} +0 -0
package/lib/index.mjs CHANGED
@@ -1,13 +1,66 @@
1
+ import {
2
+ SEED_SYSTEM_DATA_ACTOR_SYSTEM,
3
+ SEED_SYSTEM_DATA_CONSUMER_NAME,
4
+ SEED_SYSTEM_DATA_CONTROL_BUS_ENV_VAR,
5
+ import_workflows as import_workflows2
6
+ } from "./chunk-AGF3RAAZ.mjs";
7
+ import {
8
+ DEMO_PERIOD,
9
+ DEMO_TENANT_SPECS,
10
+ DEMO_URN_SYSTEM,
11
+ DEV_USERS,
12
+ OPENHI_RESOURCE_URN_SYSTEM,
13
+ PLACEHOLDER_TENANT_ID,
14
+ PLACEHOLDER_WORKSPACE_ID,
15
+ PLATFORM_SCOPE_TENANT_ID,
16
+ SEED_DEMO_DATA_CONSUMER_NAME,
17
+ SEED_DEMO_DATA_USER_POOL_ID_ENV_VAR,
18
+ demoBasePartitionKeys,
19
+ demoDevUserPartitionKeys,
20
+ demoMembershipId,
21
+ demoMembershipPartitionKey,
22
+ demoRoleAssignmentId,
23
+ demoRoleAssignmentPartitionKey,
24
+ demoRolesForUserInTenant,
25
+ demoScenarioIdentifier,
26
+ demoTenantPartitionKey,
27
+ demoUserPartitionKey,
28
+ demoWorkspacePartitionKey,
29
+ import_workflows,
30
+ openhiResourceIdentifier,
31
+ rolePartitionKey
32
+ } from "./chunk-QMIOLLAS.mjs";
1
33
  import {
2
34
  DATA_STORE_CHANGE_DETAIL_MAX_UTF8_BYTES,
3
35
  DATA_STORE_CHANGE_DETAIL_TYPE,
4
36
  DATA_STORE_CHANGE_EVENT_SOURCE,
5
37
  buildFhirCurrentResourceChangeDetail
6
38
  } from "./chunk-CEOAGPYY.mjs";
39
+ import "./chunk-L6UAP4KP.mjs";
40
+ import {
41
+ PROVISION_DEFAULT_WORKSPACE_DETAIL_TYPE,
42
+ USER_ONBOARDING_EVENT_SOURCE,
43
+ buildProvisionDefaultWorkspaceRequestedDetail
44
+ } from "./chunk-2PM2NGXI.mjs";
45
+ import {
46
+ BRIDGED_STATUSES,
47
+ CLOUDFORMATION_EVENT_SOURCE,
48
+ CLOUDFORMATION_STACK_STATUS_CHANGE_DETAIL_TYPE,
49
+ CONTROL_EVENT_BUS_NAME_ENV_VAR,
50
+ OPENHI_REPO_TAG_KEY_ENV_VAR,
51
+ OPENHI_TAG_KEY_PREFIX_ENV_VAR,
52
+ PLATFORM_DEPLOY_BRIDGE_ACTOR_SYSTEM
53
+ } from "./chunk-VXX4I3EF.mjs";
54
+ import {
55
+ require_lib
56
+ } from "./chunk-SYBADQXI.mjs";
57
+ import "./chunk-AO3E22CS.mjs";
58
+ import "./chunk-YZZDUJHI.mjs";
59
+ import "./chunk-VYDIGFIX.mjs";
7
60
  import {
8
61
  __commonJS,
9
62
  __toESM
10
- } from "./chunk-3QS3WKRC.mjs";
63
+ } from "./chunk-LZOMFHX3.mjs";
11
64
 
12
65
  // ../config/lib/open-hi-config.js
13
66
  var require_open_hi_config = __commonJS({
@@ -45,7 +98,7 @@ var require_open_hi_config = __commonJS({
45
98
  });
46
99
 
47
100
  // ../config/lib/index.js
48
- var require_lib = __commonJS({
101
+ var require_lib2 = __commonJS({
49
102
  "../config/lib/index.js"(exports) {
50
103
  "use strict";
51
104
  var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
@@ -70,11 +123,11 @@ var require_lib = __commonJS({
70
123
  });
71
124
 
72
125
  // src/app/open-hi-app.ts
73
- var import_config2 = __toESM(require_lib());
126
+ var import_config2 = __toESM(require_lib2());
74
127
  import { App } from "aws-cdk-lib";
75
128
 
76
129
  // src/app/open-hi-environment.ts
77
- var import_config = __toESM(require_lib());
130
+ var import_config = __toESM(require_lib2());
78
131
  import { Stage } from "aws-cdk-lib";
79
132
  var OPEN_HI_ENVIRONMENT_SYMBOL = /* @__PURE__ */ Symbol.for(
80
133
  "@openhi/constructs/core.OpenHiEnvironment"
@@ -276,7 +329,7 @@ var OpenHiApp = class _OpenHiApp extends App {
276
329
  };
277
330
 
278
331
  // src/app/open-hi-service.ts
279
- var import_config3 = __toESM(require_lib());
332
+ var import_config3 = __toESM(require_lib2());
280
333
  import {
281
334
  findGitBranch,
282
335
  findGitRepoName,
@@ -284,6 +337,11 @@ import {
284
337
  } from "@codedrifters/utils";
285
338
  import { RemovalPolicy, Stack, Tags } from "aws-cdk-lib";
286
339
  import { paramCase } from "change-case";
340
+ var OPENHI_TAG_SUFFIX_REPO_NAME = "repo-name";
341
+ var OPENHI_TAG_SUFFIX_BRANCH_NAME = "branch-name";
342
+ var OPENHI_TAG_SUFFIX_SERVICE_TYPE = "service-type";
343
+ var OPENHI_TAG_SUFFIX_STAGE_TYPE = "stage-type";
344
+ var openHiTagKey = (appName, suffix) => `${appName}:${suffix}`;
287
345
  var OpenHiService = class extends Stack {
288
346
  /**
289
347
  * Creates a new OpenHI service stack.
@@ -351,11 +409,20 @@ var OpenHiService = class extends Stack {
351
409
  `availability-zones:account=${account}:region=${region}`,
352
410
  [`${region}a`, `${region}b`, `${region}c`]
353
411
  );
354
- Tags.of(this).add(`${appName}:repo-name`, repoName.slice(0, 255));
355
- Tags.of(this).add(`${appName}:branch-name`, branchName.slice(0, 255));
356
- Tags.of(this).add(`${appName}:service-type`, id.slice(0, 255));
357
412
  Tags.of(this).add(
358
- `${appName}:stage-type`,
413
+ openHiTagKey(appName, OPENHI_TAG_SUFFIX_REPO_NAME),
414
+ repoName.slice(0, 255)
415
+ );
416
+ Tags.of(this).add(
417
+ openHiTagKey(appName, OPENHI_TAG_SUFFIX_BRANCH_NAME),
418
+ branchName.slice(0, 255)
419
+ );
420
+ Tags.of(this).add(
421
+ openHiTagKey(appName, OPENHI_TAG_SUFFIX_SERVICE_TYPE),
422
+ id.slice(0, 255)
423
+ );
424
+ Tags.of(this).add(
425
+ openHiTagKey(appName, OPENHI_TAG_SUFFIX_STAGE_TYPE),
359
426
  ohEnv.ohStage.stageType.slice(0, 255)
360
427
  );
361
428
  }
@@ -711,14 +778,13 @@ import { Runtime as Runtime2 } from "aws-cdk-lib/aws-lambda";
711
778
  import { NodejsFunction as NodejsFunction2 } from "aws-cdk-lib/aws-lambda-nodejs";
712
779
  import { Construct as Construct2 } from "constructs";
713
780
  var HANDLER_NAME2 = "post-confirmation.handler.js";
714
- function resolveHandlerEntry2(dirname) {
781
+ var resolveHandlerEntry2 = (dirname) => {
715
782
  const sameDir = path2.join(dirname, HANDLER_NAME2);
716
783
  if (fs2.existsSync(sameDir)) {
717
784
  return sameDir;
718
785
  }
719
- const fromLib = path2.join(dirname, "..", "..", "..", "lib", HANDLER_NAME2);
720
- return fromLib;
721
- }
786
+ return path2.join(dirname, "..", "..", "..", "lib", HANDLER_NAME2);
787
+ };
722
788
  var PostConfirmationLambda = class extends Construct2 {
723
789
  constructor(scope, props) {
724
790
  super(scope, "post-confirmation-lambda");
@@ -727,7 +793,7 @@ var PostConfirmationLambda = class extends Construct2 {
727
793
  runtime: Runtime2.NODEJS_LATEST,
728
794
  memorySize: 1024,
729
795
  environment: {
730
- DYNAMO_TABLE_NAME: props.dynamoTableName
796
+ CONTROL_EVENT_BUS_NAME: props.controlEventBusName
731
797
  }
732
798
  });
733
799
  }
@@ -939,6 +1005,204 @@ var DynamoDbDataStore = class extends Table {
939
1005
  }
940
1006
  };
941
1007
 
1008
+ // src/components/dynamodb/workflow-dedup-table.ts
1009
+ var import_workflows3 = __toESM(require_lib());
1010
+ import { Annotations } from "aws-cdk-lib";
1011
+ import { AttributeType as AttributeType2, BillingMode as BillingMode2, Table as Table2 } from "aws-cdk-lib/aws-dynamodb";
1012
+ import { Effect, PolicyStatement } from "aws-cdk-lib/aws-iam";
1013
+ import { Construct as Construct5 } from "constructs";
1014
+ function getWorkflowDedupTableName(scope) {
1015
+ const stack = OpenHiService.of(scope);
1016
+ return `workflow-dedup-${stack.branchHash}`;
1017
+ }
1018
+ var _WorkflowDedupTable = class _WorkflowDedupTable extends Construct5 {
1019
+ constructor(scope, id, props = {}) {
1020
+ super(scope, id);
1021
+ this.registeredConsumers = /* @__PURE__ */ new Set();
1022
+ const service = OpenHiService.of(scope);
1023
+ const others = service.node.findAll().filter(
1024
+ (c) => c instanceof _WorkflowDedupTable && c !== this
1025
+ );
1026
+ if (others.length > 0) {
1027
+ throw new WorkflowDedupTableDuplicateError(
1028
+ `WorkflowDedupTable already exists at ${others[0].node.path}; only one shared dedup table is allowed per service stack (TR-015).`
1029
+ );
1030
+ }
1031
+ this.table = new Table2(this, "Table", {
1032
+ tableName: getWorkflowDedupTableName(scope),
1033
+ partitionKey: {
1034
+ name: "consumerName",
1035
+ type: AttributeType2.STRING
1036
+ },
1037
+ sortKey: {
1038
+ name: "sk",
1039
+ type: AttributeType2.STRING
1040
+ },
1041
+ billingMode: BillingMode2.PAY_PER_REQUEST,
1042
+ timeToLiveAttribute: "expiresAt",
1043
+ removalPolicy: props.removalPolicy ?? service.removalPolicy
1044
+ });
1045
+ new DiscoverableStringParameter(this, "table-name-param", {
1046
+ ssmParamName: _WorkflowDedupTable.TABLE_NAME_SSM_PARAM_NAME,
1047
+ stringValue: this.table.tableName
1048
+ });
1049
+ new DiscoverableStringParameter(this, "table-arn-param", {
1050
+ ssmParamName: _WorkflowDedupTable.TABLE_ARN_SSM_PARAM_NAME,
1051
+ stringValue: this.table.tableArn
1052
+ });
1053
+ }
1054
+ /** Cross-stack lookup for the table name. */
1055
+ static tableNameFromLookup(scope) {
1056
+ return DiscoverableStringParameter.valueForLookupName(scope, {
1057
+ ssmParamName: _WorkflowDedupTable.TABLE_NAME_SSM_PARAM_NAME,
1058
+ serviceType: _WorkflowDedupTable.PUBLISHER_SERVICE_TYPE
1059
+ });
1060
+ }
1061
+ /** Cross-stack lookup for the table ARN. */
1062
+ static tableArnFromLookup(scope) {
1063
+ return DiscoverableStringParameter.valueForLookupName(scope, {
1064
+ ssmParamName: _WorkflowDedupTable.TABLE_ARN_SSM_PARAM_NAME,
1065
+ serviceType: _WorkflowDedupTable.PUBLISHER_SERVICE_TYPE
1066
+ });
1067
+ }
1068
+ /**
1069
+ * Cross-stack equivalent of {@link grantConsumer}. Use when the dedup
1070
+ * table is on a different stack than the consumer Lambda — the
1071
+ * grant resolves the table name + ARN via SSM at synth time, so the
1072
+ * consumer stack does not pick up a CloudFormation export dependency
1073
+ * on the global stack.
1074
+ *
1075
+ * Inverts the singleton-guard semantics of `grantConsumer`: there is
1076
+ * no synth-time check that the same `consumerName` was registered
1077
+ * twice across stacks. Consumer names are agreed by convention
1078
+ * (see TR-015); double-registration is operator error caught at
1079
+ * design time, not synth time.
1080
+ */
1081
+ static grantConsumerFromLookup(scope, fn, consumerName, options = {}) {
1082
+ _WorkflowDedupTable.assertConsumerNameStatic(consumerName);
1083
+ const tableName = _WorkflowDedupTable.tableNameFromLookup(scope);
1084
+ const tableArn = _WorkflowDedupTable.tableArnFromLookup(scope);
1085
+ fn.addEnvironment(import_workflows3.WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR, tableName);
1086
+ if (options.defaultTtlSeconds !== void 0) {
1087
+ fn.addEnvironment(
1088
+ "OPENHI_WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS",
1089
+ String(options.defaultTtlSeconds)
1090
+ );
1091
+ }
1092
+ fn.addToRolePolicy(
1093
+ new PolicyStatement({
1094
+ effect: Effect.ALLOW,
1095
+ actions: [
1096
+ "dynamodb:PutItem",
1097
+ "dynamodb:UpdateItem",
1098
+ "dynamodb:GetItem",
1099
+ "dynamodb:Query"
1100
+ ],
1101
+ resources: [tableArn],
1102
+ conditions: {
1103
+ "ForAllValues:StringEquals": {
1104
+ "dynamodb:LeadingKeys": [consumerName]
1105
+ }
1106
+ }
1107
+ })
1108
+ );
1109
+ }
1110
+ /**
1111
+ * Standalone consumer-name validator shared by the instance method
1112
+ * and `grantConsumerFromLookup` so the two grants enforce identical
1113
+ * invariants.
1114
+ */
1115
+ static assertConsumerNameStatic(consumerName) {
1116
+ if (consumerName.length === 0) {
1117
+ throw new WorkflowDedupConsumerNameInvalidError(
1118
+ "consumerName must be non-empty."
1119
+ );
1120
+ }
1121
+ if (consumerName.length > import_workflows3.WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH) {
1122
+ throw new WorkflowDedupConsumerNameInvalidError(
1123
+ `consumerName must be at most ${import_workflows3.WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH} chars; got ${consumerName.length}.`
1124
+ );
1125
+ }
1126
+ if (/\s/.test(consumerName)) {
1127
+ throw new WorkflowDedupConsumerNameInvalidError(
1128
+ "consumerName must not contain whitespace."
1129
+ );
1130
+ }
1131
+ }
1132
+ /**
1133
+ * Wire a Lambda consumer to this table. Injects the table-name env var
1134
+ * so the runtime `WorkflowDedupClient` can resolve it, then attaches a
1135
+ * per-consumer IAM grant scoped by `dynamodb:LeadingKeys` so the
1136
+ * consumer can only read/write its own partition.
1137
+ */
1138
+ grantConsumer(fn, consumerName, options = {}) {
1139
+ this.assertConsumerName(consumerName);
1140
+ if (this.registeredConsumers.has(consumerName)) {
1141
+ Annotations.of(this).addWarning(
1142
+ `WorkflowDedupTable: consumerName "${consumerName}" registered more than once; subsequent grantConsumer calls add policy statements but do not re-inject the env var.`
1143
+ );
1144
+ }
1145
+ this.registeredConsumers.add(consumerName);
1146
+ fn.addEnvironment(import_workflows3.WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR, this.table.tableName);
1147
+ if (options.defaultTtlSeconds !== void 0) {
1148
+ fn.addEnvironment(
1149
+ "OPENHI_WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS",
1150
+ String(options.defaultTtlSeconds)
1151
+ );
1152
+ }
1153
+ fn.addToRolePolicy(
1154
+ new PolicyStatement({
1155
+ effect: Effect.ALLOW,
1156
+ actions: [
1157
+ "dynamodb:PutItem",
1158
+ "dynamodb:UpdateItem",
1159
+ "dynamodb:GetItem",
1160
+ "dynamodb:Query"
1161
+ ],
1162
+ resources: [this.table.tableArn],
1163
+ conditions: {
1164
+ "ForAllValues:StringEquals": {
1165
+ "dynamodb:LeadingKeys": [consumerName]
1166
+ }
1167
+ }
1168
+ })
1169
+ );
1170
+ }
1171
+ assertConsumerName(consumerName) {
1172
+ _WorkflowDedupTable.assertConsumerNameStatic(consumerName);
1173
+ }
1174
+ };
1175
+ /** SSM param name (short) used by `DiscoverableStringParameter` for the table name lookup. */
1176
+ _WorkflowDedupTable.TABLE_NAME_SSM_PARAM_NAME = "workflow-dedup-table-name";
1177
+ /** SSM param name (short) used by `DiscoverableStringParameter` for the table ARN lookup. */
1178
+ _WorkflowDedupTable.TABLE_ARN_SSM_PARAM_NAME = "workflow-dedup-table-arn";
1179
+ /**
1180
+ * Service-type the publishing stack runs under. The cross-stack lookups
1181
+ * pin to this value so consumer stacks on a different service-type
1182
+ * (e.g. `data`, `auth`) resolve the parameter at the publisher's SSM
1183
+ * path instead of their own. Typed against `OpenHiServiceType` so a
1184
+ * future rename of the literal triggers a compile error; not pulled
1185
+ * from `OpenHiGlobalService.SERVICE_TYPE` because
1186
+ * `OpenHiGlobalService` already imports `WorkflowDedupTable` — a
1187
+ * back-import would create a circular dependency.
1188
+ */
1189
+ _WorkflowDedupTable.PUBLISHER_SERVICE_TYPE = "global";
1190
+ var WorkflowDedupTable = _WorkflowDedupTable;
1191
+ var WorkflowDedupTableDuplicateError = class extends Error {
1192
+ /** @param message - human-readable description of the duplicate. */
1193
+ constructor(message) {
1194
+ super(message);
1195
+ this.name = "WorkflowDedupTableDuplicateError";
1196
+ }
1197
+ };
1198
+ var WorkflowDedupConsumerNameInvalidError = class extends Error {
1199
+ /** @param message - human-readable description of the invariant violation. */
1200
+ constructor(message) {
1201
+ super(message);
1202
+ this.name = "WorkflowDedupConsumerNameInvalidError";
1203
+ }
1204
+ };
1205
+
942
1206
  // src/components/event-bridge/data-event-bus.ts
943
1207
  import { EventBus } from "aws-cdk-lib/aws-events";
944
1208
  var DataEventBus = class _DataEventBus extends EventBus {
@@ -983,6 +1247,28 @@ var OpsEventBus = class _OpsEventBus extends EventBus2 {
983
1247
  }
984
1248
  };
985
1249
 
1250
+ // src/components/event-bridge/control-event-bus.ts
1251
+ import { EventBus as EventBus3 } from "aws-cdk-lib/aws-events";
1252
+ var ControlEventBus = class _ControlEventBus extends EventBus3 {
1253
+ /*****************************************************************************
1254
+ *
1255
+ * Return a name for this EventBus based on the stack environment hash. This
1256
+ * name is common across all stacks since it's using the environment hash in
1257
+ * its name.
1258
+ *
1259
+ ****************************************************************************/
1260
+ static getEventBusName(scope) {
1261
+ const stack = OpenHiService.of(scope);
1262
+ return `controlv1${stack.branchHash}`;
1263
+ }
1264
+ constructor(scope, props) {
1265
+ super(scope, "control-event-bus-v1", {
1266
+ ...props,
1267
+ eventBusName: _ControlEventBus.getEventBusName(scope)
1268
+ });
1269
+ }
1270
+ };
1271
+
986
1272
  // src/components/postgres/data-store-postgres-replica.ts
987
1273
  import fs5 from "fs";
988
1274
  import path5 from "path";
@@ -992,7 +1278,7 @@ import { Runtime as Runtime5, StartingPosition } from "aws-cdk-lib/aws-lambda";
992
1278
  import { KinesisEventSource } from "aws-cdk-lib/aws-lambda-event-sources";
993
1279
  import { NodejsFunction as NodejsFunction5 } from "aws-cdk-lib/aws-lambda-nodejs";
994
1280
  import * as rds from "aws-cdk-lib/aws-rds";
995
- import { Construct as Construct5 } from "constructs";
1281
+ import { Construct as Construct6 } from "constructs";
996
1282
  var HANDLER_NAME5 = "data-store-postgres-replication.handler.js";
997
1283
  var DEFAULT_DATABASE_NAME = "openhi";
998
1284
  var SCHEMA_NAME_PATTERN = /^[a-z_][a-z0-9_]{0,62}$/;
@@ -1015,7 +1301,7 @@ function getPostgresReplicaSchemaName(branchHash) {
1015
1301
  }
1016
1302
  return candidate;
1017
1303
  }
1018
- var DataStorePostgresReplica = class extends Construct5 {
1304
+ var DataStorePostgresReplica = class extends Construct6 {
1019
1305
  /**
1020
1306
  * Resolve the cluster ARN published by an upstream {@link DataStorePostgresReplica}.
1021
1307
  * Use from any stack that needs to grant `rds-data:ExecuteStatement` against
@@ -1170,8 +1456,8 @@ var ChildHostedZone = class extends HostedZone {
1170
1456
  ChildHostedZone.SSM_PARAM_NAME = "CHILDHOSTEDZONE";
1171
1457
 
1172
1458
  // src/components/route-53/root-hosted-zone.ts
1173
- import { Construct as Construct6 } from "constructs";
1174
- var RootHostedZone = class extends Construct6 {
1459
+ import { Construct as Construct7 } from "constructs";
1460
+ var RootHostedZone = class extends Construct7 {
1175
1461
  };
1176
1462
 
1177
1463
  // src/components/static-hosting/static-hosting.ts
@@ -1182,9 +1468,9 @@ import {
1182
1468
  import { S3BucketOrigin } from "aws-cdk-lib/aws-cloudfront-origins";
1183
1469
  import { Bucket as Bucket2 } from "aws-cdk-lib/aws-s3";
1184
1470
  import { Duration as Duration5 } from "aws-cdk-lib/core";
1185
- import { Construct as Construct7 } from "constructs";
1471
+ import { Construct as Construct8 } from "constructs";
1186
1472
  var STATIC_HOSTING_SERVICE_TYPE = "website";
1187
- var _StaticHosting = class _StaticHosting extends Construct7 {
1473
+ var _StaticHosting = class _StaticHosting extends Construct8 {
1188
1474
  constructor(scope, id, props = {}) {
1189
1475
  super(scope, id);
1190
1476
  const stack = OpenHiService.of(scope);
@@ -1236,7 +1522,7 @@ _StaticHosting.SSM_PARAM_NAME_DISTRIBUTION_ARN = "STATIC_HOSTING_DISTRIBUTION_AR
1236
1522
  var StaticHosting = _StaticHosting;
1237
1523
 
1238
1524
  // src/services/open-hi-auth-service.ts
1239
- var import_config4 = __toESM(require_lib());
1525
+ var import_config5 = __toESM(require_lib2());
1240
1526
  import {
1241
1527
  LambdaVersion,
1242
1528
  UserPool as UserPool2,
@@ -1244,12 +1530,13 @@ import {
1244
1530
  UserPoolDomain as UserPoolDomain2,
1245
1531
  UserPoolOperation
1246
1532
  } from "aws-cdk-lib/aws-cognito";
1247
- import { Effect, PolicyStatement } from "aws-cdk-lib/aws-iam";
1533
+ import { Effect as Effect6, PolicyStatement as PolicyStatement6 } from "aws-cdk-lib/aws-iam";
1248
1534
  import { Key as Key2 } from "aws-cdk-lib/aws-kms";
1249
- import { Stack as Stack3 } from "aws-cdk-lib/core";
1535
+ import { Stack as Stack6 } from "aws-cdk-lib/core";
1250
1536
 
1251
1537
  // src/services/open-hi-data-service.ts
1252
- import { StreamViewType, Table as Table2 } from "aws-cdk-lib/aws-dynamodb";
1538
+ var import_config4 = __toESM(require_lib2());
1539
+ import { StreamViewType, Table as Table3 } from "aws-cdk-lib/aws-dynamodb";
1253
1540
  import * as kinesis from "aws-cdk-lib/aws-kinesis";
1254
1541
 
1255
1542
  // src/services/open-hi-global-service.ts
@@ -1257,11 +1544,99 @@ import {
1257
1544
  Certificate as Certificate2,
1258
1545
  CertificateValidation
1259
1546
  } from "aws-cdk-lib/aws-certificatemanager";
1260
- import { EventBus as EventBus3 } from "aws-cdk-lib/aws-events";
1547
+ import { EventBus as EventBus4 } from "aws-cdk-lib/aws-events";
1261
1548
  import {
1262
1549
  HostedZone as HostedZone2
1263
1550
  } from "aws-cdk-lib/aws-route53";
1264
1551
  import { StringParameter as StringParameter3 } from "aws-cdk-lib/aws-ssm";
1552
+
1553
+ // src/workflows/control-plane/platform-deploy-bridge/platform-deploy-bridge.ts
1554
+ import { Construct as Construct10 } from "constructs";
1555
+
1556
+ // src/workflows/control-plane/platform-deploy-bridge/platform-deploy-bridge-lambda.ts
1557
+ import fs6 from "fs";
1558
+ import path6 from "path";
1559
+ import { Duration as Duration6, Stack as Stack3 } from "aws-cdk-lib";
1560
+ import { Rule } from "aws-cdk-lib/aws-events";
1561
+ import { LambdaFunction } from "aws-cdk-lib/aws-events-targets";
1562
+ import { Effect as Effect2, PolicyStatement as PolicyStatement2 } from "aws-cdk-lib/aws-iam";
1563
+ import { Runtime as Runtime6 } from "aws-cdk-lib/aws-lambda";
1564
+ import { NodejsFunction as NodejsFunction6 } from "aws-cdk-lib/aws-lambda-nodejs";
1565
+ import { Construct as Construct9 } from "constructs";
1566
+ var HANDLER_NAME6 = "platform-deploy-bridge.handler.js";
1567
+ function resolveHandlerEntry6(dirname) {
1568
+ const sameDir = path6.join(dirname, HANDLER_NAME6);
1569
+ if (fs6.existsSync(sameDir)) {
1570
+ return sameDir;
1571
+ }
1572
+ return path6.join(dirname, "..", "..", "..", "..", "lib", HANDLER_NAME6);
1573
+ }
1574
+ var PlatformDeployBridgeLambda = class extends Construct9 {
1575
+ constructor(scope, props) {
1576
+ super(scope, "platform-deploy-bridge-lambda");
1577
+ const service = OpenHiService.of(this);
1578
+ const repoTagKey = openHiTagKey(
1579
+ service.appName,
1580
+ OPENHI_TAG_SUFFIX_REPO_NAME
1581
+ );
1582
+ const tagKeyPrefix = `${service.appName}:`;
1583
+ const ownStackName = Stack3.of(this).stackName;
1584
+ const ownSuffix = `-${service.serviceId}-${Stack3.of(this).account}-${Stack3.of(this).region}`;
1585
+ const sharedPrefix = ownStackName.endsWith(ownSuffix) ? ownStackName.slice(0, -ownSuffix.length) : service.branchHash;
1586
+ const stackIdPrefix = `arn:aws:cloudformation:${Stack3.of(this).region}:${Stack3.of(this).account}:stack/${sharedPrefix}-`;
1587
+ this.lambda = new NodejsFunction6(this, "handler", {
1588
+ entry: resolveHandlerEntry6(__dirname),
1589
+ runtime: Runtime6.NODEJS_LATEST,
1590
+ memorySize: 256,
1591
+ timeout: Duration6.seconds(30),
1592
+ environment: {
1593
+ [CONTROL_EVENT_BUS_NAME_ENV_VAR]: props.controlEventBus.eventBusName,
1594
+ [OPENHI_REPO_TAG_KEY_ENV_VAR]: repoTagKey,
1595
+ [OPENHI_TAG_KEY_PREFIX_ENV_VAR]: tagKeyPrefix
1596
+ }
1597
+ });
1598
+ this.lambda.addToRolePolicy(
1599
+ new PolicyStatement2({
1600
+ effect: Effect2.ALLOW,
1601
+ actions: ["cloudformation:DescribeStacks"],
1602
+ resources: [
1603
+ `arn:aws:cloudformation:${Stack3.of(this).region}:${Stack3.of(this).account}:stack/*`
1604
+ ]
1605
+ })
1606
+ );
1607
+ props.controlEventBus.grantPutEventsTo(this.lambda);
1608
+ this.rule = new Rule(this, "rule", {
1609
+ eventPattern: {
1610
+ source: [CLOUDFORMATION_EVENT_SOURCE],
1611
+ detailType: [CLOUDFORMATION_STACK_STATUS_CHANGE_DETAIL_TYPE],
1612
+ detail: {
1613
+ "stack-id": [{ prefix: stackIdPrefix }],
1614
+ "status-details": {
1615
+ status: [...BRIDGED_STATUSES]
1616
+ }
1617
+ }
1618
+ },
1619
+ targets: [
1620
+ new LambdaFunction(this.lambda, {
1621
+ retryAttempts: 2,
1622
+ maxEventAge: Duration6.hours(2)
1623
+ })
1624
+ ]
1625
+ });
1626
+ }
1627
+ };
1628
+
1629
+ // src/workflows/control-plane/platform-deploy-bridge/platform-deploy-bridge.ts
1630
+ var PlatformDeployBridge = class extends Construct10 {
1631
+ constructor(scope, props) {
1632
+ super(scope, "platform-deploy-bridge");
1633
+ this.bridgeLambda = new PlatformDeployBridgeLambda(this, {
1634
+ controlEventBus: props.controlEventBus
1635
+ });
1636
+ }
1637
+ };
1638
+
1639
+ // src/services/open-hi-global-service.ts
1265
1640
  var _OpenHiGlobalService = class _OpenHiGlobalService extends OpenHiService {
1266
1641
  /**
1267
1642
  * Returns an IHostedZone from the given attributes (no SSM). Use when the zone is imported from config.
@@ -1300,7 +1675,7 @@ var _OpenHiGlobalService = class _OpenHiGlobalService extends OpenHiService {
1300
1675
  * Returns the data event bus by name (deterministic per branch). Use from other stacks to obtain an IEventBus reference.
1301
1676
  */
1302
1677
  static dataEventBusFromConstruct(scope) {
1303
- return EventBus3.fromEventBusName(
1678
+ return EventBus4.fromEventBusName(
1304
1679
  scope,
1305
1680
  "data-event-bus",
1306
1681
  DataEventBus.getEventBusName(scope)
@@ -1310,12 +1685,33 @@ var _OpenHiGlobalService = class _OpenHiGlobalService extends OpenHiService {
1310
1685
  * Returns the ops event bus by name (deterministic per branch). Use from other stacks to obtain an IEventBus reference.
1311
1686
  */
1312
1687
  static opsEventBusFromConstruct(scope) {
1313
- return EventBus3.fromEventBusName(
1688
+ return EventBus4.fromEventBusName(
1314
1689
  scope,
1315
1690
  "ops-event-bus",
1316
1691
  OpsEventBus.getEventBusName(scope)
1317
1692
  );
1318
1693
  }
1694
+ /**
1695
+ * Returns the control-plane event bus by name (deterministic per branch). Use from other stacks to obtain an IEventBus reference.
1696
+ */
1697
+ static controlEventBusFromConstruct(scope) {
1698
+ return EventBus4.fromEventBusName(
1699
+ scope,
1700
+ "control-event-bus",
1701
+ ControlEventBus.getEventBusName(scope)
1702
+ );
1703
+ }
1704
+ /**
1705
+ * Returns the workflow dedup table by name (deterministic per branch).
1706
+ * Use from other stacks to obtain an ITable reference. Consumer Lambdas
1707
+ * are typically wired via `WorkflowDedupTable.grantConsumer(fn, name)`
1708
+ * on the owning service's `workflowDedupTable` reference; the
1709
+ * `tableNameFromLookup` / `tableArnFromLookup` SSM helpers on the
1710
+ * construct cover cross-stack consumers that need only the name/ARN.
1711
+ */
1712
+ static workflowDedupTableNameFromLookup(scope) {
1713
+ return WorkflowDedupTable.tableNameFromLookup(scope);
1714
+ }
1319
1715
  get serviceType() {
1320
1716
  return _OpenHiGlobalService.SERVICE_TYPE;
1321
1717
  }
@@ -1328,6 +1724,9 @@ var _OpenHiGlobalService = class _OpenHiGlobalService extends OpenHiService {
1328
1724
  this.rootWildcardCertificate = this.createRootWildcardCertificate();
1329
1725
  this.dataEventBus = this.createDataEventBus();
1330
1726
  this.opsEventBus = this.createOpsEventBus();
1727
+ this.controlEventBus = this.createControlEventBus();
1728
+ this.workflowDedupTable = this.createWorkflowDedupTable();
1729
+ this.platformDeployBridge = this.createPlatformDeployBridge();
1331
1730
  }
1332
1731
  /**
1333
1732
  * Validates that config required for the Global stack is present.
@@ -1392,23 +1791,249 @@ var _OpenHiGlobalService = class _OpenHiGlobalService extends OpenHiService {
1392
1791
  createOpsEventBus() {
1393
1792
  return new OpsEventBus(this);
1394
1793
  }
1794
+ /**
1795
+ * Creates the control-plane event bus.
1796
+ * Override to customize.
1797
+ */
1798
+ createControlEventBus() {
1799
+ return new ControlEventBus(this);
1800
+ }
1801
+ /**
1802
+ * Creates the platform deploy bridge that republishes CloudFormation
1803
+ * Stack Status Change events onto the control event bus.
1804
+ * Override to customize.
1805
+ */
1806
+ createPlatformDeployBridge() {
1807
+ return new PlatformDeployBridge(this, {
1808
+ controlEventBus: this.controlEventBus
1809
+ });
1810
+ }
1811
+ /**
1812
+ * Creates the shared workflow dedup table (TR-015 singleton).
1813
+ * Override to customize.
1814
+ */
1815
+ createWorkflowDedupTable() {
1816
+ return new WorkflowDedupTable(this, "workflow-dedup-table");
1817
+ }
1395
1818
  };
1396
1819
  _OpenHiGlobalService.SERVICE_TYPE = "global";
1397
1820
  var OpenHiGlobalService = _OpenHiGlobalService;
1398
1821
 
1399
- // src/services/open-hi-data-service.ts
1400
- var _OpenHiDataService = class _OpenHiDataService extends OpenHiService {
1401
- /**
1402
- * Returns the data store table by name. Use from other stacks (e.g. REST API Lambda) to obtain an ITable reference.
1403
- */
1404
- static dynamoDbDataStoreFromConstruct(scope, id = "dynamo-db-data-store") {
1405
- return Table2.fromTableName(scope, id, getDynamoDbDataStoreTableName(scope));
1822
+ // src/workflows/control-plane/seed-demo-data/seed-demo-data-lambda.ts
1823
+ import fs7 from "fs";
1824
+ import path7 from "path";
1825
+ import { CONTROL_PLANE_ROLE_IDS } from "@openhi/types";
1826
+ import { Duration as Duration7, Stack as Stack4 } from "aws-cdk-lib";
1827
+ import { Rule as Rule2 } from "aws-cdk-lib/aws-events";
1828
+ import { LambdaFunction as LambdaFunction2 } from "aws-cdk-lib/aws-events-targets";
1829
+ import { Effect as Effect3, PolicyStatement as PolicyStatement3 } from "aws-cdk-lib/aws-iam";
1830
+ import { Runtime as Runtime7 } from "aws-cdk-lib/aws-lambda";
1831
+ import { NodejsFunction as NodejsFunction7 } from "aws-cdk-lib/aws-lambda-nodejs";
1832
+ import { Construct as Construct11 } from "constructs";
1833
+ var HANDLER_NAME7 = "seed-demo-data.handler.js";
1834
+ function resolveHandlerEntry7(dirname) {
1835
+ const sameDir = path7.join(dirname, HANDLER_NAME7);
1836
+ if (fs7.existsSync(sameDir)) {
1837
+ return sameDir;
1406
1838
  }
1407
- get serviceType() {
1408
- return _OpenHiDataService.SERVICE_TYPE;
1839
+ return path7.join(dirname, "..", "..", "..", "..", "lib", HANDLER_NAME7);
1840
+ }
1841
+ var SeedDemoDataLambda = class extends Construct11 {
1842
+ constructor(scope, props) {
1843
+ super(scope, "seed-demo-data-lambda");
1844
+ this.lambda = new NodejsFunction7(this, "handler", {
1845
+ entry: resolveHandlerEntry7(__dirname),
1846
+ runtime: Runtime7.NODEJS_LATEST,
1847
+ memorySize: 512,
1848
+ timeout: Duration7.minutes(2),
1849
+ environment: {
1850
+ DYNAMO_TABLE_NAME: props.dataStoreTable.tableName,
1851
+ [SEED_DEMO_DATA_USER_POOL_ID_ENV_VAR]: props.userPool.userPoolId
1852
+ }
1853
+ });
1854
+ const roleReadKeys = Object.values(CONTROL_PLANE_ROLE_IDS).map(
1855
+ rolePartitionKey
1856
+ );
1857
+ this.lambda.addToRolePolicy(
1858
+ new PolicyStatement3({
1859
+ effect: Effect3.ALLOW,
1860
+ actions: ["dynamodb:GetItem"],
1861
+ resources: [props.dataStoreTable.tableArn],
1862
+ conditions: {
1863
+ "ForAllValues:StringEquals": {
1864
+ "dynamodb:LeadingKeys": roleReadKeys
1865
+ }
1866
+ }
1867
+ })
1868
+ );
1869
+ const writeKeys = [
1870
+ ...demoBasePartitionKeys(),
1871
+ ...demoDevUserPartitionKeys(DEV_USERS)
1872
+ ];
1873
+ this.lambda.addToRolePolicy(
1874
+ new PolicyStatement3({
1875
+ effect: Effect3.ALLOW,
1876
+ actions: ["dynamodb:PutItem", "dynamodb:UpdateItem"],
1877
+ resources: [props.dataStoreTable.tableArn],
1878
+ conditions: {
1879
+ "ForAllValues:StringEquals": {
1880
+ "dynamodb:LeadingKeys": writeKeys
1881
+ }
1882
+ }
1883
+ })
1884
+ );
1885
+ this.lambda.addToRolePolicy(
1886
+ new PolicyStatement3({
1887
+ effect: Effect3.ALLOW,
1888
+ actions: [
1889
+ "cognito-idp:AdminCreateUser",
1890
+ "cognito-idp:AdminGetUser",
1891
+ "cognito-idp:AdminSetUserPassword"
1892
+ ],
1893
+ resources: [
1894
+ Stack4.of(this).formatArn({
1895
+ service: "cognito-idp",
1896
+ resource: "userpool",
1897
+ resourceName: props.userPool.userPoolId
1898
+ })
1899
+ ]
1900
+ })
1901
+ );
1902
+ this.rule = new Rule2(this, "rule", {
1903
+ eventBus: props.controlEventBus,
1904
+ eventPattern: {
1905
+ source: [import_workflows.PlatformSystemDataSeededV1.source],
1906
+ detailType: [import_workflows.PlatformSystemDataSeededV1.detailType]
1907
+ },
1908
+ targets: [
1909
+ new LambdaFunction2(this.lambda, {
1910
+ retryAttempts: 2,
1911
+ maxEventAge: Duration7.hours(2)
1912
+ })
1913
+ ]
1914
+ });
1915
+ }
1916
+ };
1917
+
1918
+ // src/workflows/control-plane/seed-demo-data/seed-demo-data-workflow.ts
1919
+ import { Construct as Construct12 } from "constructs";
1920
+ var SeedDemoDataWorkflow = class extends Construct12 {
1921
+ constructor(scope, props) {
1922
+ super(scope, "seed-demo-data-workflow");
1923
+ this.seedDemoData = new SeedDemoDataLambda(this, {
1924
+ controlEventBus: props.controlEventBus,
1925
+ dataStoreTable: props.dataStoreTable,
1926
+ userPool: props.userPool
1927
+ });
1928
+ WorkflowDedupTable.grantConsumerFromLookup(
1929
+ this,
1930
+ this.seedDemoData.lambda,
1931
+ SEED_DEMO_DATA_CONSUMER_NAME
1932
+ );
1933
+ }
1934
+ };
1935
+
1936
+ // src/workflows/control-plane/seed-system-data/seed-system-data-lambda.ts
1937
+ import fs8 from "fs";
1938
+ import path8 from "path";
1939
+ import { CONTROL_PLANE_ROLE_IDS as CONTROL_PLANE_ROLE_IDS2 } from "@openhi/types";
1940
+ import { Duration as Duration8, Stack as Stack5 } from "aws-cdk-lib";
1941
+ import { Rule as Rule3 } from "aws-cdk-lib/aws-events";
1942
+ import { LambdaFunction as LambdaFunction3 } from "aws-cdk-lib/aws-events-targets";
1943
+ import { Effect as Effect4, PolicyStatement as PolicyStatement4 } from "aws-cdk-lib/aws-iam";
1944
+ import { Runtime as Runtime8 } from "aws-cdk-lib/aws-lambda";
1945
+ import { NodejsFunction as NodejsFunction8 } from "aws-cdk-lib/aws-lambda-nodejs";
1946
+ import { Construct as Construct13 } from "constructs";
1947
+ var HANDLER_NAME8 = "seed-system-data.handler.js";
1948
+ function resolveHandlerEntry8(dirname) {
1949
+ const sameDir = path8.join(dirname, HANDLER_NAME8);
1950
+ if (fs8.existsSync(sameDir)) {
1951
+ return sameDir;
1952
+ }
1953
+ return path8.join(dirname, "..", "..", "..", "..", "lib", HANDLER_NAME8);
1954
+ }
1955
+ var SeedSystemDataLambda = class extends Construct13 {
1956
+ constructor(scope, props) {
1957
+ super(scope, "seed-system-data-lambda");
1958
+ this.lambda = new NodejsFunction8(this, "handler", {
1959
+ entry: resolveHandlerEntry8(__dirname),
1960
+ runtime: Runtime8.NODEJS_LATEST,
1961
+ memorySize: 512,
1962
+ timeout: Duration8.minutes(1),
1963
+ environment: {
1964
+ DYNAMO_TABLE_NAME: props.dataStoreTable.tableName,
1965
+ [SEED_SYSTEM_DATA_CONTROL_BUS_ENV_VAR]: props.controlEventBus.eventBusName
1966
+ }
1967
+ });
1968
+ const roleArns = Object.values(CONTROL_PLANE_ROLE_IDS2).map(
1969
+ (id) => `role#id#${id}`
1970
+ );
1971
+ this.lambda.addToRolePolicy(
1972
+ new PolicyStatement4({
1973
+ effect: Effect4.ALLOW,
1974
+ actions: ["dynamodb:PutItem", "dynamodb:UpdateItem"],
1975
+ resources: [props.dataStoreTable.tableArn],
1976
+ conditions: {
1977
+ "ForAllValues:StringEquals": {
1978
+ "dynamodb:LeadingKeys": roleArns
1979
+ }
1980
+ }
1981
+ })
1982
+ );
1983
+ props.controlEventBus.grantPutEventsTo(this.lambda);
1984
+ const hostStackName = Stack5.of(this).stackName;
1985
+ this.rule = new Rule3(this, "rule", {
1986
+ eventBus: props.controlEventBus,
1987
+ eventPattern: {
1988
+ source: [import_workflows2.PlatformDeploymentCompletedV1.source],
1989
+ detailType: [import_workflows2.PlatformDeploymentCompletedV1.detailType],
1990
+ detail: {
1991
+ payload: {
1992
+ stackName: [hostStackName]
1993
+ }
1994
+ }
1995
+ },
1996
+ targets: [
1997
+ new LambdaFunction3(this.lambda, {
1998
+ retryAttempts: 2,
1999
+ maxEventAge: Duration8.hours(2)
2000
+ })
2001
+ ]
2002
+ });
1409
2003
  }
2004
+ };
2005
+
2006
+ // src/workflows/control-plane/seed-system-data/seed-system-data-workflow.ts
2007
+ import { Construct as Construct14 } from "constructs";
2008
+ var SeedSystemDataWorkflow = class extends Construct14 {
2009
+ constructor(scope, props) {
2010
+ super(scope, "seed-system-data-workflow");
2011
+ this.seedSystemData = new SeedSystemDataLambda(this, {
2012
+ controlEventBus: props.controlEventBus,
2013
+ dataStoreTable: props.dataStoreTable
2014
+ });
2015
+ WorkflowDedupTable.grantConsumerFromLookup(
2016
+ this,
2017
+ this.seedSystemData.lambda,
2018
+ SEED_SYSTEM_DATA_CONSUMER_NAME
2019
+ );
2020
+ }
2021
+ };
2022
+
2023
+ // src/services/open-hi-data-service.ts
2024
+ var _OpenHiDataService = class _OpenHiDataService extends OpenHiService {
1410
2025
  constructor(ohEnv, props = {}) {
1411
2026
  super(ohEnv, _OpenHiDataService.SERVICE_TYPE, props);
2027
+ /**
2028
+ * Cached control-event-bus lookup. `OpenHiGlobalService.controlEventBusFromConstruct`
2029
+ * registers a child `EventBus.fromEventBusName` construct with a
2030
+ * fixed id under the scope it is passed, so calling it twice on the
2031
+ * same `OpenHiDataService` instance collides. The cache mirrors the
2032
+ * `private controlEventBus()` pattern already used in
2033
+ * `OpenHiAuthService`. Use {@link controlEventBus} from this class
2034
+ * — never call the static lookup from inside `OpenHiDataService`.
2035
+ */
2036
+ this._controlEventBus = null;
1412
2037
  this.props = props;
1413
2038
  this.dataStoreChangeStream = new kinesis.Stream(
1414
2039
  this,
@@ -1443,6 +2068,53 @@ var _OpenHiDataService = class _OpenHiDataService extends OpenHiService {
1443
2068
  branchHash: this.branchHash
1444
2069
  }
1445
2070
  );
2071
+ this.seedSystemDataWorkflow = this.createSeedSystemDataWorkflow();
2072
+ this.seedDemoDataWorkflow = this.createSeedDemoDataWorkflow();
2073
+ }
2074
+ /**
2075
+ * Returns the data store table by name. Use from other stacks (e.g. REST API Lambda) to obtain an ITable reference.
2076
+ */
2077
+ static dynamoDbDataStoreFromConstruct(scope, id = "dynamo-db-data-store") {
2078
+ return Table3.fromTableName(scope, id, getDynamoDbDataStoreTableName(scope));
2079
+ }
2080
+ get serviceType() {
2081
+ return _OpenHiDataService.SERVICE_TYPE;
2082
+ }
2083
+ /**
2084
+ * Lazily looks up the control event bus exactly once per
2085
+ * `OpenHiDataService` instance and caches the reference. Every
2086
+ * workflow that consumes the bus must read it through this method
2087
+ * — see {@link _controlEventBus} for the underlying collision risk.
2088
+ */
2089
+ controlEventBus() {
2090
+ if (this._controlEventBus === null) {
2091
+ this._controlEventBus = OpenHiGlobalService.controlEventBusFromConstruct(this);
2092
+ }
2093
+ return this._controlEventBus;
2094
+ }
2095
+ /**
2096
+ * Creates the seed-system-data workflow. Override to customize.
2097
+ */
2098
+ createSeedSystemDataWorkflow() {
2099
+ return new SeedSystemDataWorkflow(this, {
2100
+ controlEventBus: this.controlEventBus(),
2101
+ dataStoreTable: this.dataStore
2102
+ });
2103
+ }
2104
+ /**
2105
+ * Creates the seed-demo-data workflow — but only on non-prod
2106
+ * stages. Returns `undefined` on prod so the workflow literally
2107
+ * does not exist in prod stacks. Override to customize.
2108
+ */
2109
+ createSeedDemoDataWorkflow() {
2110
+ if (this.ohEnv.ohStage.stageType === import_config4.OPEN_HI_STAGE.PROD) {
2111
+ return void 0;
2112
+ }
2113
+ return new SeedDemoDataWorkflow(this, {
2114
+ controlEventBus: this.controlEventBus(),
2115
+ dataStoreTable: this.dataStore,
2116
+ userPool: OpenHiAuthService.userPoolFromConstruct(this)
2117
+ });
1446
2118
  }
1447
2119
  /**
1448
2120
  * Creates the single-table DynamoDB data store.
@@ -1458,6 +2130,75 @@ var _OpenHiDataService = class _OpenHiDataService extends OpenHiService {
1458
2130
  _OpenHiDataService.SERVICE_TYPE = "data";
1459
2131
  var OpenHiDataService = _OpenHiDataService;
1460
2132
 
2133
+ // src/workflows/control-plane/user-onboarding/provision-default-workspace-lambda.ts
2134
+ import fs9 from "fs";
2135
+ import path9 from "path";
2136
+ import { Duration as Duration9 } from "aws-cdk-lib";
2137
+ import { Rule as Rule4 } from "aws-cdk-lib/aws-events";
2138
+ import { LambdaFunction as LambdaFunction4 } from "aws-cdk-lib/aws-events-targets";
2139
+ import { Effect as Effect5, PolicyStatement as PolicyStatement5 } from "aws-cdk-lib/aws-iam";
2140
+ import { Runtime as Runtime9 } from "aws-cdk-lib/aws-lambda";
2141
+ import { NodejsFunction as NodejsFunction9 } from "aws-cdk-lib/aws-lambda-nodejs";
2142
+ import { Construct as Construct15 } from "constructs";
2143
+ var HANDLER_NAME9 = "provision-default-workspace.handler.js";
2144
+ function resolveHandlerEntry9(dirname) {
2145
+ const sameDir = path9.join(dirname, HANDLER_NAME9);
2146
+ if (fs9.existsSync(sameDir)) {
2147
+ return sameDir;
2148
+ }
2149
+ return path9.join(dirname, "..", "..", "..", "..", "lib", HANDLER_NAME9);
2150
+ }
2151
+ var ProvisionDefaultWorkspaceLambda = class extends Construct15 {
2152
+ constructor(scope, props) {
2153
+ super(scope, "provision-default-workspace-lambda");
2154
+ this.lambda = new NodejsFunction9(this, "handler", {
2155
+ entry: resolveHandlerEntry9(__dirname),
2156
+ runtime: Runtime9.NODEJS_LATEST,
2157
+ memorySize: 1024,
2158
+ environment: {
2159
+ DYNAMO_TABLE_NAME: props.dataStoreTable.tableName
2160
+ }
2161
+ });
2162
+ props.dataStoreTable.grant(
2163
+ this.lambda,
2164
+ "dynamodb:PutItem",
2165
+ "dynamodb:UpdateItem"
2166
+ );
2167
+ this.lambda.addToRolePolicy(
2168
+ new PolicyStatement5({
2169
+ effect: Effect5.ALLOW,
2170
+ actions: ["dynamodb:Query"],
2171
+ resources: [`${props.dataStoreTable.tableArn}/index/*`]
2172
+ })
2173
+ );
2174
+ this.rule = new Rule4(this, "rule", {
2175
+ eventBus: props.controlEventBus,
2176
+ eventPattern: {
2177
+ source: [USER_ONBOARDING_EVENT_SOURCE],
2178
+ detailType: [PROVISION_DEFAULT_WORKSPACE_DETAIL_TYPE]
2179
+ },
2180
+ targets: [
2181
+ new LambdaFunction4(this.lambda, {
2182
+ retryAttempts: 2,
2183
+ maxEventAge: Duration9.hours(2)
2184
+ })
2185
+ ]
2186
+ });
2187
+ }
2188
+ };
2189
+
2190
+ // src/workflows/control-plane/user-onboarding/user-onboarding-workflow.ts
2191
+ import { Construct as Construct16 } from "constructs";
2192
+ var UserOnboardingWorkflow = class extends Construct16 {
2193
+ constructor(scope, props) {
2194
+ super(scope, "user-onboarding-workflow");
2195
+ this.provisionDefaultWorkspace = new ProvisionDefaultWorkspaceLambda(this, {
2196
+ dataStoreTable: props.dataStoreTable,
2197
+ controlEventBus: props.controlEventBus
2198
+ });
2199
+ }
2200
+ };
2201
+
1461
2202
  // src/services/open-hi-auth-service.ts
1462
2203
  var _OpenHiAuthService = class _OpenHiAuthService extends OpenHiService {
1463
2204
  constructor(ohEnv, props = {}) {
@@ -1469,11 +2210,13 @@ var _OpenHiAuthService = class _OpenHiAuthService extends OpenHiService {
1469
2210
  * would collide.
1470
2211
  */
1471
2212
  this._dataStoreTable = null;
2213
+ this._controlEventBus = null;
1472
2214
  this.props = props;
1473
2215
  this.userPoolKmsKey = this.createUserPoolKmsKey();
1474
2216
  this.preTokenGenerationLambda = this.createPreTokenGenerationLambda();
1475
2217
  this.postAuthenticationLambda = this.createPostAuthenticationLambda();
1476
2218
  this.postConfirmationLambda = this.createPostConfirmationLambda();
2219
+ this.userOnboardingWorkflow = this.createUserOnboardingWorkflow();
1477
2220
  this.userPool = this.createUserPool();
1478
2221
  this.grantPreTokenGenerationPermissions();
1479
2222
  this.grantPostAuthenticationPermissions();
@@ -1590,23 +2333,33 @@ var _OpenHiAuthService = class _OpenHiAuthService extends OpenHiService {
1590
2333
  }
1591
2334
  /**
1592
2335
  * Creates the Post Confirmation Lambda (Cognito trigger). On sign-up
1593
- * confirmation, writes the new user's default Tenant, Workspace,
1594
- * Memberships, and `tenant-user` RoleAssignment, plus a User record
1595
- * carrying the Cognito `sub` and current tenant/workspace pointers
1596
- * (ADR 2026-03-17-01 invariants).
2336
+ * confirmation, publishes a control-plane workflow event; provisioning lives
2337
+ * behind EventBridge.
1597
2338
  */
1598
2339
  createPostConfirmationLambda() {
1599
2340
  const construct = new PostConfirmationLambda(this, {
1600
- dynamoTableName: this.dataStoreTable().tableName
2341
+ controlEventBusName: this.controlEventBus().eventBusName
1601
2342
  });
1602
2343
  return construct.lambda;
1603
2344
  }
2345
+ createUserOnboardingWorkflow() {
2346
+ return new UserOnboardingWorkflow(this, {
2347
+ controlEventBus: this.controlEventBus(),
2348
+ dataStoreTable: this.dataStoreTable()
2349
+ });
2350
+ }
1604
2351
  dataStoreTable() {
1605
2352
  if (this._dataStoreTable === null) {
1606
2353
  this._dataStoreTable = OpenHiDataService.dynamoDbDataStoreFromConstruct(this);
1607
2354
  }
1608
2355
  return this._dataStoreTable;
1609
2356
  }
2357
+ controlEventBus() {
2358
+ if (this._controlEventBus === null) {
2359
+ this._controlEventBus = OpenHiGlobalService.controlEventBusFromConstruct(this);
2360
+ }
2361
+ return this._controlEventBus;
2362
+ }
1610
2363
  /**
1611
2364
  * Creates the Cognito User Pool and exports its ID to SSM.
1612
2365
  * Look up via {@link OpenHiAuthService.userPoolFromConstruct}.
@@ -1651,8 +2404,8 @@ var _OpenHiAuthService = class _OpenHiAuthService extends OpenHiService {
1651
2404
  const dynamoActions = ["dynamodb:GetItem", "dynamodb:Query"];
1652
2405
  dataStoreTable.grant(this.preTokenGenerationLambda, ...dynamoActions);
1653
2406
  this.preTokenGenerationLambda.addToRolePolicy(
1654
- new PolicyStatement({
1655
- effect: Effect.ALLOW,
2407
+ new PolicyStatement6({
2408
+ effect: Effect6.ALLOW,
1656
2409
  actions: [...dynamoActions],
1657
2410
  resources: [`${dataStoreTable.tableArn}/index/*`]
1658
2411
  })
@@ -1673,10 +2426,10 @@ var _OpenHiAuthService = class _OpenHiAuthService extends OpenHiService {
1673
2426
  */
1674
2427
  grantPostAuthenticationPermissions() {
1675
2428
  this.postAuthenticationLambda.addToRolePolicy(
1676
- new PolicyStatement({
2429
+ new PolicyStatement6({
1677
2430
  actions: ["cognito-idp:AdminUserGlobalSignOut"],
1678
2431
  resources: [
1679
- Stack3.of(this).formatArn({
2432
+ Stack6.of(this).formatArn({
1680
2433
  service: "cognito-idp",
1681
2434
  resource: "userpool",
1682
2435
  resourceName: "*"
@@ -1686,26 +2439,11 @@ var _OpenHiAuthService = class _OpenHiAuthService extends OpenHiService {
1686
2439
  );
1687
2440
  }
1688
2441
  /**
1689
- * Grants the Post Confirmation Lambda write access to the data store
1690
- * table (and its GSIs) so it can seed the new user's Tenant, Workspace,
1691
- * Memberships, RoleAssignment, and User records on sign-up confirmation.
2442
+ * Grants the Post Confirmation Lambda publish-only access to the
2443
+ * control-plane event bus. Workflow Lambdas own DynamoDB writes.
1692
2444
  */
1693
2445
  grantPostConfirmationPermissions() {
1694
- const dataStoreTable = this.dataStoreTable();
1695
- const dynamoActions = [
1696
- "dynamodb:PutItem",
1697
- "dynamodb:UpdateItem",
1698
- "dynamodb:BatchWriteItem",
1699
- "dynamodb:DescribeTable"
1700
- ];
1701
- dataStoreTable.grant(this.postConfirmationLambda, ...dynamoActions);
1702
- this.postConfirmationLambda.addToRolePolicy(
1703
- new PolicyStatement({
1704
- effect: Effect.ALLOW,
1705
- actions: [...dynamoActions],
1706
- resources: [`${dataStoreTable.tableArn}/index/*`]
1707
- })
1708
- );
2446
+ this.controlEventBus().grantPutEventsTo(this.postConfirmationLambda);
1709
2447
  }
1710
2448
  /**
1711
2449
  * Creates the User Pool Client and exports its ID to SSM (AUTH service type).
@@ -1735,7 +2473,7 @@ var _OpenHiAuthService = class _OpenHiAuthService extends OpenHiService {
1735
2473
  * via env vars to drive `InitiateAuth`.
1736
2474
  */
1737
2475
  createFixtureSeederClient() {
1738
- if (this.ohEnv.ohStage.stageType === import_config4.OPEN_HI_STAGE.PROD) {
2476
+ if (this.ohEnv.ohStage.stageType === import_config5.OPEN_HI_STAGE.PROD) {
1739
2477
  return void 0;
1740
2478
  }
1741
2479
  const client = new CognitoFixtureSeederClient(this, {
@@ -1772,7 +2510,7 @@ _OpenHiAuthService.SERVICE_TYPE = "auth";
1772
2510
  var OpenHiAuthService = _OpenHiAuthService;
1773
2511
 
1774
2512
  // src/services/open-hi-rest-api-service.ts
1775
- var import_config5 = __toESM(require_lib());
2513
+ var import_config6 = __toESM(require_lib2());
1776
2514
  import {
1777
2515
  CorsHttpMethod,
1778
2516
  DomainName,
@@ -1784,62 +2522,62 @@ import {
1784
2522
  } from "aws-cdk-lib/aws-apigatewayv2";
1785
2523
  import { HttpUserPoolAuthorizer } from "aws-cdk-lib/aws-apigatewayv2-authorizers";
1786
2524
  import { HttpLambdaIntegration } from "aws-cdk-lib/aws-apigatewayv2-integrations";
1787
- import { Effect as Effect2, PolicyStatement as PolicyStatement2 } from "aws-cdk-lib/aws-iam";
2525
+ import { Effect as Effect7, PolicyStatement as PolicyStatement7 } from "aws-cdk-lib/aws-iam";
1788
2526
  import {
1789
2527
  ARecord,
1790
2528
  HostedZone as HostedZone3,
1791
2529
  RecordTarget
1792
2530
  } from "aws-cdk-lib/aws-route53";
1793
2531
  import { ApiGatewayv2DomainProperties } from "aws-cdk-lib/aws-route53-targets";
1794
- import { Duration as Duration6 } from "aws-cdk-lib/core";
2532
+ import { Duration as Duration10 } from "aws-cdk-lib/core";
1795
2533
 
1796
2534
  // src/data/lambda/cors-options-lambda.ts
1797
- import fs6 from "fs";
1798
- import path6 from "path";
1799
- import { Runtime as Runtime6 } from "aws-cdk-lib/aws-lambda";
1800
- import { NodejsFunction as NodejsFunction6 } from "aws-cdk-lib/aws-lambda-nodejs";
1801
- import { Construct as Construct8 } from "constructs";
1802
- var HANDLER_NAME6 = "cors-options-lambda.handler.js";
1803
- function resolveHandlerEntry6(dirname) {
1804
- const sameDir = path6.join(dirname, HANDLER_NAME6);
1805
- if (fs6.existsSync(sameDir)) {
2535
+ import fs10 from "fs";
2536
+ import path10 from "path";
2537
+ import { Runtime as Runtime10 } from "aws-cdk-lib/aws-lambda";
2538
+ import { NodejsFunction as NodejsFunction10 } from "aws-cdk-lib/aws-lambda-nodejs";
2539
+ import { Construct as Construct17 } from "constructs";
2540
+ var HANDLER_NAME10 = "cors-options-lambda.handler.js";
2541
+ function resolveHandlerEntry10(dirname) {
2542
+ const sameDir = path10.join(dirname, HANDLER_NAME10);
2543
+ if (fs10.existsSync(sameDir)) {
1806
2544
  return sameDir;
1807
2545
  }
1808
- const fromLib = path6.join(dirname, "..", "..", "..", "lib", HANDLER_NAME6);
2546
+ const fromLib = path10.join(dirname, "..", "..", "..", "lib", HANDLER_NAME10);
1809
2547
  return fromLib;
1810
2548
  }
1811
- var CorsOptionsLambda = class extends Construct8 {
2549
+ var CorsOptionsLambda = class extends Construct17 {
1812
2550
  constructor(scope, id = "cors-options-lambda") {
1813
2551
  super(scope, id);
1814
- this.lambda = new NodejsFunction6(this, "handler", {
1815
- entry: resolveHandlerEntry6(__dirname),
1816
- runtime: Runtime6.NODEJS_LATEST,
2552
+ this.lambda = new NodejsFunction10(this, "handler", {
2553
+ entry: resolveHandlerEntry10(__dirname),
2554
+ runtime: Runtime10.NODEJS_LATEST,
1817
2555
  memorySize: 128
1818
2556
  });
1819
2557
  }
1820
2558
  };
1821
2559
 
1822
2560
  // src/data/lambda/rest-api-lambda.ts
1823
- import fs7 from "fs";
1824
- import path7 from "path";
1825
- import { Runtime as Runtime7 } from "aws-cdk-lib/aws-lambda";
1826
- import { NodejsFunction as NodejsFunction7 } from "aws-cdk-lib/aws-lambda-nodejs";
1827
- import { Construct as Construct9 } from "constructs";
1828
- var HANDLER_NAME7 = "rest-api-lambda.handler.js";
1829
- function resolveHandlerEntry7(dirname) {
1830
- const sameDir = path7.join(dirname, HANDLER_NAME7);
1831
- if (fs7.existsSync(sameDir)) {
2561
+ import fs11 from "fs";
2562
+ import path11 from "path";
2563
+ import { Runtime as Runtime11 } from "aws-cdk-lib/aws-lambda";
2564
+ import { NodejsFunction as NodejsFunction11 } from "aws-cdk-lib/aws-lambda-nodejs";
2565
+ import { Construct as Construct18 } from "constructs";
2566
+ var HANDLER_NAME11 = "rest-api-lambda.handler.js";
2567
+ function resolveHandlerEntry11(dirname) {
2568
+ const sameDir = path11.join(dirname, HANDLER_NAME11);
2569
+ if (fs11.existsSync(sameDir)) {
1832
2570
  return sameDir;
1833
2571
  }
1834
- const fromLib = path7.join(dirname, "..", "..", "..", "lib", HANDLER_NAME7);
2572
+ const fromLib = path11.join(dirname, "..", "..", "..", "lib", HANDLER_NAME11);
1835
2573
  return fromLib;
1836
2574
  }
1837
- var RestApiLambda = class extends Construct9 {
2575
+ var RestApiLambda = class extends Construct18 {
1838
2576
  constructor(scope, props) {
1839
2577
  super(scope, "rest-api-lambda");
1840
- this.lambda = new NodejsFunction7(this, "handler", {
1841
- entry: resolveHandlerEntry7(__dirname),
1842
- runtime: Runtime7.NODEJS_LATEST,
2578
+ this.lambda = new NodejsFunction11(this, "handler", {
2579
+ entry: resolveHandlerEntry11(__dirname),
2580
+ runtime: Runtime11.NODEJS_LATEST,
1843
2581
  memorySize: 1024,
1844
2582
  environment: {
1845
2583
  DYNAMO_TABLE_NAME: props.dynamoTableName,
@@ -1981,8 +2719,8 @@ var _OpenHiRestApiService = class _OpenHiRestApiService extends OpenHiService {
1981
2719
  postgresSchema
1982
2720
  });
1983
2721
  lambda.addToRolePolicy(
1984
- new PolicyStatement2({
1985
- effect: Effect2.ALLOW,
2722
+ new PolicyStatement7({
2723
+ effect: Effect7.ALLOW,
1986
2724
  actions: [
1987
2725
  "rds-data:ExecuteStatement",
1988
2726
  "rds-data:BatchExecuteStatement"
@@ -1991,8 +2729,8 @@ var _OpenHiRestApiService = class _OpenHiRestApiService extends OpenHiService {
1991
2729
  })
1992
2730
  );
1993
2731
  lambda.addToRolePolicy(
1994
- new PolicyStatement2({
1995
- effect: Effect2.ALLOW,
2732
+ new PolicyStatement7({
2733
+ effect: Effect7.ALLOW,
1996
2734
  actions: ["secretsmanager:GetSecretValue"],
1997
2735
  resources: [postgresSecretArn]
1998
2736
  })
@@ -2010,15 +2748,15 @@ var _OpenHiRestApiService = class _OpenHiRestApiService extends OpenHiService {
2010
2748
  ];
2011
2749
  dataStoreTable.grant(lambda, ...dynamoActions);
2012
2750
  lambda.addToRolePolicy(
2013
- new PolicyStatement2({
2014
- effect: Effect2.ALLOW,
2751
+ new PolicyStatement7({
2752
+ effect: Effect7.ALLOW,
2015
2753
  actions: [...dynamoActions],
2016
2754
  resources: [`${dataStoreTable.tableArn}/index/*`]
2017
2755
  })
2018
2756
  );
2019
2757
  lambda.addToRolePolicy(
2020
- new PolicyStatement2({
2021
- effect: Effect2.ALLOW,
2758
+ new PolicyStatement7({
2759
+ effect: Effect7.ALLOW,
2022
2760
  actions: [
2023
2761
  "ssm:GetParameter",
2024
2762
  "ssm:GetParameters",
@@ -2077,7 +2815,7 @@ var _OpenHiRestApiService = class _OpenHiRestApiService extends OpenHiService {
2077
2815
  const userPool = OpenHiAuthService.userPoolFromConstruct(this);
2078
2816
  const userPoolClient = OpenHiAuthService.userPoolClientFromConstruct(this);
2079
2817
  const userPoolClients = [userPoolClient];
2080
- if (this.ohEnv.ohStage.stageType !== import_config5.OPEN_HI_STAGE.PROD) {
2818
+ if (this.ohEnv.ohStage.stageType !== import_config6.OPEN_HI_STAGE.PROD) {
2081
2819
  userPoolClients.push(
2082
2820
  OpenHiAuthService.fixtureSeederClientFromConstruct(this)
2083
2821
  );
@@ -2104,7 +2842,7 @@ var _OpenHiRestApiService = class _OpenHiRestApiService extends OpenHiService {
2104
2842
  "Authorization"
2105
2843
  ],
2106
2844
  allowCredentials: cors.allowCredentials ?? true,
2107
- maxAge: cors.maxAge ?? Duration6.days(1),
2845
+ maxAge: cors.maxAge ?? Duration10.days(1),
2108
2846
  ...cors.exposeHeaders !== void 0 && {
2109
2847
  exposeHeaders: cors.exposeHeaders
2110
2848
  }
@@ -2168,21 +2906,38 @@ var _OpenHiGraphqlService = class _OpenHiGraphqlService extends OpenHiService {
2168
2906
  };
2169
2907
  _OpenHiGraphqlService.SERVICE_TYPE = "graphql-api";
2170
2908
  var OpenHiGraphqlService = _OpenHiGraphqlService;
2909
+ var export_PlatformDeploymentCompletedV1 = import_workflows2.PlatformDeploymentCompletedV1;
2171
2910
  export {
2911
+ BRIDGED_STATUSES,
2912
+ CLOUDFORMATION_EVENT_SOURCE,
2913
+ CLOUDFORMATION_STACK_STATUS_CHANGE_DETAIL_TYPE,
2914
+ CONTROL_EVENT_BUS_NAME_ENV_VAR,
2172
2915
  ChildHostedZone,
2173
2916
  CognitoFixtureSeederClient,
2174
2917
  CognitoUserPool,
2175
2918
  CognitoUserPoolClient,
2176
2919
  CognitoUserPoolDomain,
2177
2920
  CognitoUserPoolKmsKey,
2921
+ ControlEventBus,
2178
2922
  DATA_STORE_CHANGE_DETAIL_MAX_UTF8_BYTES,
2179
2923
  DATA_STORE_CHANGE_DETAIL_TYPE,
2180
2924
  DATA_STORE_CHANGE_EVENT_SOURCE,
2925
+ DEMO_PERIOD,
2926
+ DEMO_TENANT_SPECS,
2927
+ DEMO_URN_SYSTEM,
2928
+ DEV_USERS,
2181
2929
  DataEventBus,
2182
2930
  DataStoreHistoricalArchive,
2183
2931
  DataStorePostgresReplica,
2184
2932
  DiscoverableStringParameter,
2185
2933
  DynamoDbDataStore,
2934
+ OPENHI_REPO_TAG_KEY_ENV_VAR,
2935
+ OPENHI_RESOURCE_URN_SYSTEM,
2936
+ OPENHI_TAG_KEY_PREFIX_ENV_VAR,
2937
+ OPENHI_TAG_SUFFIX_BRANCH_NAME,
2938
+ OPENHI_TAG_SUFFIX_REPO_NAME,
2939
+ OPENHI_TAG_SUFFIX_SERVICE_TYPE,
2940
+ OPENHI_TAG_SUFFIX_STAGE_TYPE,
2186
2941
  OpenHiApp,
2187
2942
  OpenHiAuthService,
2188
2943
  OpenHiDataService,
@@ -2193,21 +2948,59 @@ export {
2193
2948
  OpenHiService,
2194
2949
  OpenHiStage,
2195
2950
  OpsEventBus,
2951
+ PLACEHOLDER_TENANT_ID,
2952
+ PLACEHOLDER_WORKSPACE_ID,
2953
+ PLATFORM_DEPLOY_BRIDGE_ACTOR_SYSTEM,
2954
+ PLATFORM_SCOPE_TENANT_ID,
2196
2955
  POSTGRES_REPLICA_CLUSTER_ARN_SSM_NAME,
2197
2956
  POSTGRES_REPLICA_DATABASE_NAME_SSM_NAME,
2198
2957
  POSTGRES_REPLICA_SECRET_ARN_SSM_NAME,
2958
+ PROVISION_DEFAULT_WORKSPACE_DETAIL_TYPE,
2959
+ PlatformDeployBridge,
2960
+ PlatformDeployBridgeLambda,
2961
+ export_PlatformDeploymentCompletedV1 as PlatformDeploymentCompletedV1,
2199
2962
  PostAuthenticationLambda,
2200
2963
  PostConfirmationLambda,
2201
2964
  PreTokenGenerationLambda,
2965
+ ProvisionDefaultWorkspaceLambda,
2202
2966
  REST_API_BASE_URL_SSM_NAME,
2203
2967
  RootGraphqlApi,
2204
2968
  RootHostedZone,
2205
2969
  RootHttpApi,
2206
2970
  RootWildcardCertificate,
2971
+ SEED_DEMO_DATA_CONSUMER_NAME,
2972
+ SEED_SYSTEM_DATA_ACTOR_SYSTEM,
2973
+ SEED_SYSTEM_DATA_CONSUMER_NAME,
2974
+ SEED_SYSTEM_DATA_CONTROL_BUS_ENV_VAR,
2207
2975
  STATIC_HOSTING_SERVICE_TYPE,
2976
+ SeedDemoDataLambda,
2977
+ SeedDemoDataWorkflow,
2978
+ SeedSystemDataLambda,
2979
+ SeedSystemDataWorkflow,
2208
2980
  StaticHosting,
2981
+ USER_ONBOARDING_EVENT_SOURCE,
2982
+ UserOnboardingWorkflow,
2983
+ WorkflowDedupConsumerNameInvalidError,
2984
+ WorkflowDedupTable,
2985
+ WorkflowDedupTableDuplicateError,
2209
2986
  buildFhirCurrentResourceChangeDetail,
2987
+ buildProvisionDefaultWorkspaceRequestedDetail,
2988
+ demoBasePartitionKeys,
2989
+ demoDevUserPartitionKeys,
2990
+ demoMembershipId,
2991
+ demoMembershipPartitionKey,
2992
+ demoRoleAssignmentId,
2993
+ demoRoleAssignmentPartitionKey,
2994
+ demoRolesForUserInTenant,
2995
+ demoScenarioIdentifier,
2996
+ demoTenantPartitionKey,
2997
+ demoUserPartitionKey,
2998
+ demoWorkspacePartitionKey,
2210
2999
  getDynamoDbDataStoreTableName,
2211
- getPostgresReplicaSchemaName
3000
+ getPostgresReplicaSchemaName,
3001
+ getWorkflowDedupTableName,
3002
+ openHiTagKey,
3003
+ openhiResourceIdentifier,
3004
+ rolePartitionKey
2212
3005
  };
2213
3006
  //# sourceMappingURL=index.mjs.map