@openhi/constructs 0.0.105 → 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.
- package/lib/chunk-AGF3RAAZ.mjs +20 -0
- package/lib/chunk-AGF3RAAZ.mjs.map +1 -0
- package/lib/{chunk-BXEG7IOZ.mjs → chunk-AO3E22CS.mjs} +2 -2
- package/lib/{chunk-WNUH2WDZ.mjs → chunk-CHPEQRXU.mjs} +2 -2
- package/lib/chunk-JUNL76HF.mjs +428 -0
- package/lib/chunk-JUNL76HF.mjs.map +1 -0
- package/lib/chunk-L6UAP4KP.mjs +27 -0
- package/lib/chunk-L6UAP4KP.mjs.map +1 -0
- package/lib/{chunk-3QS3WKRC.mjs → chunk-LZOMFHX3.mjs} +9 -2
- package/lib/chunk-QMIOLLAS.mjs +531 -0
- package/lib/chunk-QMIOLLAS.mjs.map +1 -0
- package/lib/chunk-SYBADQXI.mjs +607 -0
- package/lib/chunk-SYBADQXI.mjs.map +1 -0
- package/lib/chunk-VXX4I3EF.mjs +19 -0
- package/lib/chunk-VXX4I3EF.mjs.map +1 -0
- package/lib/{chunk-36YCDLLA.mjs → chunk-VYDIGFIX.mjs} +75 -481
- package/lib/chunk-VYDIGFIX.mjs.map +1 -0
- package/lib/chunk-YU2HRNUP.mjs +33 -0
- package/lib/chunk-YU2HRNUP.mjs.map +1 -0
- package/lib/chunk-YZZDUJHI.mjs +37 -0
- package/lib/chunk-YZZDUJHI.mjs.map +1 -0
- package/lib/cors-options-lambda.handler.mjs +1 -1
- package/lib/data-store-postgres-replication.handler.mjs +1 -1
- package/lib/events-BfrkMoBD.d.mts +44 -0
- package/lib/events-BfrkMoBD.d.ts +44 -0
- package/lib/events-DGep6C7w.d.mts +207 -0
- package/lib/events-DGep6C7w.d.ts +207 -0
- package/lib/firehose-archive-transform.handler.mjs +1 -1
- package/lib/index.d.mts +417 -9
- package/lib/index.d.ts +663 -10
- package/lib/index.js +2400 -111
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +781 -104
- package/lib/index.mjs.map +1 -1
- package/lib/openhi-context-CaBH8SFo.d.mts +39 -0
- package/lib/openhi-context-CaBH8SFo.d.ts +39 -0
- package/lib/platform-deploy-bridge.handler.d.mts +14 -0
- package/lib/platform-deploy-bridge.handler.d.ts +14 -0
- package/lib/platform-deploy-bridge.handler.js +762 -0
- package/lib/platform-deploy-bridge.handler.js.map +1 -0
- package/lib/platform-deploy-bridge.handler.mjs +134 -0
- package/lib/platform-deploy-bridge.handler.mjs.map +1 -0
- package/lib/post-authentication.handler.mjs +1 -1
- package/lib/post-confirmation.handler.mjs +1 -1
- package/lib/pre-token-generation.handler.js +76 -31
- package/lib/pre-token-generation.handler.js.map +1 -1
- package/lib/pre-token-generation.handler.mjs +5 -3
- package/lib/pre-token-generation.handler.mjs.map +1 -1
- package/lib/provision-default-workspace.handler.js +86 -41
- package/lib/provision-default-workspace.handler.js.map +1 -1
- package/lib/provision-default-workspace.handler.mjs +6 -4
- package/lib/provision-default-workspace.handler.mjs.map +1 -1
- package/lib/rest-api-lambda.handler.js +114 -59
- package/lib/rest-api-lambda.handler.js.map +1 -1
- package/lib/rest-api-lambda.handler.mjs +40 -61
- package/lib/rest-api-lambda.handler.mjs.map +1 -1
- package/lib/seed-demo-data.handler.d.mts +107 -0
- package/lib/seed-demo-data.handler.d.ts +107 -0
- package/lib/seed-demo-data.handler.js +2037 -0
- package/lib/seed-demo-data.handler.js.map +1 -0
- package/lib/seed-demo-data.handler.mjs +23 -0
- package/lib/seed-demo-data.handler.mjs.map +1 -0
- package/lib/seed-system-data.handler.d.mts +64 -0
- package/lib/seed-system-data.handler.d.ts +64 -0
- package/lib/seed-system-data.handler.js +1631 -0
- package/lib/seed-system-data.handler.js.map +1 -0
- package/lib/seed-system-data.handler.mjs +135 -0
- package/lib/seed-system-data.handler.mjs.map +1 -0
- package/package.json +4 -2
- package/lib/chunk-36YCDLLA.mjs.map +0 -1
- /package/lib/{chunk-BXEG7IOZ.mjs.map → chunk-AO3E22CS.mjs.map} +0 -0
- /package/lib/{chunk-WNUH2WDZ.mjs.map → chunk-CHPEQRXU.mjs.map} +0 -0
- /package/lib/{chunk-3QS3WKRC.mjs.map → chunk-LZOMFHX3.mjs.map} +0 -0
|
@@ -0,0 +1,1631 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
};
|
|
11
|
+
var __export = (target, all) => {
|
|
12
|
+
for (var name in all)
|
|
13
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
|
+
};
|
|
15
|
+
var __copyProps = (to, from, except, desc) => {
|
|
16
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
17
|
+
for (let key of __getOwnPropNames(from))
|
|
18
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
19
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
24
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
25
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
26
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
27
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
28
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
29
|
+
mod
|
|
30
|
+
));
|
|
31
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
|
+
|
|
33
|
+
// ../workflows/lib/envelope-version.js
|
|
34
|
+
var require_envelope_version = __commonJS({
|
|
35
|
+
"../workflows/lib/envelope-version.js"(exports2) {
|
|
36
|
+
"use strict";
|
|
37
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
38
|
+
exports2.ENVELOPE_VERSION = void 0;
|
|
39
|
+
exports2.isSupportedEnvelopeVersion = isSupportedEnvelopeVersion;
|
|
40
|
+
exports2.ENVELOPE_VERSION = "1.0";
|
|
41
|
+
var ENVELOPE_VERSION_PATTERN = /^\d+\.\d+$/;
|
|
42
|
+
var MIN_SUPPORTED_MAJOR = 1;
|
|
43
|
+
var MAX_SUPPORTED_MAJOR = 1;
|
|
44
|
+
function isSupportedEnvelopeVersion(version) {
|
|
45
|
+
if (!ENVELOPE_VERSION_PATTERN.test(version)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const major = Number.parseInt(version.split(".")[0], 10);
|
|
49
|
+
return major >= MIN_SUPPORTED_MAJOR && major <= MAX_SUPPORTED_MAJOR;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// ../workflows/lib/envelope.js
|
|
55
|
+
var require_envelope = __commonJS({
|
|
56
|
+
"../workflows/lib/envelope.js"(exports2) {
|
|
57
|
+
"use strict";
|
|
58
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
59
|
+
exports2.MissingActorContextError = void 0;
|
|
60
|
+
exports2.isWorkflowUserActor = isWorkflowUserActor;
|
|
61
|
+
exports2.isWorkflowSystemActor = isWorkflowSystemActor;
|
|
62
|
+
exports2.workflowUserActorFromClaims = workflowUserActorFromClaims;
|
|
63
|
+
function isWorkflowUserActor(actor) {
|
|
64
|
+
return actor.ohi_uid !== void 0;
|
|
65
|
+
}
|
|
66
|
+
function isWorkflowSystemActor(actor) {
|
|
67
|
+
return actor.system !== void 0;
|
|
68
|
+
}
|
|
69
|
+
function workflowUserActorFromClaims(claims) {
|
|
70
|
+
if (claims.ohi_tid === void 0 || claims.ohi_wid === void 0) {
|
|
71
|
+
throw new MissingActorContextError("workflowUserActorFromClaims: ohi_tid and ohi_wid are required on the workflow user-actor; the caller's JWT is missing one or both. Use a system-actor for pre-provisioning bootstrap workflows.");
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
ohi_tid: claims.ohi_tid,
|
|
75
|
+
ohi_wid: claims.ohi_wid,
|
|
76
|
+
ohi_uid: claims.ohi_uid,
|
|
77
|
+
ohi_uname: claims.ohi_uname
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
var MissingActorContextError = class extends Error {
|
|
81
|
+
/** @param message - human-readable description of the missing claim. */
|
|
82
|
+
constructor(message) {
|
|
83
|
+
super(message);
|
|
84
|
+
this.name = "MissingActorContextError";
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
exports2.MissingActorContextError = MissingActorContextError;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// ../workflows/lib/sources.js
|
|
92
|
+
var require_sources = __commonJS({
|
|
93
|
+
"../workflows/lib/sources.js"(exports2) {
|
|
94
|
+
"use strict";
|
|
95
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
96
|
+
exports2.DEFAULT_BUS_NAME_BY_SOURCE = exports2.OPENHI_OPS_SOURCE = exports2.OPENHI_DATA_SOURCE = exports2.OPENHI_CONTROL_SOURCE = void 0;
|
|
97
|
+
exports2.OPENHI_CONTROL_SOURCE = "openhi.control";
|
|
98
|
+
exports2.OPENHI_DATA_SOURCE = "openhi.data";
|
|
99
|
+
exports2.OPENHI_OPS_SOURCE = "openhi.ops";
|
|
100
|
+
exports2.DEFAULT_BUS_NAME_BY_SOURCE = {
|
|
101
|
+
[exports2.OPENHI_CONTROL_SOURCE]: "openhi-control-event-bus",
|
|
102
|
+
[exports2.OPENHI_DATA_SOURCE]: "openhi-data-event-bus",
|
|
103
|
+
[exports2.OPENHI_OPS_SOURCE]: "openhi-ops-event-bus"
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// ../workflows/lib/detail-types/registry.js
|
|
109
|
+
var require_registry = __commonJS({
|
|
110
|
+
"../workflows/lib/detail-types/registry.js"(exports2) {
|
|
111
|
+
"use strict";
|
|
112
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
113
|
+
exports2.InvalidDetailTypeRegistrationError = void 0;
|
|
114
|
+
exports2.defineDetailType = defineDetailType;
|
|
115
|
+
exports2.isWellFormedDetailType = isWellFormedDetailType;
|
|
116
|
+
function defineDetailType(entry) {
|
|
117
|
+
if (!isWellFormedDetailType(entry.detailType)) {
|
|
118
|
+
throw new InvalidDetailTypeRegistrationError(`Detail-type "${entry.detailType}" does not match the platform-wide format <area>.<event>.v<integer>. See TR-016 \xA7Open Items #2.`);
|
|
119
|
+
}
|
|
120
|
+
return entry;
|
|
121
|
+
}
|
|
122
|
+
var DETAIL_TYPE_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*\.[a-z0-9]+(?:-[a-z0-9]+)*\.v\d+$/;
|
|
123
|
+
function isWellFormedDetailType(detailType) {
|
|
124
|
+
return DETAIL_TYPE_PATTERN.test(detailType);
|
|
125
|
+
}
|
|
126
|
+
var InvalidDetailTypeRegistrationError = class extends Error {
|
|
127
|
+
/** @param message - human-readable description of the violation. */
|
|
128
|
+
constructor(message) {
|
|
129
|
+
super(message);
|
|
130
|
+
this.name = "InvalidDetailTypeRegistrationError";
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
exports2.InvalidDetailTypeRegistrationError = InvalidDetailTypeRegistrationError;
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// ../workflows/lib/detail-types/platform.js
|
|
138
|
+
var require_platform = __commonJS({
|
|
139
|
+
"../workflows/lib/detail-types/platform.js"(exports2) {
|
|
140
|
+
"use strict";
|
|
141
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
142
|
+
exports2.PlatformSystemDataSeededV1 = exports2.PlatformDeploymentCompletedV1 = void 0;
|
|
143
|
+
var sources_1 = require_sources();
|
|
144
|
+
var registry_1 = require_registry();
|
|
145
|
+
exports2.PlatformDeploymentCompletedV1 = (0, registry_1.defineDetailType)({
|
|
146
|
+
detailType: "platform.deployment-completed.v1",
|
|
147
|
+
source: sources_1.OPENHI_CONTROL_SOURCE,
|
|
148
|
+
dedupRequired: true
|
|
149
|
+
});
|
|
150
|
+
exports2.PlatformSystemDataSeededV1 = (0, registry_1.defineDetailType)({
|
|
151
|
+
detailType: "platform.system-data-seeded.v1",
|
|
152
|
+
source: sources_1.OPENHI_CONTROL_SOURCE,
|
|
153
|
+
dedupRequired: true
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// ../workflows/lib/detail-types/index.js
|
|
159
|
+
var require_detail_types = __commonJS({
|
|
160
|
+
"../workflows/lib/detail-types/index.js"(exports2) {
|
|
161
|
+
"use strict";
|
|
162
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
163
|
+
if (k2 === void 0) k2 = k;
|
|
164
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
165
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
166
|
+
desc = { enumerable: true, get: function() {
|
|
167
|
+
return m[k];
|
|
168
|
+
} };
|
|
169
|
+
}
|
|
170
|
+
Object.defineProperty(o, k2, desc);
|
|
171
|
+
}) : (function(o, m, k, k2) {
|
|
172
|
+
if (k2 === void 0) k2 = k;
|
|
173
|
+
o[k2] = m[k];
|
|
174
|
+
}));
|
|
175
|
+
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
176
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
|
|
177
|
+
};
|
|
178
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
179
|
+
__exportStar(require_platform(), exports2);
|
|
180
|
+
__exportStar(require_registry(), exports2);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// ../workflows/lib/publisher.js
|
|
185
|
+
var require_publisher = __commonJS({
|
|
186
|
+
"../workflows/lib/publisher.js"(exports2) {
|
|
187
|
+
"use strict";
|
|
188
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
189
|
+
exports2.WorkflowPublishError = void 0;
|
|
190
|
+
exports2.workflowsClient = workflowsClient;
|
|
191
|
+
exports2.publishWorkflowEvent = publishWorkflowEvent2;
|
|
192
|
+
var node_crypto_1 = require("crypto");
|
|
193
|
+
var client_eventbridge_1 = require("@aws-sdk/client-eventbridge");
|
|
194
|
+
var envelope_version_1 = require_envelope_version();
|
|
195
|
+
var sources_1 = require_sources();
|
|
196
|
+
function workflowsClient(bridge, options = {}) {
|
|
197
|
+
return {
|
|
198
|
+
publish: (entry, payload, ctx) => publishWorkflowEvent2(bridge, entry, payload, ctx, options)
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
async function publishWorkflowEvent2(bridge, entry, payload, ctx, options = {}) {
|
|
202
|
+
const eventIdGenerator = options.eventIdGenerator ?? (() => (0, node_crypto_1.randomUUID)());
|
|
203
|
+
const correlationIdGenerator = options.correlationIdGenerator ?? (() => (0, node_crypto_1.randomUUID)());
|
|
204
|
+
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
205
|
+
const envelope = {
|
|
206
|
+
eventId: eventIdGenerator(),
|
|
207
|
+
attempt: 1,
|
|
208
|
+
correlationId: ctx.correlationId ?? correlationIdGenerator(),
|
|
209
|
+
causationId: ctx.causationId ?? null,
|
|
210
|
+
actor: ctx.actor,
|
|
211
|
+
occurredAt: now().toISOString(),
|
|
212
|
+
envelopeVersion: envelope_version_1.ENVELOPE_VERSION,
|
|
213
|
+
payload
|
|
214
|
+
};
|
|
215
|
+
const busName = options.busNameByPlane?.[entry.source] ?? sources_1.DEFAULT_BUS_NAME_BY_SOURCE[entry.source];
|
|
216
|
+
const result = await bridge.send(new client_eventbridge_1.PutEventsCommand({
|
|
217
|
+
Entries: [
|
|
218
|
+
{
|
|
219
|
+
EventBusName: busName,
|
|
220
|
+
Source: entry.source,
|
|
221
|
+
DetailType: entry.detailType,
|
|
222
|
+
Detail: JSON.stringify(envelope)
|
|
223
|
+
}
|
|
224
|
+
]
|
|
225
|
+
}));
|
|
226
|
+
if ((result.FailedEntryCount ?? 0) > 0) {
|
|
227
|
+
const first = result.Entries?.[0];
|
|
228
|
+
throw new WorkflowPublishError(`EventBridge rejected ${entry.detailType} publish on bus ${busName}: ${first?.ErrorCode ?? "unknown"} \u2014 ${first?.ErrorMessage ?? "no error message"}`);
|
|
229
|
+
}
|
|
230
|
+
return { eventId: envelope.eventId };
|
|
231
|
+
}
|
|
232
|
+
var WorkflowPublishError = class extends Error {
|
|
233
|
+
/** @param message - human-readable description of the failed publish. */
|
|
234
|
+
constructor(message) {
|
|
235
|
+
super(message);
|
|
236
|
+
this.name = "WorkflowPublishError";
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
exports2.WorkflowPublishError = WorkflowPublishError;
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// ../workflows/lib/consumer.js
|
|
244
|
+
var require_consumer = __commonJS({
|
|
245
|
+
"../workflows/lib/consumer.js"(exports2) {
|
|
246
|
+
"use strict";
|
|
247
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
248
|
+
exports2.UnsupportedEnvelopeVersionError = exports2.InvalidWorkflowEventError = void 0;
|
|
249
|
+
exports2.parseWorkflowEvent = parseWorkflowEvent2;
|
|
250
|
+
var envelope_version_1 = require_envelope_version();
|
|
251
|
+
function parseWorkflowEvent2(event, expected) {
|
|
252
|
+
if (event.source !== expected.source) {
|
|
253
|
+
throw new InvalidWorkflowEventError(`EventBridge source "${event.source}" does not match expected detail-type's source "${expected.source}".`);
|
|
254
|
+
}
|
|
255
|
+
if (event["detail-type"] !== expected.detailType) {
|
|
256
|
+
throw new InvalidWorkflowEventError(`EventBridge detail-type "${event["detail-type"]}" does not match expected "${expected.detailType}".`);
|
|
257
|
+
}
|
|
258
|
+
const candidate = asEnvelopeCandidate(event.detail);
|
|
259
|
+
if (!(0, envelope_version_1.isSupportedEnvelopeVersion)(candidate.envelopeVersion)) {
|
|
260
|
+
throw new UnsupportedEnvelopeVersionError(`Envelope version "${candidate.envelopeVersion}" is outside the SDK's supported range.`);
|
|
261
|
+
}
|
|
262
|
+
const envelope = {
|
|
263
|
+
eventId: candidate.eventId,
|
|
264
|
+
attempt: candidate.attempt,
|
|
265
|
+
correlationId: candidate.correlationId,
|
|
266
|
+
causationId: candidate.causationId,
|
|
267
|
+
actor: candidate.actor,
|
|
268
|
+
occurredAt: candidate.occurredAt,
|
|
269
|
+
envelopeVersion: candidate.envelopeVersion,
|
|
270
|
+
payload: candidate.payload
|
|
271
|
+
};
|
|
272
|
+
return {
|
|
273
|
+
envelope,
|
|
274
|
+
dedupKey: { eventId: envelope.eventId, attempt: envelope.attempt }
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
function asEnvelopeCandidate(detail) {
|
|
278
|
+
if (detail === null || typeof detail !== "object") {
|
|
279
|
+
throw new InvalidWorkflowEventError("EventBridge detail is not a non-null object.");
|
|
280
|
+
}
|
|
281
|
+
const obj = detail;
|
|
282
|
+
assertString(obj, "eventId");
|
|
283
|
+
assertPositiveInteger(obj, "attempt");
|
|
284
|
+
assertString(obj, "correlationId");
|
|
285
|
+
assertCausationId(obj);
|
|
286
|
+
assertActor(obj);
|
|
287
|
+
assertString(obj, "occurredAt");
|
|
288
|
+
assertString(obj, "envelopeVersion");
|
|
289
|
+
if (!("payload" in obj)) {
|
|
290
|
+
throw new InvalidWorkflowEventError("Envelope is missing required field: payload.");
|
|
291
|
+
}
|
|
292
|
+
return obj;
|
|
293
|
+
}
|
|
294
|
+
function assertString(obj, field) {
|
|
295
|
+
const value = obj[field];
|
|
296
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
297
|
+
throw new InvalidWorkflowEventError(`Envelope field "${field}" must be a non-empty string.`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function assertPositiveInteger(obj, field) {
|
|
301
|
+
const value = obj[field];
|
|
302
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 1) {
|
|
303
|
+
throw new InvalidWorkflowEventError(`Envelope field "${field}" must be a 1-indexed integer.`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function assertCausationId(obj) {
|
|
307
|
+
if (!("causationId" in obj)) {
|
|
308
|
+
throw new InvalidWorkflowEventError("Envelope is missing required field: causationId.");
|
|
309
|
+
}
|
|
310
|
+
const value = obj.causationId;
|
|
311
|
+
if (value !== null && (typeof value !== "string" || value.length === 0)) {
|
|
312
|
+
throw new InvalidWorkflowEventError('Envelope field "causationId" must be a non-empty string or null.');
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function assertActor(obj) {
|
|
316
|
+
const actor = obj.actor;
|
|
317
|
+
if (actor === null || typeof actor !== "object") {
|
|
318
|
+
throw new InvalidWorkflowEventError('Envelope field "actor" must be an object.');
|
|
319
|
+
}
|
|
320
|
+
const actorObj = actor;
|
|
321
|
+
const isUserActor = typeof actorObj.ohi_uid === "string" && typeof actorObj.ohi_uname === "string" && typeof actorObj.ohi_tid === "string" && typeof actorObj.ohi_wid === "string";
|
|
322
|
+
const isSystemActor = typeof actorObj.system === "string";
|
|
323
|
+
if (!isUserActor && !isSystemActor) {
|
|
324
|
+
throw new InvalidWorkflowEventError('Envelope field "actor" must be either a user-actor (ohi_tid, ohi_wid, ohi_uid, ohi_uname) or a system-actor ({ system: string }).');
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
var InvalidWorkflowEventError = class extends Error {
|
|
328
|
+
/** @param message - human-readable description of the validation failure. */
|
|
329
|
+
constructor(message) {
|
|
330
|
+
super(message);
|
|
331
|
+
this.name = "InvalidWorkflowEventError";
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
exports2.InvalidWorkflowEventError = InvalidWorkflowEventError;
|
|
335
|
+
var UnsupportedEnvelopeVersionError = class extends Error {
|
|
336
|
+
/** @param message - human-readable description of the unsupported version. */
|
|
337
|
+
constructor(message) {
|
|
338
|
+
super(message);
|
|
339
|
+
this.name = "UnsupportedEnvelopeVersionError";
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
exports2.UnsupportedEnvelopeVersionError = UnsupportedEnvelopeVersionError;
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
// ../workflows/lib/dedup/env.js
|
|
347
|
+
var require_env = __commonJS({
|
|
348
|
+
"../workflows/lib/dedup/env.js"(exports2) {
|
|
349
|
+
"use strict";
|
|
350
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
351
|
+
exports2.WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH = exports2.WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS = exports2.WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR = void 0;
|
|
352
|
+
exports2.WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR = "OPENHI_WORKFLOW_DEDUP_TABLE_NAME";
|
|
353
|
+
exports2.WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS = 14 * 24 * 60 * 60;
|
|
354
|
+
exports2.WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH = 64;
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// ../workflows/lib/dedup/workflow-dedup-client.js
|
|
359
|
+
var require_workflow_dedup_client = __commonJS({
|
|
360
|
+
"../workflows/lib/dedup/workflow-dedup-client.js"(exports2) {
|
|
361
|
+
"use strict";
|
|
362
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
363
|
+
exports2.WorkflowDedupInvalidInputError = exports2.WorkflowDedupTableNameMissingError = void 0;
|
|
364
|
+
exports2.workflowDedupClient = workflowDedupClient2;
|
|
365
|
+
exports2.recordIfAbsent = recordIfAbsent;
|
|
366
|
+
exports2.markFailed = markFailed;
|
|
367
|
+
exports2.encodeSortKey = encodeSortKey;
|
|
368
|
+
var client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
|
|
369
|
+
var env_1 = require_env();
|
|
370
|
+
function workflowDedupClient2(dynamodb, options = {}) {
|
|
371
|
+
return {
|
|
372
|
+
recordIfAbsent: (input) => recordIfAbsent(dynamodb, input, options),
|
|
373
|
+
markFailed: (input) => markFailed(dynamodb, input, options)
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
async function recordIfAbsent(dynamodb, input, options = {}) {
|
|
377
|
+
assertConsumerName(input.consumerName);
|
|
378
|
+
assertPositiveInteger(input.attempt, "attempt");
|
|
379
|
+
const ttlSeconds = input.ttlSeconds ?? options.defaultTtlSeconds ?? env_1.WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS;
|
|
380
|
+
if (!Number.isInteger(ttlSeconds) || ttlSeconds <= 0) {
|
|
381
|
+
throw new WorkflowDedupInvalidInputError(`ttlSeconds must be a positive integer; got ${ttlSeconds}.`);
|
|
382
|
+
}
|
|
383
|
+
const tableName = resolveTableName(options.tableName);
|
|
384
|
+
const now = (options.now ?? defaultNow)();
|
|
385
|
+
const sk = encodeSortKey(input.eventId, input.attempt);
|
|
386
|
+
const expiresAt = Math.floor(now.getTime() / 1e3) + ttlSeconds;
|
|
387
|
+
try {
|
|
388
|
+
await dynamodb.send(new client_dynamodb_1.PutItemCommand({
|
|
389
|
+
TableName: tableName,
|
|
390
|
+
Item: {
|
|
391
|
+
consumerName: { S: input.consumerName },
|
|
392
|
+
sk: { S: sk },
|
|
393
|
+
eventId: { S: input.eventId },
|
|
394
|
+
attempt: { N: String(input.attempt) },
|
|
395
|
+
recordedAt: { S: now.toISOString() },
|
|
396
|
+
expiresAt: { N: String(expiresAt) }
|
|
397
|
+
},
|
|
398
|
+
ConditionExpression: "attribute_not_exists(consumerName) AND attribute_not_exists(sk)"
|
|
399
|
+
}));
|
|
400
|
+
return { recorded: true };
|
|
401
|
+
} catch (err) {
|
|
402
|
+
if (err instanceof client_dynamodb_1.ConditionalCheckFailedException) {
|
|
403
|
+
return { recorded: false, alreadyProcessed: true };
|
|
404
|
+
}
|
|
405
|
+
throw err;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
async function markFailed(dynamodb, input, options = {}) {
|
|
409
|
+
assertConsumerName(input.consumerName);
|
|
410
|
+
assertPositiveInteger(input.attempt, "attempt");
|
|
411
|
+
if (input.reason.length === 0) {
|
|
412
|
+
throw new WorkflowDedupInvalidInputError("reason must be non-empty.");
|
|
413
|
+
}
|
|
414
|
+
const tableName = resolveTableName(options.tableName);
|
|
415
|
+
const now = (options.now ?? defaultNow)();
|
|
416
|
+
const sk = encodeSortKey(input.eventId, input.attempt);
|
|
417
|
+
await dynamodb.send(new client_dynamodb_1.UpdateItemCommand({
|
|
418
|
+
TableName: tableName,
|
|
419
|
+
Key: {
|
|
420
|
+
consumerName: { S: input.consumerName },
|
|
421
|
+
sk: { S: sk }
|
|
422
|
+
},
|
|
423
|
+
UpdateExpression: "SET #failed = :failed, #failureReason = :reason, #failedAt = :failedAt",
|
|
424
|
+
ExpressionAttributeNames: {
|
|
425
|
+
"#failed": "failed",
|
|
426
|
+
"#failureReason": "failureReason",
|
|
427
|
+
"#failedAt": "failedAt"
|
|
428
|
+
},
|
|
429
|
+
ExpressionAttributeValues: {
|
|
430
|
+
":failed": { BOOL: true },
|
|
431
|
+
":reason": { S: input.reason },
|
|
432
|
+
":failedAt": { S: now.toISOString() }
|
|
433
|
+
}
|
|
434
|
+
}));
|
|
435
|
+
}
|
|
436
|
+
function encodeSortKey(eventId, attempt) {
|
|
437
|
+
if (eventId.length === 0) {
|
|
438
|
+
throw new WorkflowDedupInvalidInputError("eventId must be non-empty.");
|
|
439
|
+
}
|
|
440
|
+
return `${eventId}#${attempt}`;
|
|
441
|
+
}
|
|
442
|
+
function resolveTableName(explicit) {
|
|
443
|
+
const name = explicit ?? process.env[env_1.WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR];
|
|
444
|
+
if (!name) {
|
|
445
|
+
throw new WorkflowDedupTableNameMissingError(`Workflow dedup table name not set. Pass options.tableName or set ${env_1.WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR}.`);
|
|
446
|
+
}
|
|
447
|
+
return name;
|
|
448
|
+
}
|
|
449
|
+
function assertConsumerName(consumerName) {
|
|
450
|
+
if (consumerName.length === 0) {
|
|
451
|
+
throw new WorkflowDedupInvalidInputError("consumerName must be non-empty.");
|
|
452
|
+
}
|
|
453
|
+
if (consumerName.length > env_1.WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH) {
|
|
454
|
+
throw new WorkflowDedupInvalidInputError(`consumerName must be \u2264${env_1.WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH} chars; got ${consumerName.length}.`);
|
|
455
|
+
}
|
|
456
|
+
if (/\s/.test(consumerName)) {
|
|
457
|
+
throw new WorkflowDedupInvalidInputError("consumerName must not contain whitespace.");
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
function assertPositiveInteger(value, field) {
|
|
461
|
+
if (!Number.isInteger(value) || value < 1) {
|
|
462
|
+
throw new WorkflowDedupInvalidInputError(`${field} must be a 1-indexed integer; got ${value}.`);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
function defaultNow() {
|
|
466
|
+
return /* @__PURE__ */ new Date();
|
|
467
|
+
}
|
|
468
|
+
var WorkflowDedupTableNameMissingError = class extends Error {
|
|
469
|
+
/** @param message - human-readable description. */
|
|
470
|
+
constructor(message) {
|
|
471
|
+
super(message);
|
|
472
|
+
this.name = "WorkflowDedupTableNameMissingError";
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
exports2.WorkflowDedupTableNameMissingError = WorkflowDedupTableNameMissingError;
|
|
476
|
+
var WorkflowDedupInvalidInputError = class extends Error {
|
|
477
|
+
/** @param message - human-readable description. */
|
|
478
|
+
constructor(message) {
|
|
479
|
+
super(message);
|
|
480
|
+
this.name = "WorkflowDedupInvalidInputError";
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
exports2.WorkflowDedupInvalidInputError = WorkflowDedupInvalidInputError;
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
// ../workflows/lib/dedup/index.js
|
|
488
|
+
var require_dedup = __commonJS({
|
|
489
|
+
"../workflows/lib/dedup/index.js"(exports2) {
|
|
490
|
+
"use strict";
|
|
491
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
492
|
+
exports2.workflowDedupClient = exports2.recordIfAbsent = exports2.markFailed = exports2.encodeSortKey = exports2.WorkflowDedupTableNameMissingError = exports2.WorkflowDedupInvalidInputError = exports2.WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR = exports2.WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH = exports2.WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS = void 0;
|
|
493
|
+
var env_1 = require_env();
|
|
494
|
+
Object.defineProperty(exports2, "WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS", { enumerable: true, get: function() {
|
|
495
|
+
return env_1.WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS;
|
|
496
|
+
} });
|
|
497
|
+
Object.defineProperty(exports2, "WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH", { enumerable: true, get: function() {
|
|
498
|
+
return env_1.WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH;
|
|
499
|
+
} });
|
|
500
|
+
Object.defineProperty(exports2, "WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR", { enumerable: true, get: function() {
|
|
501
|
+
return env_1.WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR;
|
|
502
|
+
} });
|
|
503
|
+
var workflow_dedup_client_1 = require_workflow_dedup_client();
|
|
504
|
+
Object.defineProperty(exports2, "WorkflowDedupInvalidInputError", { enumerable: true, get: function() {
|
|
505
|
+
return workflow_dedup_client_1.WorkflowDedupInvalidInputError;
|
|
506
|
+
} });
|
|
507
|
+
Object.defineProperty(exports2, "WorkflowDedupTableNameMissingError", { enumerable: true, get: function() {
|
|
508
|
+
return workflow_dedup_client_1.WorkflowDedupTableNameMissingError;
|
|
509
|
+
} });
|
|
510
|
+
Object.defineProperty(exports2, "encodeSortKey", { enumerable: true, get: function() {
|
|
511
|
+
return workflow_dedup_client_1.encodeSortKey;
|
|
512
|
+
} });
|
|
513
|
+
Object.defineProperty(exports2, "markFailed", { enumerable: true, get: function() {
|
|
514
|
+
return workflow_dedup_client_1.markFailed;
|
|
515
|
+
} });
|
|
516
|
+
Object.defineProperty(exports2, "recordIfAbsent", { enumerable: true, get: function() {
|
|
517
|
+
return workflow_dedup_client_1.recordIfAbsent;
|
|
518
|
+
} });
|
|
519
|
+
Object.defineProperty(exports2, "workflowDedupClient", { enumerable: true, get: function() {
|
|
520
|
+
return workflow_dedup_client_1.workflowDedupClient;
|
|
521
|
+
} });
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
// ../workflows/lib/index.js
|
|
526
|
+
var require_lib = __commonJS({
|
|
527
|
+
"../workflows/lib/index.js"(exports2) {
|
|
528
|
+
"use strict";
|
|
529
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
530
|
+
exports2.workflowDedupClient = exports2.recordIfAbsent = exports2.markFailed = exports2.encodeSortKey = exports2.WorkflowDedupTableNameMissingError = exports2.WorkflowDedupInvalidInputError = exports2.WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR = exports2.WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH = exports2.WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS = exports2.parseWorkflowEvent = exports2.UnsupportedEnvelopeVersionError = exports2.InvalidWorkflowEventError = exports2.workflowsClient = exports2.publishWorkflowEvent = exports2.WorkflowPublishError = exports2.isWellFormedDetailType = exports2.defineDetailType = exports2.PlatformSystemDataSeededV1 = exports2.PlatformDeploymentCompletedV1 = exports2.InvalidDetailTypeRegistrationError = exports2.OPENHI_OPS_SOURCE = exports2.OPENHI_DATA_SOURCE = exports2.OPENHI_CONTROL_SOURCE = exports2.DEFAULT_BUS_NAME_BY_SOURCE = exports2.workflowUserActorFromClaims = exports2.isWorkflowUserActor = exports2.isWorkflowSystemActor = exports2.MissingActorContextError = exports2.isSupportedEnvelopeVersion = exports2.ENVELOPE_VERSION = void 0;
|
|
531
|
+
var envelope_version_1 = require_envelope_version();
|
|
532
|
+
Object.defineProperty(exports2, "ENVELOPE_VERSION", { enumerable: true, get: function() {
|
|
533
|
+
return envelope_version_1.ENVELOPE_VERSION;
|
|
534
|
+
} });
|
|
535
|
+
Object.defineProperty(exports2, "isSupportedEnvelopeVersion", { enumerable: true, get: function() {
|
|
536
|
+
return envelope_version_1.isSupportedEnvelopeVersion;
|
|
537
|
+
} });
|
|
538
|
+
var envelope_1 = require_envelope();
|
|
539
|
+
Object.defineProperty(exports2, "MissingActorContextError", { enumerable: true, get: function() {
|
|
540
|
+
return envelope_1.MissingActorContextError;
|
|
541
|
+
} });
|
|
542
|
+
Object.defineProperty(exports2, "isWorkflowSystemActor", { enumerable: true, get: function() {
|
|
543
|
+
return envelope_1.isWorkflowSystemActor;
|
|
544
|
+
} });
|
|
545
|
+
Object.defineProperty(exports2, "isWorkflowUserActor", { enumerable: true, get: function() {
|
|
546
|
+
return envelope_1.isWorkflowUserActor;
|
|
547
|
+
} });
|
|
548
|
+
Object.defineProperty(exports2, "workflowUserActorFromClaims", { enumerable: true, get: function() {
|
|
549
|
+
return envelope_1.workflowUserActorFromClaims;
|
|
550
|
+
} });
|
|
551
|
+
var sources_1 = require_sources();
|
|
552
|
+
Object.defineProperty(exports2, "DEFAULT_BUS_NAME_BY_SOURCE", { enumerable: true, get: function() {
|
|
553
|
+
return sources_1.DEFAULT_BUS_NAME_BY_SOURCE;
|
|
554
|
+
} });
|
|
555
|
+
Object.defineProperty(exports2, "OPENHI_CONTROL_SOURCE", { enumerable: true, get: function() {
|
|
556
|
+
return sources_1.OPENHI_CONTROL_SOURCE;
|
|
557
|
+
} });
|
|
558
|
+
Object.defineProperty(exports2, "OPENHI_DATA_SOURCE", { enumerable: true, get: function() {
|
|
559
|
+
return sources_1.OPENHI_DATA_SOURCE;
|
|
560
|
+
} });
|
|
561
|
+
Object.defineProperty(exports2, "OPENHI_OPS_SOURCE", { enumerable: true, get: function() {
|
|
562
|
+
return sources_1.OPENHI_OPS_SOURCE;
|
|
563
|
+
} });
|
|
564
|
+
var detail_types_1 = require_detail_types();
|
|
565
|
+
Object.defineProperty(exports2, "InvalidDetailTypeRegistrationError", { enumerable: true, get: function() {
|
|
566
|
+
return detail_types_1.InvalidDetailTypeRegistrationError;
|
|
567
|
+
} });
|
|
568
|
+
Object.defineProperty(exports2, "PlatformDeploymentCompletedV1", { enumerable: true, get: function() {
|
|
569
|
+
return detail_types_1.PlatformDeploymentCompletedV1;
|
|
570
|
+
} });
|
|
571
|
+
Object.defineProperty(exports2, "PlatformSystemDataSeededV1", { enumerable: true, get: function() {
|
|
572
|
+
return detail_types_1.PlatformSystemDataSeededV1;
|
|
573
|
+
} });
|
|
574
|
+
Object.defineProperty(exports2, "defineDetailType", { enumerable: true, get: function() {
|
|
575
|
+
return detail_types_1.defineDetailType;
|
|
576
|
+
} });
|
|
577
|
+
Object.defineProperty(exports2, "isWellFormedDetailType", { enumerable: true, get: function() {
|
|
578
|
+
return detail_types_1.isWellFormedDetailType;
|
|
579
|
+
} });
|
|
580
|
+
var publisher_1 = require_publisher();
|
|
581
|
+
Object.defineProperty(exports2, "WorkflowPublishError", { enumerable: true, get: function() {
|
|
582
|
+
return publisher_1.WorkflowPublishError;
|
|
583
|
+
} });
|
|
584
|
+
Object.defineProperty(exports2, "publishWorkflowEvent", { enumerable: true, get: function() {
|
|
585
|
+
return publisher_1.publishWorkflowEvent;
|
|
586
|
+
} });
|
|
587
|
+
Object.defineProperty(exports2, "workflowsClient", { enumerable: true, get: function() {
|
|
588
|
+
return publisher_1.workflowsClient;
|
|
589
|
+
} });
|
|
590
|
+
var consumer_1 = require_consumer();
|
|
591
|
+
Object.defineProperty(exports2, "InvalidWorkflowEventError", { enumerable: true, get: function() {
|
|
592
|
+
return consumer_1.InvalidWorkflowEventError;
|
|
593
|
+
} });
|
|
594
|
+
Object.defineProperty(exports2, "UnsupportedEnvelopeVersionError", { enumerable: true, get: function() {
|
|
595
|
+
return consumer_1.UnsupportedEnvelopeVersionError;
|
|
596
|
+
} });
|
|
597
|
+
Object.defineProperty(exports2, "parseWorkflowEvent", { enumerable: true, get: function() {
|
|
598
|
+
return consumer_1.parseWorkflowEvent;
|
|
599
|
+
} });
|
|
600
|
+
var dedup_1 = require_dedup();
|
|
601
|
+
Object.defineProperty(exports2, "WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS", { enumerable: true, get: function() {
|
|
602
|
+
return dedup_1.WORKFLOW_DEDUP_DEFAULT_TTL_SECONDS;
|
|
603
|
+
} });
|
|
604
|
+
Object.defineProperty(exports2, "WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH", { enumerable: true, get: function() {
|
|
605
|
+
return dedup_1.WORKFLOW_DEDUP_MAX_CONSUMER_NAME_LENGTH;
|
|
606
|
+
} });
|
|
607
|
+
Object.defineProperty(exports2, "WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR", { enumerable: true, get: function() {
|
|
608
|
+
return dedup_1.WORKFLOW_DEDUP_TABLE_NAME_ENV_VAR;
|
|
609
|
+
} });
|
|
610
|
+
Object.defineProperty(exports2, "WorkflowDedupInvalidInputError", { enumerable: true, get: function() {
|
|
611
|
+
return dedup_1.WorkflowDedupInvalidInputError;
|
|
612
|
+
} });
|
|
613
|
+
Object.defineProperty(exports2, "WorkflowDedupTableNameMissingError", { enumerable: true, get: function() {
|
|
614
|
+
return dedup_1.WorkflowDedupTableNameMissingError;
|
|
615
|
+
} });
|
|
616
|
+
Object.defineProperty(exports2, "encodeSortKey", { enumerable: true, get: function() {
|
|
617
|
+
return dedup_1.encodeSortKey;
|
|
618
|
+
} });
|
|
619
|
+
Object.defineProperty(exports2, "markFailed", { enumerable: true, get: function() {
|
|
620
|
+
return dedup_1.markFailed;
|
|
621
|
+
} });
|
|
622
|
+
Object.defineProperty(exports2, "recordIfAbsent", { enumerable: true, get: function() {
|
|
623
|
+
return dedup_1.recordIfAbsent;
|
|
624
|
+
} });
|
|
625
|
+
Object.defineProperty(exports2, "workflowDedupClient", { enumerable: true, get: function() {
|
|
626
|
+
return dedup_1.workflowDedupClient;
|
|
627
|
+
} });
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
// src/workflows/control-plane/seed-system-data/seed-system-data.handler.ts
|
|
632
|
+
var seed_system_data_handler_exports = {};
|
|
633
|
+
__export(seed_system_data_handler_exports, {
|
|
634
|
+
handler: () => handler,
|
|
635
|
+
runSeedSystemData: () => runSeedSystemData
|
|
636
|
+
});
|
|
637
|
+
module.exports = __toCommonJS(seed_system_data_handler_exports);
|
|
638
|
+
var import_client_dynamodb2 = require("@aws-sdk/client-dynamodb");
|
|
639
|
+
var import_client_eventbridge = require("@aws-sdk/client-eventbridge");
|
|
640
|
+
var import_types3 = require("@openhi/types");
|
|
641
|
+
var import_workflows2 = __toESM(require_lib());
|
|
642
|
+
|
|
643
|
+
// src/workflows/control-plane/seed-system-data/events.ts
|
|
644
|
+
var import_workflows = __toESM(require_lib());
|
|
645
|
+
var SEED_SYSTEM_DATA_CONSUMER_NAME = "seed-system-data";
|
|
646
|
+
var SEED_SYSTEM_DATA_ACTOR_SYSTEM = "seed-system-data";
|
|
647
|
+
var SEED_SYSTEM_DATA_CONTROL_BUS_ENV_VAR = "CONTROL_EVENT_BUS_NAME";
|
|
648
|
+
|
|
649
|
+
// src/data/operations/control/role/role-create-operation.ts
|
|
650
|
+
var import_types2 = require("@openhi/types");
|
|
651
|
+
|
|
652
|
+
// src/data/dynamo/dynamo-control-service.ts
|
|
653
|
+
var import_electrodb8 = require("electrodb");
|
|
654
|
+
|
|
655
|
+
// src/data/dynamo/dynamo-client.ts
|
|
656
|
+
var import_client_dynamodb = require("@aws-sdk/client-dynamodb");
|
|
657
|
+
var defaultTableName = process.env.DYNAMO_TABLE_NAME ?? "jesttesttable";
|
|
658
|
+
var dynamoClient = new import_client_dynamodb.DynamoDBClient({
|
|
659
|
+
...process.env.MOCK_DYNAMODB_ENDPOINT && {
|
|
660
|
+
endpoint: process.env.MOCK_DYNAMODB_ENDPOINT,
|
|
661
|
+
sslEnabled: false,
|
|
662
|
+
region: "local"
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
// src/data/dynamo/entities/control/configuration-entity.ts
|
|
667
|
+
var import_electrodb = require("electrodb");
|
|
668
|
+
|
|
669
|
+
// src/data/dynamo/entities/control/control-entity-common.ts
|
|
670
|
+
var import_types = require("@openhi/types");
|
|
671
|
+
|
|
672
|
+
// src/data/dynamo/shard.ts
|
|
673
|
+
var SHARD_COUNT = 4;
|
|
674
|
+
function computeShard(id) {
|
|
675
|
+
let hash = 2166136261;
|
|
676
|
+
for (let i = 0; i < id.length; i++) {
|
|
677
|
+
hash ^= id.charCodeAt(i);
|
|
678
|
+
hash = Math.imul(hash, 16777619);
|
|
679
|
+
}
|
|
680
|
+
return (hash >>> 0) % SHARD_COUNT;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// src/data/dynamo/entities/control/control-entity-common.ts
|
|
684
|
+
var gsi1ShardAttribute = {
|
|
685
|
+
type: "string",
|
|
686
|
+
watch: ["id"],
|
|
687
|
+
set: (_val, item) => {
|
|
688
|
+
if (typeof item?.id !== "string" || item.id.length === 0) {
|
|
689
|
+
return void 0;
|
|
690
|
+
}
|
|
691
|
+
return String(computeShard(item.id));
|
|
692
|
+
}
|
|
693
|
+
};
|
|
694
|
+
var gsi1skAttribute = {
|
|
695
|
+
type: "string",
|
|
696
|
+
watch: ["resource", "lastUpdated", "id"],
|
|
697
|
+
set: (_val, item) => {
|
|
698
|
+
const id = typeof item?.id === "string" ? item.id : "";
|
|
699
|
+
const lastUpdated = typeof item?.lastUpdated === "string" ? item.lastUpdated : "";
|
|
700
|
+
const fallback = `${lastUpdated}#${id}`;
|
|
701
|
+
if (typeof item?.resource !== "string" || item.resource.length === 0) {
|
|
702
|
+
return fallback;
|
|
703
|
+
}
|
|
704
|
+
let parsed;
|
|
705
|
+
try {
|
|
706
|
+
parsed = JSON.parse(item.resource);
|
|
707
|
+
} catch {
|
|
708
|
+
return fallback;
|
|
709
|
+
}
|
|
710
|
+
if (!parsed || typeof parsed !== "object") return fallback;
|
|
711
|
+
const resourceType = parsed.resourceType;
|
|
712
|
+
if (typeof resourceType !== "string") return fallback;
|
|
713
|
+
const label = (0, import_types.extractLabel)(parsed);
|
|
714
|
+
return label !== void 0 ? `${label}#${id}` : fallback;
|
|
715
|
+
}
|
|
716
|
+
};
|
|
717
|
+
|
|
718
|
+
// src/data/dynamo/entities/control/configuration-entity.ts
|
|
719
|
+
var ConfigurationEntity = new import_electrodb.Entity({
|
|
720
|
+
model: {
|
|
721
|
+
entity: "configuration",
|
|
722
|
+
service: "control",
|
|
723
|
+
version: "01"
|
|
724
|
+
},
|
|
725
|
+
attributes: {
|
|
726
|
+
/** Sort key. "CURRENT" for current version; version history in S3. */
|
|
727
|
+
sk: {
|
|
728
|
+
type: "string",
|
|
729
|
+
required: true,
|
|
730
|
+
default: "CURRENT"
|
|
731
|
+
},
|
|
732
|
+
/** Tenant scope. Use "BASELINE" when the config is baseline default (no tenant). */
|
|
733
|
+
tenantId: {
|
|
734
|
+
type: "string",
|
|
735
|
+
required: true,
|
|
736
|
+
default: "BASELINE"
|
|
737
|
+
},
|
|
738
|
+
/** Workspace scope. Use "-" when absent. */
|
|
739
|
+
workspaceId: {
|
|
740
|
+
type: "string",
|
|
741
|
+
required: true,
|
|
742
|
+
default: "-"
|
|
743
|
+
},
|
|
744
|
+
/** User scope. Use "-" when absent. */
|
|
745
|
+
userId: {
|
|
746
|
+
type: "string",
|
|
747
|
+
required: true,
|
|
748
|
+
default: "-"
|
|
749
|
+
},
|
|
750
|
+
/** Role scope. Use "-" when absent. */
|
|
751
|
+
roleId: {
|
|
752
|
+
type: "string",
|
|
753
|
+
required: true,
|
|
754
|
+
default: "-"
|
|
755
|
+
},
|
|
756
|
+
/** Config type (category), e.g. endpoints, branding, display. */
|
|
757
|
+
key: {
|
|
758
|
+
type: "string",
|
|
759
|
+
required: true
|
|
760
|
+
},
|
|
761
|
+
/** FHIR Resource.id; logical id in URL and for the Configuration resource. */
|
|
762
|
+
id: {
|
|
763
|
+
type: "string",
|
|
764
|
+
required: true
|
|
765
|
+
},
|
|
766
|
+
/** Payload as JSON string. JSON.stringify(resource) on write; JSON.parse(item.resource) on read. */
|
|
767
|
+
resource: {
|
|
768
|
+
type: "string",
|
|
769
|
+
required: true
|
|
770
|
+
},
|
|
771
|
+
/**
|
|
772
|
+
* Summary projection (key display fields as JSON string: id, key, status).
|
|
773
|
+
* Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
|
|
774
|
+
*/
|
|
775
|
+
summary: {
|
|
776
|
+
type: "string",
|
|
777
|
+
required: true
|
|
778
|
+
},
|
|
779
|
+
/** Version id (e.g. ULID). Tracks current version; S3 history key. */
|
|
780
|
+
vid: {
|
|
781
|
+
type: "string",
|
|
782
|
+
required: true
|
|
783
|
+
},
|
|
784
|
+
lastUpdated: {
|
|
785
|
+
type: "string",
|
|
786
|
+
required: true
|
|
787
|
+
},
|
|
788
|
+
gsi1Shard: gsi1ShardAttribute,
|
|
789
|
+
deleted: {
|
|
790
|
+
type: "boolean",
|
|
791
|
+
required: false
|
|
792
|
+
},
|
|
793
|
+
bundleId: {
|
|
794
|
+
type: "string",
|
|
795
|
+
required: false
|
|
796
|
+
},
|
|
797
|
+
msgId: {
|
|
798
|
+
type: "string",
|
|
799
|
+
required: false
|
|
800
|
+
}
|
|
801
|
+
},
|
|
802
|
+
indexes: {
|
|
803
|
+
/** Base table: PK, SK (data store key names). PK is built from tenantId, workspaceId, userId, roleId; SK is built from key and sk. Do not supply PK or SK from outside. */
|
|
804
|
+
record: {
|
|
805
|
+
pk: {
|
|
806
|
+
field: "PK",
|
|
807
|
+
composite: ["tenantId", "workspaceId", "userId", "roleId"],
|
|
808
|
+
template: "CONFIG#TID#${tenantId}#WID#${workspaceId}#UID#${userId}#RID#${roleId}"
|
|
809
|
+
},
|
|
810
|
+
sk: {
|
|
811
|
+
field: "SK",
|
|
812
|
+
composite: ["key", "sk"],
|
|
813
|
+
template: "KEY#${key}#SK#${sk}"
|
|
814
|
+
}
|
|
815
|
+
},
|
|
816
|
+
/**
|
|
817
|
+
* GSI1 — Unified Sharded List per ADR-011: list all Configuration entries for a
|
|
818
|
+
* (tenant, workspace) across the four shards. Use for "list configs scoped to this tenant"
|
|
819
|
+
* (workspaceId = "-") or "list configs scoped to this workspace". Does not support
|
|
820
|
+
* hierarchical resolution in one query; use base table GetItem in fallback order
|
|
821
|
+
* (user → workspace → tenant → baseline) for that.
|
|
822
|
+
* SK is `<key>#<id>` — Configuration's `key` is a required entity attribute (the
|
|
823
|
+
* config category: endpoints, branding, display, …) and the natural sort/lookup
|
|
824
|
+
* dimension. `casing: "none"` preserves the literal key value.
|
|
825
|
+
*/
|
|
826
|
+
gsi1: {
|
|
827
|
+
index: "GSI1",
|
|
828
|
+
pk: {
|
|
829
|
+
field: "GSI1PK",
|
|
830
|
+
composite: ["tenantId", "workspaceId", "gsi1Shard"],
|
|
831
|
+
template: "TID#${tenantId}#WID#${workspaceId}#RT#Configuration#SHARD#${gsi1Shard}"
|
|
832
|
+
},
|
|
833
|
+
sk: {
|
|
834
|
+
field: "GSI1SK",
|
|
835
|
+
casing: "none",
|
|
836
|
+
composite: ["key", "id"],
|
|
837
|
+
template: "${key}#${id}"
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
// src/data/dynamo/entities/control/membership-entity.ts
|
|
844
|
+
var import_electrodb2 = require("electrodb");
|
|
845
|
+
var MembershipEntity = new import_electrodb2.Entity({
|
|
846
|
+
model: {
|
|
847
|
+
entity: "membership",
|
|
848
|
+
service: "control",
|
|
849
|
+
version: "01"
|
|
850
|
+
},
|
|
851
|
+
attributes: {
|
|
852
|
+
/** Sort key sentinel. Always "CURRENT". */
|
|
853
|
+
sk: {
|
|
854
|
+
type: "string",
|
|
855
|
+
required: true,
|
|
856
|
+
default: "CURRENT"
|
|
857
|
+
},
|
|
858
|
+
/** Tenant in which the user has membership (required). */
|
|
859
|
+
tenantId: {
|
|
860
|
+
type: "string",
|
|
861
|
+
required: true
|
|
862
|
+
},
|
|
863
|
+
/** FHIR Resource.id; membership id. */
|
|
864
|
+
id: {
|
|
865
|
+
type: "string",
|
|
866
|
+
required: true
|
|
867
|
+
},
|
|
868
|
+
/** Full Membership resource serialized as JSON string. */
|
|
869
|
+
resource: {
|
|
870
|
+
type: "string",
|
|
871
|
+
required: true
|
|
872
|
+
},
|
|
873
|
+
/**
|
|
874
|
+
* Summary projection (key display fields as JSON string: id, displayName, status).
|
|
875
|
+
* Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
|
|
876
|
+
*/
|
|
877
|
+
summary: {
|
|
878
|
+
type: "string",
|
|
879
|
+
required: true
|
|
880
|
+
},
|
|
881
|
+
/** Version id (e.g. ULID). */
|
|
882
|
+
vid: {
|
|
883
|
+
type: "string",
|
|
884
|
+
required: true
|
|
885
|
+
},
|
|
886
|
+
lastUpdated: {
|
|
887
|
+
type: "string",
|
|
888
|
+
required: true
|
|
889
|
+
},
|
|
890
|
+
gsi1Shard: gsi1ShardAttribute,
|
|
891
|
+
/** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
|
|
892
|
+
gsi1sk: gsi1skAttribute,
|
|
893
|
+
deleted: {
|
|
894
|
+
type: "boolean",
|
|
895
|
+
required: false
|
|
896
|
+
},
|
|
897
|
+
bundleId: {
|
|
898
|
+
type: "string",
|
|
899
|
+
required: false
|
|
900
|
+
},
|
|
901
|
+
msgId: {
|
|
902
|
+
type: "string",
|
|
903
|
+
required: false
|
|
904
|
+
}
|
|
905
|
+
},
|
|
906
|
+
indexes: {
|
|
907
|
+
/** Base table: PK = TID#<tenantId>#MEMBERSHIP#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */
|
|
908
|
+
record: {
|
|
909
|
+
pk: {
|
|
910
|
+
field: "PK",
|
|
911
|
+
composite: ["tenantId", "id"],
|
|
912
|
+
template: "TID#${tenantId}#MEMBERSHIP#ID#${id}"
|
|
913
|
+
},
|
|
914
|
+
sk: {
|
|
915
|
+
field: "SK",
|
|
916
|
+
composite: ["sk"],
|
|
917
|
+
template: "${sk}"
|
|
918
|
+
}
|
|
919
|
+
},
|
|
920
|
+
/**
|
|
921
|
+
* GSI1 — Unified Sharded List per ADR-011: list all Memberships for a tenant across the
|
|
922
|
+
* four shards. Membership is tenant-scoped only, so `WID#-` is a sentinel.
|
|
923
|
+
* SK is derived via `gsi1skAttribute` — uses the resource's natural label when
|
|
924
|
+
* extractable, else `<lastUpdated>#<id>` (DR-004). `casing: "none"` preserves the
|
|
925
|
+
* normalized label and ISO-8601 `T`/`Z`.
|
|
926
|
+
*/
|
|
927
|
+
gsi1: {
|
|
928
|
+
index: "GSI1",
|
|
929
|
+
pk: {
|
|
930
|
+
field: "GSI1PK",
|
|
931
|
+
composite: ["tenantId", "gsi1Shard"],
|
|
932
|
+
template: "TID#${tenantId}#WID#-#RT#Membership#SHARD#${gsi1Shard}"
|
|
933
|
+
},
|
|
934
|
+
sk: {
|
|
935
|
+
field: "GSI1SK",
|
|
936
|
+
casing: "none",
|
|
937
|
+
composite: ["gsi1sk"],
|
|
938
|
+
template: "${gsi1sk}"
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
// src/data/dynamo/entities/control/role-entity.ts
|
|
945
|
+
var import_electrodb3 = require("electrodb");
|
|
946
|
+
var RoleEntity = new import_electrodb3.Entity({
|
|
947
|
+
model: {
|
|
948
|
+
entity: "role",
|
|
949
|
+
service: "control",
|
|
950
|
+
version: "01"
|
|
951
|
+
},
|
|
952
|
+
attributes: {
|
|
953
|
+
/** Sort key sentinel. Always "CURRENT". */
|
|
954
|
+
sk: {
|
|
955
|
+
type: "string",
|
|
956
|
+
required: true,
|
|
957
|
+
default: "CURRENT"
|
|
958
|
+
},
|
|
959
|
+
/** FHIR Resource.id; role id. */
|
|
960
|
+
id: {
|
|
961
|
+
type: "string",
|
|
962
|
+
required: true
|
|
963
|
+
},
|
|
964
|
+
/** Full Role resource serialized as JSON string. */
|
|
965
|
+
resource: {
|
|
966
|
+
type: "string",
|
|
967
|
+
required: true
|
|
968
|
+
},
|
|
969
|
+
/**
|
|
970
|
+
* Summary projection (key display fields as JSON string: id, displayName, status).
|
|
971
|
+
* Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
|
|
972
|
+
*/
|
|
973
|
+
summary: {
|
|
974
|
+
type: "string",
|
|
975
|
+
required: true
|
|
976
|
+
},
|
|
977
|
+
/** Version id (e.g. ULID). */
|
|
978
|
+
vid: {
|
|
979
|
+
type: "string",
|
|
980
|
+
required: true
|
|
981
|
+
},
|
|
982
|
+
lastUpdated: {
|
|
983
|
+
type: "string",
|
|
984
|
+
required: true
|
|
985
|
+
},
|
|
986
|
+
gsi1Shard: gsi1ShardAttribute,
|
|
987
|
+
/** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
|
|
988
|
+
gsi1sk: gsi1skAttribute,
|
|
989
|
+
deleted: {
|
|
990
|
+
type: "boolean",
|
|
991
|
+
required: false
|
|
992
|
+
},
|
|
993
|
+
bundleId: {
|
|
994
|
+
type: "string",
|
|
995
|
+
required: false
|
|
996
|
+
},
|
|
997
|
+
msgId: {
|
|
998
|
+
type: "string",
|
|
999
|
+
required: false
|
|
1000
|
+
}
|
|
1001
|
+
},
|
|
1002
|
+
indexes: {
|
|
1003
|
+
/** Base table: PK = ROLE#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */
|
|
1004
|
+
record: {
|
|
1005
|
+
pk: {
|
|
1006
|
+
field: "PK",
|
|
1007
|
+
composite: ["id"],
|
|
1008
|
+
template: "ROLE#ID#${id}"
|
|
1009
|
+
},
|
|
1010
|
+
sk: {
|
|
1011
|
+
field: "SK",
|
|
1012
|
+
composite: ["sk"],
|
|
1013
|
+
template: "${sk}"
|
|
1014
|
+
}
|
|
1015
|
+
},
|
|
1016
|
+
/**
|
|
1017
|
+
* GSI1 — Unified Sharded List per ADR-011: list all Roles across the four shards.
|
|
1018
|
+
* Non-tenant-isolated, so `TID#-#WID#-` sentinels precede `RT#Role#SHARD#<n>`.
|
|
1019
|
+
* SK is derived via `gsi1skAttribute` — uses the resource's natural label when
|
|
1020
|
+
* extractable, else `<lastUpdated>#<id>` (DR-004). `casing: "none"` preserves the
|
|
1021
|
+
* normalized label and ISO-8601 `T`/`Z`.
|
|
1022
|
+
*/
|
|
1023
|
+
gsi1: {
|
|
1024
|
+
index: "GSI1",
|
|
1025
|
+
pk: {
|
|
1026
|
+
field: "GSI1PK",
|
|
1027
|
+
composite: ["gsi1Shard"],
|
|
1028
|
+
template: "TID#-#WID#-#RT#Role#SHARD#${gsi1Shard}"
|
|
1029
|
+
},
|
|
1030
|
+
sk: {
|
|
1031
|
+
field: "GSI1SK",
|
|
1032
|
+
casing: "none",
|
|
1033
|
+
composite: ["gsi1sk"],
|
|
1034
|
+
template: "${gsi1sk}"
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
});
|
|
1039
|
+
|
|
1040
|
+
// src/data/dynamo/entities/control/roleassignment-entity.ts
|
|
1041
|
+
var import_electrodb4 = require("electrodb");
|
|
1042
|
+
var RoleAssignmentEntity = new import_electrodb4.Entity({
|
|
1043
|
+
model: {
|
|
1044
|
+
entity: "roleassignment",
|
|
1045
|
+
service: "control",
|
|
1046
|
+
version: "01"
|
|
1047
|
+
},
|
|
1048
|
+
attributes: {
|
|
1049
|
+
/** Sort key sentinel. Always "CURRENT". */
|
|
1050
|
+
sk: {
|
|
1051
|
+
type: "string",
|
|
1052
|
+
required: true,
|
|
1053
|
+
default: "CURRENT"
|
|
1054
|
+
},
|
|
1055
|
+
/** Tenant in which the role assignment applies (required). */
|
|
1056
|
+
tenantId: {
|
|
1057
|
+
type: "string",
|
|
1058
|
+
required: true
|
|
1059
|
+
},
|
|
1060
|
+
/** FHIR Resource.id; role assignment id. */
|
|
1061
|
+
id: {
|
|
1062
|
+
type: "string",
|
|
1063
|
+
required: true
|
|
1064
|
+
},
|
|
1065
|
+
/** Full RoleAssignment resource serialized as JSON string. */
|
|
1066
|
+
resource: {
|
|
1067
|
+
type: "string",
|
|
1068
|
+
required: true
|
|
1069
|
+
},
|
|
1070
|
+
/**
|
|
1071
|
+
* Summary projection (key display fields as JSON string: id, displayName, status).
|
|
1072
|
+
* Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
|
|
1073
|
+
*/
|
|
1074
|
+
summary: {
|
|
1075
|
+
type: "string",
|
|
1076
|
+
required: true
|
|
1077
|
+
},
|
|
1078
|
+
/** Version id (e.g. ULID). */
|
|
1079
|
+
vid: {
|
|
1080
|
+
type: "string",
|
|
1081
|
+
required: true
|
|
1082
|
+
},
|
|
1083
|
+
lastUpdated: {
|
|
1084
|
+
type: "string",
|
|
1085
|
+
required: true
|
|
1086
|
+
},
|
|
1087
|
+
gsi1Shard: gsi1ShardAttribute,
|
|
1088
|
+
/** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
|
|
1089
|
+
gsi1sk: gsi1skAttribute,
|
|
1090
|
+
deleted: {
|
|
1091
|
+
type: "boolean",
|
|
1092
|
+
required: false
|
|
1093
|
+
},
|
|
1094
|
+
bundleId: {
|
|
1095
|
+
type: "string",
|
|
1096
|
+
required: false
|
|
1097
|
+
},
|
|
1098
|
+
msgId: {
|
|
1099
|
+
type: "string",
|
|
1100
|
+
required: false
|
|
1101
|
+
}
|
|
1102
|
+
},
|
|
1103
|
+
indexes: {
|
|
1104
|
+
/** Base table: PK = TID#<tenantId>#ROLEASSIGNMENT#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */
|
|
1105
|
+
record: {
|
|
1106
|
+
pk: {
|
|
1107
|
+
field: "PK",
|
|
1108
|
+
composite: ["tenantId", "id"],
|
|
1109
|
+
template: "TID#${tenantId}#ROLEASSIGNMENT#ID#${id}"
|
|
1110
|
+
},
|
|
1111
|
+
sk: {
|
|
1112
|
+
field: "SK",
|
|
1113
|
+
composite: ["sk"],
|
|
1114
|
+
template: "${sk}"
|
|
1115
|
+
}
|
|
1116
|
+
},
|
|
1117
|
+
/**
|
|
1118
|
+
* GSI1 — Unified Sharded List per ADR-011: list all RoleAssignments for a tenant across the
|
|
1119
|
+
* four shards. Tenant-scoped only, so `WID#-` is a sentinel.
|
|
1120
|
+
* SK is derived via `gsi1skAttribute` — uses the resource's natural label when
|
|
1121
|
+
* extractable, else `<lastUpdated>#<id>` (DR-004). `casing: "none"` preserves the
|
|
1122
|
+
* normalized label and ISO-8601 `T`/`Z`.
|
|
1123
|
+
*/
|
|
1124
|
+
gsi1: {
|
|
1125
|
+
index: "GSI1",
|
|
1126
|
+
pk: {
|
|
1127
|
+
field: "GSI1PK",
|
|
1128
|
+
composite: ["tenantId", "gsi1Shard"],
|
|
1129
|
+
template: "TID#${tenantId}#WID#-#RT#RoleAssignment#SHARD#${gsi1Shard}"
|
|
1130
|
+
},
|
|
1131
|
+
sk: {
|
|
1132
|
+
field: "GSI1SK",
|
|
1133
|
+
casing: "none",
|
|
1134
|
+
composite: ["gsi1sk"],
|
|
1135
|
+
template: "${gsi1sk}"
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
});
|
|
1140
|
+
|
|
1141
|
+
// src/data/dynamo/entities/control/tenant-entity.ts
|
|
1142
|
+
var import_electrodb5 = require("electrodb");
|
|
1143
|
+
var TenantEntity = new import_electrodb5.Entity({
|
|
1144
|
+
model: {
|
|
1145
|
+
entity: "tenant",
|
|
1146
|
+
service: "control",
|
|
1147
|
+
version: "01"
|
|
1148
|
+
},
|
|
1149
|
+
attributes: {
|
|
1150
|
+
/** Sort key sentinel. Always "CURRENT". */
|
|
1151
|
+
sk: {
|
|
1152
|
+
type: "string",
|
|
1153
|
+
required: true,
|
|
1154
|
+
default: "CURRENT"
|
|
1155
|
+
},
|
|
1156
|
+
/** The tenant's own id (= resource id). Drives the partition key. */
|
|
1157
|
+
tenantId: {
|
|
1158
|
+
type: "string",
|
|
1159
|
+
required: true
|
|
1160
|
+
},
|
|
1161
|
+
/** FHIR Resource.id; logical id in URL. Equals tenantId. */
|
|
1162
|
+
id: {
|
|
1163
|
+
type: "string",
|
|
1164
|
+
required: true
|
|
1165
|
+
},
|
|
1166
|
+
/** Full Tenant resource serialized as JSON string. */
|
|
1167
|
+
resource: {
|
|
1168
|
+
type: "string",
|
|
1169
|
+
required: true
|
|
1170
|
+
},
|
|
1171
|
+
/**
|
|
1172
|
+
* Summary projection (key display fields as JSON string: id, displayName, status).
|
|
1173
|
+
* Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
|
|
1174
|
+
*/
|
|
1175
|
+
summary: {
|
|
1176
|
+
type: "string",
|
|
1177
|
+
required: true
|
|
1178
|
+
},
|
|
1179
|
+
/** Version id (e.g. ULID). */
|
|
1180
|
+
vid: {
|
|
1181
|
+
type: "string",
|
|
1182
|
+
required: true
|
|
1183
|
+
},
|
|
1184
|
+
lastUpdated: {
|
|
1185
|
+
type: "string",
|
|
1186
|
+
required: true
|
|
1187
|
+
},
|
|
1188
|
+
gsi1Shard: gsi1ShardAttribute,
|
|
1189
|
+
/** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
|
|
1190
|
+
gsi1sk: gsi1skAttribute,
|
|
1191
|
+
deleted: {
|
|
1192
|
+
type: "boolean",
|
|
1193
|
+
required: false
|
|
1194
|
+
},
|
|
1195
|
+
bundleId: {
|
|
1196
|
+
type: "string",
|
|
1197
|
+
required: false
|
|
1198
|
+
},
|
|
1199
|
+
msgId: {
|
|
1200
|
+
type: "string",
|
|
1201
|
+
required: false
|
|
1202
|
+
}
|
|
1203
|
+
},
|
|
1204
|
+
indexes: {
|
|
1205
|
+
/** Base table: PK = TENANT#ID#<tenantId>, SK = CURRENT. Do not supply PK or SK from outside. */
|
|
1206
|
+
record: {
|
|
1207
|
+
pk: {
|
|
1208
|
+
field: "PK",
|
|
1209
|
+
composite: ["tenantId"],
|
|
1210
|
+
template: "TENANT#ID#${tenantId}"
|
|
1211
|
+
},
|
|
1212
|
+
sk: {
|
|
1213
|
+
field: "SK",
|
|
1214
|
+
composite: ["sk"],
|
|
1215
|
+
template: "${sk}"
|
|
1216
|
+
}
|
|
1217
|
+
},
|
|
1218
|
+
/**
|
|
1219
|
+
* GSI1 — Unified Sharded List per ADR-011: list all Tenants across the four shards.
|
|
1220
|
+
* Tenant lives at the platform tier (no parent tenant or workspace), so `TID#-#WID#-`
|
|
1221
|
+
* sentinels precede `RT#Tenant#SHARD#<n>`. SK is derived via `gsi1skAttribute` —
|
|
1222
|
+
* `<normalizedName>#<id>` when the resource carries a `name`, else `<lastUpdated>#<id>`
|
|
1223
|
+
* (DR-004). `casing: "none"` preserves the normalized label and ISO-8601 `T`/`Z`.
|
|
1224
|
+
*/
|
|
1225
|
+
gsi1: {
|
|
1226
|
+
index: "GSI1",
|
|
1227
|
+
pk: {
|
|
1228
|
+
field: "GSI1PK",
|
|
1229
|
+
composite: ["gsi1Shard"],
|
|
1230
|
+
template: "TID#-#WID#-#RT#Tenant#SHARD#${gsi1Shard}"
|
|
1231
|
+
},
|
|
1232
|
+
sk: {
|
|
1233
|
+
field: "GSI1SK",
|
|
1234
|
+
casing: "none",
|
|
1235
|
+
composite: ["gsi1sk"],
|
|
1236
|
+
template: "${gsi1sk}"
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
});
|
|
1241
|
+
|
|
1242
|
+
// src/data/dynamo/entities/control/user-entity.ts
|
|
1243
|
+
var import_electrodb6 = require("electrodb");
|
|
1244
|
+
var UserEntity = new import_electrodb6.Entity({
|
|
1245
|
+
model: {
|
|
1246
|
+
entity: "user",
|
|
1247
|
+
service: "control",
|
|
1248
|
+
version: "01"
|
|
1249
|
+
},
|
|
1250
|
+
attributes: {
|
|
1251
|
+
/** Sort key sentinel. Always "CURRENT". */
|
|
1252
|
+
sk: {
|
|
1253
|
+
type: "string",
|
|
1254
|
+
required: true,
|
|
1255
|
+
default: "CURRENT"
|
|
1256
|
+
},
|
|
1257
|
+
/** FHIR Resource.id; platform user id (ohi_uid). */
|
|
1258
|
+
id: {
|
|
1259
|
+
type: "string",
|
|
1260
|
+
required: true
|
|
1261
|
+
},
|
|
1262
|
+
/** Full User resource serialized as JSON string. */
|
|
1263
|
+
resource: {
|
|
1264
|
+
type: "string",
|
|
1265
|
+
required: true
|
|
1266
|
+
},
|
|
1267
|
+
/**
|
|
1268
|
+
* Summary projection (key display fields as JSON string: id, displayName, status).
|
|
1269
|
+
* Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
|
|
1270
|
+
*/
|
|
1271
|
+
summary: {
|
|
1272
|
+
type: "string",
|
|
1273
|
+
required: true
|
|
1274
|
+
},
|
|
1275
|
+
/**
|
|
1276
|
+
* Immutable Cognito-issued `sub` claim. Drives GSI2 (sub-lookup). Optional until the
|
|
1277
|
+
* Post Confirmation Lambda (#770) lands; required thereafter.
|
|
1278
|
+
*/
|
|
1279
|
+
cognitoSub: {
|
|
1280
|
+
type: "string",
|
|
1281
|
+
required: false
|
|
1282
|
+
},
|
|
1283
|
+
/** Version id (e.g. ULID). */
|
|
1284
|
+
vid: {
|
|
1285
|
+
type: "string",
|
|
1286
|
+
required: true
|
|
1287
|
+
},
|
|
1288
|
+
lastUpdated: {
|
|
1289
|
+
type: "string",
|
|
1290
|
+
required: true
|
|
1291
|
+
},
|
|
1292
|
+
gsi1Shard: gsi1ShardAttribute,
|
|
1293
|
+
/** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
|
|
1294
|
+
gsi1sk: gsi1skAttribute,
|
|
1295
|
+
deleted: {
|
|
1296
|
+
type: "boolean",
|
|
1297
|
+
required: false
|
|
1298
|
+
},
|
|
1299
|
+
bundleId: {
|
|
1300
|
+
type: "string",
|
|
1301
|
+
required: false
|
|
1302
|
+
},
|
|
1303
|
+
msgId: {
|
|
1304
|
+
type: "string",
|
|
1305
|
+
required: false
|
|
1306
|
+
}
|
|
1307
|
+
},
|
|
1308
|
+
indexes: {
|
|
1309
|
+
/** Base table: PK = USER#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */
|
|
1310
|
+
record: {
|
|
1311
|
+
pk: {
|
|
1312
|
+
field: "PK",
|
|
1313
|
+
composite: ["id"],
|
|
1314
|
+
template: "USER#ID#${id}"
|
|
1315
|
+
},
|
|
1316
|
+
sk: {
|
|
1317
|
+
field: "SK",
|
|
1318
|
+
composite: ["sk"],
|
|
1319
|
+
template: "${sk}"
|
|
1320
|
+
}
|
|
1321
|
+
},
|
|
1322
|
+
/**
|
|
1323
|
+
* GSI1 — Unified Sharded List per ADR-011: list all Users across the four shards.
|
|
1324
|
+
* Non-tenant-isolated, so `TID#-#WID#-` sentinels precede `RT#User#SHARD#<n>`.
|
|
1325
|
+
* SK is derived via `gsi1skAttribute` — uses the resource's natural label when
|
|
1326
|
+
* extractable (string `name`/`title` via introspection), else `<lastUpdated>#<id>`
|
|
1327
|
+
* (DR-004). `casing: "none"` preserves the normalized label and ISO-8601 `T`/`Z`.
|
|
1328
|
+
*/
|
|
1329
|
+
gsi1: {
|
|
1330
|
+
index: "GSI1",
|
|
1331
|
+
pk: {
|
|
1332
|
+
field: "GSI1PK",
|
|
1333
|
+
composite: ["gsi1Shard"],
|
|
1334
|
+
template: "TID#-#WID#-#RT#User#SHARD#${gsi1Shard}"
|
|
1335
|
+
},
|
|
1336
|
+
sk: {
|
|
1337
|
+
field: "GSI1SK",
|
|
1338
|
+
casing: "none",
|
|
1339
|
+
composite: ["gsi1sk"],
|
|
1340
|
+
template: "${gsi1sk}"
|
|
1341
|
+
}
|
|
1342
|
+
},
|
|
1343
|
+
/**
|
|
1344
|
+
* GSI2 — Cognito sub-lookup per ADR-011: resolves the UserEntity from a Cognito `sub` claim.
|
|
1345
|
+
* `condition` skips the index when `cognitoSub` is missing so legacy items without a sub are
|
|
1346
|
+
* not indexed.
|
|
1347
|
+
*/
|
|
1348
|
+
gsi2: {
|
|
1349
|
+
index: "GSI2",
|
|
1350
|
+
condition: (attrs) => typeof attrs.cognitoSub === "string" && attrs.cognitoSub.length > 0,
|
|
1351
|
+
pk: {
|
|
1352
|
+
field: "GSI2PK",
|
|
1353
|
+
casing: "none",
|
|
1354
|
+
composite: ["cognitoSub"],
|
|
1355
|
+
template: "USER#SUB#${cognitoSub}"
|
|
1356
|
+
},
|
|
1357
|
+
sk: {
|
|
1358
|
+
field: "GSI2SK",
|
|
1359
|
+
casing: "none",
|
|
1360
|
+
composite: [],
|
|
1361
|
+
template: "CURRENT"
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
});
|
|
1366
|
+
|
|
1367
|
+
// src/data/dynamo/entities/control/workspace-entity.ts
|
|
1368
|
+
var import_electrodb7 = require("electrodb");
|
|
1369
|
+
var WorkspaceEntity = new import_electrodb7.Entity({
|
|
1370
|
+
model: {
|
|
1371
|
+
entity: "workspace",
|
|
1372
|
+
service: "control",
|
|
1373
|
+
version: "01"
|
|
1374
|
+
},
|
|
1375
|
+
attributes: {
|
|
1376
|
+
/** Sort key sentinel. Always "CURRENT". */
|
|
1377
|
+
sk: {
|
|
1378
|
+
type: "string",
|
|
1379
|
+
required: true,
|
|
1380
|
+
default: "CURRENT"
|
|
1381
|
+
},
|
|
1382
|
+
/** Tenant that contains this workspace (required). */
|
|
1383
|
+
tenantId: {
|
|
1384
|
+
type: "string",
|
|
1385
|
+
required: true
|
|
1386
|
+
},
|
|
1387
|
+
/** FHIR Resource.id; logical id in URL. */
|
|
1388
|
+
id: {
|
|
1389
|
+
type: "string",
|
|
1390
|
+
required: true
|
|
1391
|
+
},
|
|
1392
|
+
/** Full Workspace resource serialized as JSON string. */
|
|
1393
|
+
resource: {
|
|
1394
|
+
type: "string",
|
|
1395
|
+
required: true
|
|
1396
|
+
},
|
|
1397
|
+
/**
|
|
1398
|
+
* Summary projection (key display fields as JSON string: id, displayName, status).
|
|
1399
|
+
* Populated on every write via extractSummary(resource); GSI1 INCLUDE surfaces it on lists.
|
|
1400
|
+
*/
|
|
1401
|
+
summary: {
|
|
1402
|
+
type: "string",
|
|
1403
|
+
required: true
|
|
1404
|
+
},
|
|
1405
|
+
/** Version id (e.g. ULID). */
|
|
1406
|
+
vid: {
|
|
1407
|
+
type: "string",
|
|
1408
|
+
required: true
|
|
1409
|
+
},
|
|
1410
|
+
lastUpdated: {
|
|
1411
|
+
type: "string",
|
|
1412
|
+
required: true
|
|
1413
|
+
},
|
|
1414
|
+
gsi1Shard: gsi1ShardAttribute,
|
|
1415
|
+
/** Derived GSI1 sort key — name-based when extractable; else `<lastUpdated>#<id>`. */
|
|
1416
|
+
gsi1sk: gsi1skAttribute,
|
|
1417
|
+
deleted: {
|
|
1418
|
+
type: "boolean",
|
|
1419
|
+
required: false
|
|
1420
|
+
},
|
|
1421
|
+
bundleId: {
|
|
1422
|
+
type: "string",
|
|
1423
|
+
required: false
|
|
1424
|
+
},
|
|
1425
|
+
msgId: {
|
|
1426
|
+
type: "string",
|
|
1427
|
+
required: false
|
|
1428
|
+
}
|
|
1429
|
+
},
|
|
1430
|
+
indexes: {
|
|
1431
|
+
/** Base table: PK = TID#<tenantId>#WORKSPACE#ID#<id>, SK = CURRENT. Do not supply PK or SK from outside. */
|
|
1432
|
+
record: {
|
|
1433
|
+
pk: {
|
|
1434
|
+
field: "PK",
|
|
1435
|
+
composite: ["tenantId", "id"],
|
|
1436
|
+
template: "TID#${tenantId}#WORKSPACE#ID#${id}"
|
|
1437
|
+
},
|
|
1438
|
+
sk: {
|
|
1439
|
+
field: "SK",
|
|
1440
|
+
composite: ["sk"],
|
|
1441
|
+
template: "${sk}"
|
|
1442
|
+
}
|
|
1443
|
+
},
|
|
1444
|
+
/**
|
|
1445
|
+
* GSI1 — Unified Sharded List per ADR-011: list all Workspaces for a tenant across the
|
|
1446
|
+
* four shards. Workspace is itself the workspace identity, so `WID#-` is a sentinel.
|
|
1447
|
+
* SK is derived via `gsi1skAttribute` — `<normalizedName>#<id>` when the resource
|
|
1448
|
+
* carries a `name`, else `<lastUpdated>#<id>` (DR-004). `casing: "none"` preserves
|
|
1449
|
+
* the normalized label and ISO-8601 `T`/`Z`.
|
|
1450
|
+
*/
|
|
1451
|
+
gsi1: {
|
|
1452
|
+
index: "GSI1",
|
|
1453
|
+
pk: {
|
|
1454
|
+
field: "GSI1PK",
|
|
1455
|
+
composite: ["tenantId", "gsi1Shard"],
|
|
1456
|
+
template: "TID#${tenantId}#WID#-#RT#Workspace#SHARD#${gsi1Shard}"
|
|
1457
|
+
},
|
|
1458
|
+
sk: {
|
|
1459
|
+
field: "GSI1SK",
|
|
1460
|
+
casing: "none",
|
|
1461
|
+
composite: ["gsi1sk"],
|
|
1462
|
+
template: "${gsi1sk}"
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
});
|
|
1467
|
+
|
|
1468
|
+
// src/data/dynamo/dynamo-control-service.ts
|
|
1469
|
+
var controlPlaneEntities = {
|
|
1470
|
+
configuration: ConfigurationEntity,
|
|
1471
|
+
membership: MembershipEntity,
|
|
1472
|
+
role: RoleEntity,
|
|
1473
|
+
roleAssignment: RoleAssignmentEntity,
|
|
1474
|
+
tenant: TenantEntity,
|
|
1475
|
+
user: UserEntity,
|
|
1476
|
+
workspace: WorkspaceEntity
|
|
1477
|
+
};
|
|
1478
|
+
var controlPlaneService = new import_electrodb8.Service(controlPlaneEntities, {
|
|
1479
|
+
table: defaultTableName,
|
|
1480
|
+
client: dynamoClient
|
|
1481
|
+
});
|
|
1482
|
+
var DynamoControlService = {
|
|
1483
|
+
entities: controlPlaneService.entities
|
|
1484
|
+
};
|
|
1485
|
+
function getDynamoControlService(tableName) {
|
|
1486
|
+
const resolved = tableName ?? defaultTableName;
|
|
1487
|
+
const service = new import_electrodb8.Service(controlPlaneEntities, {
|
|
1488
|
+
table: resolved,
|
|
1489
|
+
client: dynamoClient
|
|
1490
|
+
});
|
|
1491
|
+
return {
|
|
1492
|
+
entities: service.entities
|
|
1493
|
+
};
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
// src/data/operations/control/role/role-create-operation.ts
|
|
1497
|
+
async function createRoleOperation(params) {
|
|
1498
|
+
const { context, body, tableName } = params;
|
|
1499
|
+
const service = getDynamoControlService(tableName);
|
|
1500
|
+
const id = body.id ?? `role-${Date.now()}`;
|
|
1501
|
+
const parsedResource = typeof body.resource === "string" ? JSON.parse(body.resource) : body.resource ?? {};
|
|
1502
|
+
const lastUpdated = context.date ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
1503
|
+
const vid = `1`;
|
|
1504
|
+
const resource = { resourceType: "Role", id, ...parsedResource };
|
|
1505
|
+
const summary = JSON.stringify((0, import_types2.extractSummary)(resource));
|
|
1506
|
+
await service.entities.role.put({
|
|
1507
|
+
id,
|
|
1508
|
+
resource: JSON.stringify(resource),
|
|
1509
|
+
summary,
|
|
1510
|
+
vid,
|
|
1511
|
+
lastUpdated
|
|
1512
|
+
}).go();
|
|
1513
|
+
return {
|
|
1514
|
+
id,
|
|
1515
|
+
resource,
|
|
1516
|
+
meta: { lastUpdated, versionId: vid }
|
|
1517
|
+
};
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
// src/workflows/control-plane/seed-system-data/seed-system-data.handler.ts
|
|
1521
|
+
var errorMessage = (err) => {
|
|
1522
|
+
if (err instanceof Error) {
|
|
1523
|
+
return err.message;
|
|
1524
|
+
}
|
|
1525
|
+
return String(err);
|
|
1526
|
+
};
|
|
1527
|
+
var idForRoleCode = (code) => {
|
|
1528
|
+
for (const key of Object.keys(import_types3.CONTROL_PLANE_ROLE_IDS)) {
|
|
1529
|
+
if (import_types3.CONTROL_PLANE_ROLE_CONCEPTS[key].code === code) {
|
|
1530
|
+
return import_types3.CONTROL_PLANE_ROLE_IDS[key];
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
throw new Error(`No id mapping for role code "${code}".`);
|
|
1534
|
+
};
|
|
1535
|
+
var seedSystemRoles = async (context) => {
|
|
1536
|
+
for (const concept of Object.values(import_types3.CONTROL_PLANE_ROLE_CONCEPTS)) {
|
|
1537
|
+
const id = idForRoleCode(concept.code);
|
|
1538
|
+
await createRoleOperation({
|
|
1539
|
+
context,
|
|
1540
|
+
body: {
|
|
1541
|
+
id,
|
|
1542
|
+
resource: {
|
|
1543
|
+
resourceType: "Role",
|
|
1544
|
+
code: concept.code,
|
|
1545
|
+
display: concept.display,
|
|
1546
|
+
active: true
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
});
|
|
1550
|
+
}
|
|
1551
|
+
};
|
|
1552
|
+
var runSeedSystemData = async (event, deps) => {
|
|
1553
|
+
const parsed = (0, import_workflows2.parseWorkflowEvent)(event, import_workflows.PlatformDeploymentCompletedV1);
|
|
1554
|
+
const recordResult = await deps.dedupClient.recordIfAbsent({
|
|
1555
|
+
consumerName: SEED_SYSTEM_DATA_CONSUMER_NAME,
|
|
1556
|
+
eventId: parsed.dedupKey.eventId,
|
|
1557
|
+
attempt: parsed.dedupKey.attempt
|
|
1558
|
+
});
|
|
1559
|
+
if (!recordResult.recorded) {
|
|
1560
|
+
return;
|
|
1561
|
+
}
|
|
1562
|
+
const lastUpdated = parsed.envelope.occurredAt;
|
|
1563
|
+
const context = {
|
|
1564
|
+
tenantId: "",
|
|
1565
|
+
workspaceId: "",
|
|
1566
|
+
date: lastUpdated,
|
|
1567
|
+
actorId: "platform-deploy-bridge",
|
|
1568
|
+
actorName: "Platform Deploy Bridge",
|
|
1569
|
+
actorType: "internal-system",
|
|
1570
|
+
source: "step-function"
|
|
1571
|
+
};
|
|
1572
|
+
try {
|
|
1573
|
+
await deps.seedRoles(context);
|
|
1574
|
+
} catch (err) {
|
|
1575
|
+
await deps.dedupClient.markFailed({
|
|
1576
|
+
consumerName: SEED_SYSTEM_DATA_CONSUMER_NAME,
|
|
1577
|
+
eventId: parsed.dedupKey.eventId,
|
|
1578
|
+
attempt: parsed.dedupKey.attempt,
|
|
1579
|
+
reason: errorMessage(err)
|
|
1580
|
+
});
|
|
1581
|
+
throw err;
|
|
1582
|
+
}
|
|
1583
|
+
const sourcePayload = parsed.envelope.payload;
|
|
1584
|
+
await deps.publishSeeded({
|
|
1585
|
+
payload: {
|
|
1586
|
+
sourceEventId: parsed.envelope.eventId,
|
|
1587
|
+
sourceStackId: sourcePayload.stackId,
|
|
1588
|
+
seededRecordCount: Object.keys(import_types3.CONTROL_PLANE_ROLE_IDS).length
|
|
1589
|
+
},
|
|
1590
|
+
envelope: {
|
|
1591
|
+
correlationId: parsed.envelope.correlationId,
|
|
1592
|
+
causationId: parsed.envelope.eventId
|
|
1593
|
+
}
|
|
1594
|
+
});
|
|
1595
|
+
};
|
|
1596
|
+
var productionDependencies = () => {
|
|
1597
|
+
const dynamodb = new import_client_dynamodb2.DynamoDBClient({});
|
|
1598
|
+
const eventBridge = new import_client_eventbridge.EventBridgeClient({});
|
|
1599
|
+
return {
|
|
1600
|
+
dedupClient: (0, import_workflows2.workflowDedupClient)(dynamodb),
|
|
1601
|
+
seedRoles: seedSystemRoles,
|
|
1602
|
+
publishSeeded: async (input) => {
|
|
1603
|
+
const controlBusName = process.env[SEED_SYSTEM_DATA_CONTROL_BUS_ENV_VAR];
|
|
1604
|
+
if (!controlBusName) {
|
|
1605
|
+
throw new Error(
|
|
1606
|
+
`seed-system-data: ${SEED_SYSTEM_DATA_CONTROL_BUS_ENV_VAR} env var is required to publish system-data-seeded events.`
|
|
1607
|
+
);
|
|
1608
|
+
}
|
|
1609
|
+
return (0, import_workflows2.publishWorkflowEvent)(
|
|
1610
|
+
eventBridge,
|
|
1611
|
+
import_workflows.PlatformSystemDataSeededV1,
|
|
1612
|
+
input.payload,
|
|
1613
|
+
{
|
|
1614
|
+
actor: { system: SEED_SYSTEM_DATA_ACTOR_SYSTEM },
|
|
1615
|
+
correlationId: input.envelope.correlationId,
|
|
1616
|
+
causationId: input.envelope.causationId
|
|
1617
|
+
},
|
|
1618
|
+
{
|
|
1619
|
+
busNameByPlane: { [import_workflows2.OPENHI_CONTROL_SOURCE]: controlBusName }
|
|
1620
|
+
}
|
|
1621
|
+
);
|
|
1622
|
+
}
|
|
1623
|
+
};
|
|
1624
|
+
};
|
|
1625
|
+
var handler = async (event) => runSeedSystemData(event, productionDependencies());
|
|
1626
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1627
|
+
0 && (module.exports = {
|
|
1628
|
+
handler,
|
|
1629
|
+
runSeedSystemData
|
|
1630
|
+
});
|
|
1631
|
+
//# sourceMappingURL=seed-system-data.handler.js.map
|