@openhi/constructs 0.0.160 → 0.0.161
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-HQ67J7BP.mjs → chunk-5S6VFBLT.mjs} +12 -70
- package/lib/chunk-5S6VFBLT.mjs.map +1 -0
- package/lib/{chunk-MVQWAIMC.mjs → chunk-6BB4CRSS.mjs} +3 -312
- package/lib/chunk-6BB4CRSS.mjs.map +1 -0
- package/lib/{chunk-WPCBVDFZ.mjs → chunk-76UM2LQ5.mjs} +2 -2
- package/lib/{chunk-QFHYTCVY.mjs → chunk-7TRO2STL.mjs} +7 -7
- package/lib/chunk-BUAYVN3C.mjs +87 -0
- package/lib/chunk-BUAYVN3C.mjs.map +1 -0
- package/lib/{chunk-23PUSHBV.mjs → chunk-D2Y6DDOC.mjs} +2 -2
- package/lib/chunk-DWSWCUZR.mjs +123 -0
- package/lib/chunk-DWSWCUZR.mjs.map +1 -0
- package/lib/{chunk-VZCPGQXA.mjs → chunk-EUIP2U5F.mjs} +69 -1
- package/lib/{chunk-VZCPGQXA.mjs.map → chunk-EUIP2U5F.mjs.map} +1 -1
- package/lib/chunk-GJTPXJKD.mjs +46 -0
- package/lib/chunk-GJTPXJKD.mjs.map +1 -0
- package/lib/chunk-I6LUPJUY.mjs +61 -0
- package/lib/chunk-I6LUPJUY.mjs.map +1 -0
- package/lib/{chunk-KR2Y2CVQ.mjs → chunk-KA3OMP3X.mjs} +2 -2
- package/lib/{chunk-ZM4GDHHC.mjs → chunk-KMEWULMX.mjs} +51 -3
- package/lib/chunk-KMEWULMX.mjs.map +1 -0
- package/lib/chunk-LKKLO66E.mjs +25 -0
- package/lib/chunk-LKKLO66E.mjs.map +1 -0
- package/lib/{chunk-CFJDATDK.mjs → chunk-MLFMW5IF.mjs} +43 -9
- package/lib/chunk-MLFMW5IF.mjs.map +1 -0
- package/lib/chunk-O5VQWB6U.mjs +315 -0
- package/lib/chunk-O5VQWB6U.mjs.map +1 -0
- package/lib/{chunk-7BQHLC7U.mjs → chunk-P3CTZWC2.mjs} +8 -40
- package/lib/chunk-P3CTZWC2.mjs.map +1 -0
- package/lib/{chunk-EFB5OFM7.mjs → chunk-P3NFCKTZ.mjs} +6 -4
- package/lib/{chunk-EFB5OFM7.mjs.map → chunk-P3NFCKTZ.mjs.map} +1 -1
- package/lib/{chunk-M7Y3BOQW.mjs → chunk-Q3MKITPY.mjs} +5 -5
- package/lib/chunk-Q64MOYJ7.mjs +218 -0
- package/lib/chunk-Q64MOYJ7.mjs.map +1 -0
- package/lib/chunk-RQKJNMX5.mjs +89 -0
- package/lib/chunk-RQKJNMX5.mjs.map +1 -0
- package/lib/{chunk-ZWSGM6PZ.mjs → chunk-SD7J3N3C.mjs} +2 -2
- package/lib/{chunk-7RZHFI77.mjs → chunk-VESULYQQ.mjs} +2 -2
- package/lib/{chunk-AOSEKL7U.mjs → chunk-WOTU36P3.mjs} +6 -103
- package/lib/chunk-WOTU36P3.mjs.map +1 -0
- package/lib/{chunk-X5E4YJGZ.mjs → chunk-YPTJJ35S.mjs} +2 -2
- package/lib/counter-apply-operation-DZM3MIDm.d.mts +63 -0
- package/lib/counter-apply-operation-DZM3MIDm.d.ts +63 -0
- package/lib/counter-maintenance.handler.d.mts +38 -0
- package/lib/counter-maintenance.handler.d.ts +38 -0
- package/lib/counter-maintenance.handler.js +2885 -0
- package/lib/counter-maintenance.handler.js.map +1 -0
- package/lib/counter-maintenance.handler.mjs +180 -0
- package/lib/counter-maintenance.handler.mjs.map +1 -0
- package/lib/counter-reconciliation.handler.d.mts +116 -0
- package/lib/counter-reconciliation.handler.d.ts +116 -0
- package/lib/counter-reconciliation.handler.js +3324 -0
- package/lib/counter-reconciliation.handler.js.map +1 -0
- package/lib/counter-reconciliation.handler.mjs +295 -0
- package/lib/counter-reconciliation.handler.mjs.map +1 -0
- package/lib/data-store-postgres-replication.handler.js +50 -2
- package/lib/data-store-postgres-replication.handler.js.map +1 -1
- package/lib/data-store-postgres-replication.handler.mjs +2 -2
- package/lib/delete-chunk.handler.js +118 -2
- package/lib/delete-chunk.handler.js.map +1 -1
- package/lib/delete-chunk.handler.mjs +3 -3
- package/lib/finalize.handler.js +50 -2
- package/lib/finalize.handler.js.map +1 -1
- package/lib/finalize.handler.mjs +4 -4
- package/lib/firehose-archive-transform.handler.js +50 -2
- package/lib/firehose-archive-transform.handler.js.map +1 -1
- package/lib/firehose-archive-transform.handler.mjs +2 -2
- package/lib/index.d.mts +140 -2
- package/lib/index.d.ts +143 -5
- package/lib/index.js +493 -196
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +360 -193
- package/lib/index.mjs.map +1 -1
- package/lib/list-chunks.handler.js +118 -2
- package/lib/list-chunks.handler.js.map +1 -1
- package/lib/list-chunks.handler.mjs +3 -3
- package/lib/platform-deploy-bridge.handler.js +50 -2
- package/lib/platform-deploy-bridge.handler.js.map +1 -1
- package/lib/platform-deploy-bridge.handler.mjs +1 -1
- package/lib/pre-token-generation.handler.js +68 -0
- package/lib/pre-token-generation.handler.js.map +1 -1
- package/lib/pre-token-generation.handler.mjs +9 -5
- package/lib/pre-token-generation.handler.mjs.map +1 -1
- package/lib/provision-default-workspace.handler.js +883 -0
- package/lib/provision-default-workspace.handler.js.map +1 -1
- package/lib/provision-default-workspace.handler.mjs +10 -5
- package/lib/provision-default-workspace.handler.mjs.map +1 -1
- package/lib/rename-finalize.handler.js +50 -2
- package/lib/rename-finalize.handler.js.map +1 -1
- package/lib/rename-finalize.handler.mjs +2 -2
- package/lib/rename-list-targets.handler.js +118 -2
- package/lib/rename-list-targets.handler.js.map +1 -1
- package/lib/rename-list-targets.handler.mjs +11 -9
- package/lib/rename-list-targets.handler.mjs.map +1 -1
- package/lib/rename-rewrite-chunk.handler.js +68 -0
- package/lib/rename-rewrite-chunk.handler.js.map +1 -1
- package/lib/rename-rewrite-chunk.handler.mjs +2 -2
- package/lib/rest-api-lambda.handler.js +1454 -251
- package/lib/rest-api-lambda.handler.js.map +1 -1
- package/lib/rest-api-lambda.handler.mjs +415 -291
- package/lib/rest-api-lambda.handler.mjs.map +1 -1
- package/lib/seed-demo-data.handler.js +205 -8
- package/lib/seed-demo-data.handler.js.map +1 -1
- package/lib/seed-demo-data.handler.mjs +10 -7
- package/lib/seed-system-data.handler.js +118 -2
- package/lib/seed-system-data.handler.js.map +1 -1
- package/lib/seed-system-data.handler.mjs +5 -5
- package/package.json +1 -1
- package/lib/chunk-7BQHLC7U.mjs.map +0 -1
- package/lib/chunk-AOSEKL7U.mjs.map +0 -1
- package/lib/chunk-CFJDATDK.mjs.map +0 -1
- package/lib/chunk-HQ67J7BP.mjs.map +0 -1
- package/lib/chunk-MVQWAIMC.mjs.map +0 -1
- package/lib/chunk-ZM4GDHHC.mjs.map +0 -1
- /package/lib/{chunk-WPCBVDFZ.mjs.map → chunk-76UM2LQ5.mjs.map} +0 -0
- /package/lib/{chunk-QFHYTCVY.mjs.map → chunk-7TRO2STL.mjs.map} +0 -0
- /package/lib/{chunk-23PUSHBV.mjs.map → chunk-D2Y6DDOC.mjs.map} +0 -0
- /package/lib/{chunk-KR2Y2CVQ.mjs.map → chunk-KA3OMP3X.mjs.map} +0 -0
- /package/lib/{chunk-M7Y3BOQW.mjs.map → chunk-Q3MKITPY.mjs.map} +0 -0
- /package/lib/{chunk-ZWSGM6PZ.mjs.map → chunk-SD7J3N3C.mjs.map} +0 -0
- /package/lib/{chunk-7RZHFI77.mjs.map → chunk-VESULYQQ.mjs.map} +0 -0
- /package/lib/{chunk-X5E4YJGZ.mjs.map → chunk-YPTJJ35S.mjs.map} +0 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import {
|
|
2
|
+
COUNTER_TARGET,
|
|
3
|
+
isAdminRoleAssignment
|
|
4
|
+
} from "./chunk-RQKJNMX5.mjs";
|
|
5
|
+
import {
|
|
6
|
+
countMembershipsByUserOperation,
|
|
7
|
+
listTenantsOperation,
|
|
8
|
+
listWorkspacesOperation,
|
|
9
|
+
membershipListByWorkspaceOperation,
|
|
10
|
+
roleAssignmentListByWorkspaceOperation
|
|
11
|
+
} from "./chunk-Q64MOYJ7.mjs";
|
|
12
|
+
import {
|
|
13
|
+
listMembershipsOperation
|
|
14
|
+
} from "./chunk-GJTPXJKD.mjs";
|
|
15
|
+
import {
|
|
16
|
+
extractRoleLevel
|
|
17
|
+
} from "./chunk-BUAYVN3C.mjs";
|
|
18
|
+
import {
|
|
19
|
+
extractReferenceSlug
|
|
20
|
+
} from "./chunk-I6LUPJUY.mjs";
|
|
21
|
+
import {
|
|
22
|
+
listUsersOperation
|
|
23
|
+
} from "./chunk-DWSWCUZR.mjs";
|
|
24
|
+
import "./chunk-O5VQWB6U.mjs";
|
|
25
|
+
import "./chunk-FYHBHHWK.mjs";
|
|
26
|
+
import {
|
|
27
|
+
getDynamoControlService
|
|
28
|
+
} from "./chunk-EUIP2U5F.mjs";
|
|
29
|
+
import "./chunk-TRY7JGWO.mjs";
|
|
30
|
+
import "./chunk-KMEWULMX.mjs";
|
|
31
|
+
import "./chunk-LZOMFHX3.mjs";
|
|
32
|
+
|
|
33
|
+
// src/data/operations/control/counters/counter-reconcile-operation.ts
|
|
34
|
+
function counterValue(value) {
|
|
35
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
36
|
+
}
|
|
37
|
+
function reconcileContext(tenantId) {
|
|
38
|
+
return {
|
|
39
|
+
tenantId,
|
|
40
|
+
workspaceId: "",
|
|
41
|
+
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
42
|
+
actorId: "counter-reconciliation",
|
|
43
|
+
actorName: "Counter Reconciliation Job",
|
|
44
|
+
actorType: "internal-system",
|
|
45
|
+
source: "step-function"
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async function reconcileTenantCountersOperation(params) {
|
|
49
|
+
const { tenantId, tableName } = params;
|
|
50
|
+
const service = getDynamoControlService(tableName);
|
|
51
|
+
const context = reconcileContext(tenantId);
|
|
52
|
+
const workspacesResult = await listWorkspacesOperation({
|
|
53
|
+
context,
|
|
54
|
+
tableName,
|
|
55
|
+
mode: "count"
|
|
56
|
+
});
|
|
57
|
+
const workspacesInTenant = workspacesResult.total;
|
|
58
|
+
const memberships = await listMembershipsOperation({
|
|
59
|
+
context,
|
|
60
|
+
tableName,
|
|
61
|
+
mode: "full"
|
|
62
|
+
});
|
|
63
|
+
let usersInTenant = 0;
|
|
64
|
+
for (const entry of memberships.entries) {
|
|
65
|
+
const workspaceSlug = extractReferenceSlug(entry.resource, "workspace");
|
|
66
|
+
if (workspaceSlug === void 0) {
|
|
67
|
+
usersInTenant += 1;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const current = await service.entities.tenant.get({ tenantId, sk: "CURRENT" }).go();
|
|
71
|
+
const drift = [];
|
|
72
|
+
const recomputed = {
|
|
73
|
+
usersInTenant,
|
|
74
|
+
workspacesInTenant
|
|
75
|
+
};
|
|
76
|
+
for (const counter of Object.keys(recomputed)) {
|
|
77
|
+
const oldValue = counterValue(current.data?.[counter]);
|
|
78
|
+
const newValue = recomputed[counter];
|
|
79
|
+
if (oldValue !== newValue) {
|
|
80
|
+
drift.push({
|
|
81
|
+
target: COUNTER_TARGET.Tenant,
|
|
82
|
+
id: tenantId,
|
|
83
|
+
counter,
|
|
84
|
+
old: oldValue,
|
|
85
|
+
new: newValue
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (drift.length > 0) {
|
|
90
|
+
await service.entities.tenant.patch({ tenantId, sk: "CURRENT" }).set(recomputed).go();
|
|
91
|
+
}
|
|
92
|
+
return { drift };
|
|
93
|
+
}
|
|
94
|
+
async function reconcileWorkspaceCountersOperation(params) {
|
|
95
|
+
const { tenantId, workspaceId, tableName } = params;
|
|
96
|
+
const service = getDynamoControlService(tableName);
|
|
97
|
+
let usersInWorkspace = 0;
|
|
98
|
+
let membershipCursor = null;
|
|
99
|
+
do {
|
|
100
|
+
const page = await membershipListByWorkspaceOperation({
|
|
101
|
+
tenantId,
|
|
102
|
+
workspaceId,
|
|
103
|
+
cursor: membershipCursor,
|
|
104
|
+
tableName
|
|
105
|
+
});
|
|
106
|
+
usersInWorkspace += page.items.length;
|
|
107
|
+
membershipCursor = page.cursor;
|
|
108
|
+
} while (membershipCursor !== null);
|
|
109
|
+
let adminUsersInWorkspace = 0;
|
|
110
|
+
let normalUsersInWorkspace = 0;
|
|
111
|
+
let roleAssignmentCursor = null;
|
|
112
|
+
do {
|
|
113
|
+
const page = await roleAssignmentListByWorkspaceOperation({
|
|
114
|
+
tenantId,
|
|
115
|
+
workspaceId,
|
|
116
|
+
cursor: roleAssignmentCursor,
|
|
117
|
+
tableName
|
|
118
|
+
});
|
|
119
|
+
for (const item of page.items) {
|
|
120
|
+
const roleLevel = await readRoleLevel(
|
|
121
|
+
service,
|
|
122
|
+
tenantId,
|
|
123
|
+
item.roleAssignmentId
|
|
124
|
+
);
|
|
125
|
+
if (isAdminRoleAssignment({ roleLevel, roleId: item.roleId })) {
|
|
126
|
+
adminUsersInWorkspace += 1;
|
|
127
|
+
} else {
|
|
128
|
+
normalUsersInWorkspace += 1;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
roleAssignmentCursor = page.cursor;
|
|
132
|
+
} while (roleAssignmentCursor !== null);
|
|
133
|
+
const current = await service.entities.workspace.get({ tenantId, id: workspaceId, sk: "CURRENT" }).go();
|
|
134
|
+
const drift = [];
|
|
135
|
+
const recomputed = {
|
|
136
|
+
usersInWorkspace,
|
|
137
|
+
adminUsersInWorkspace,
|
|
138
|
+
normalUsersInWorkspace
|
|
139
|
+
};
|
|
140
|
+
for (const counter of Object.keys(recomputed)) {
|
|
141
|
+
const oldValue = counterValue(current.data?.[counter]);
|
|
142
|
+
const newValue = recomputed[counter];
|
|
143
|
+
if (oldValue !== newValue) {
|
|
144
|
+
drift.push({
|
|
145
|
+
target: COUNTER_TARGET.Workspace,
|
|
146
|
+
id: workspaceId,
|
|
147
|
+
tenantId,
|
|
148
|
+
counter,
|
|
149
|
+
old: oldValue,
|
|
150
|
+
new: newValue
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (drift.length > 0) {
|
|
155
|
+
await service.entities.workspace.patch({ tenantId, id: workspaceId, sk: "CURRENT" }).set(recomputed).go();
|
|
156
|
+
}
|
|
157
|
+
return { drift };
|
|
158
|
+
}
|
|
159
|
+
async function reconcileUserCountersOperation(params) {
|
|
160
|
+
const { userId, tableName } = params;
|
|
161
|
+
const service = getDynamoControlService(tableName);
|
|
162
|
+
const tenantsForUser = await countMembershipsByUserOperation({
|
|
163
|
+
userId,
|
|
164
|
+
mode: "tenant",
|
|
165
|
+
tableName
|
|
166
|
+
});
|
|
167
|
+
const workspacesForUser = await countMembershipsByUserOperation({
|
|
168
|
+
userId,
|
|
169
|
+
mode: "workspace",
|
|
170
|
+
tableName
|
|
171
|
+
});
|
|
172
|
+
const current = await service.entities.user.get({ id: userId, sk: "CURRENT" }).go();
|
|
173
|
+
const drift = [];
|
|
174
|
+
const recomputed = {
|
|
175
|
+
tenantsForUser,
|
|
176
|
+
workspacesForUser
|
|
177
|
+
};
|
|
178
|
+
for (const counter of Object.keys(recomputed)) {
|
|
179
|
+
const oldValue = counterValue(current.data?.[counter]);
|
|
180
|
+
const newValue = recomputed[counter];
|
|
181
|
+
if (oldValue !== newValue) {
|
|
182
|
+
drift.push({
|
|
183
|
+
target: COUNTER_TARGET.User,
|
|
184
|
+
id: userId,
|
|
185
|
+
counter,
|
|
186
|
+
old: oldValue,
|
|
187
|
+
new: newValue
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (drift.length > 0) {
|
|
192
|
+
await service.entities.user.patch({ id: userId, sk: "CURRENT" }).set(recomputed).go();
|
|
193
|
+
}
|
|
194
|
+
return { drift };
|
|
195
|
+
}
|
|
196
|
+
async function readRoleLevel(service, tenantId, roleAssignmentId) {
|
|
197
|
+
const response = await service.entities.roleAssignment.get({ tenantId, id: roleAssignmentId, sk: "CURRENT" }).go();
|
|
198
|
+
if (!response.data) {
|
|
199
|
+
return void 0;
|
|
200
|
+
}
|
|
201
|
+
const resource = JSON.parse(response.data.resource);
|
|
202
|
+
return extractRoleLevel(resource);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// src/data/operations/control/counters/counter-reconcile-driver.ts
|
|
206
|
+
function driverContext(tenantId) {
|
|
207
|
+
return {
|
|
208
|
+
tenantId,
|
|
209
|
+
workspaceId: "",
|
|
210
|
+
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
211
|
+
actorId: "counter-reconciliation",
|
|
212
|
+
actorName: "Counter Reconciliation Job",
|
|
213
|
+
actorType: "internal-system",
|
|
214
|
+
source: "step-function"
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
async function reconcileAllCountersOperation(params = {}) {
|
|
218
|
+
const { tableName } = params;
|
|
219
|
+
const drift = [];
|
|
220
|
+
let tenantsScanned = 0;
|
|
221
|
+
let workspacesScanned = 0;
|
|
222
|
+
let usersScanned = 0;
|
|
223
|
+
const tenants = await listTenantsOperation({
|
|
224
|
+
context: driverContext(""),
|
|
225
|
+
tableName,
|
|
226
|
+
mode: "summary"
|
|
227
|
+
});
|
|
228
|
+
for (const tenant of tenants.entries) {
|
|
229
|
+
tenantsScanned += 1;
|
|
230
|
+
const tenantResult = await reconcileTenantCountersOperation({
|
|
231
|
+
tenantId: tenant.id,
|
|
232
|
+
tableName
|
|
233
|
+
});
|
|
234
|
+
drift.push(...tenantResult.drift);
|
|
235
|
+
const workspaces = await listWorkspacesOperation({
|
|
236
|
+
context: driverContext(tenant.id),
|
|
237
|
+
tableName,
|
|
238
|
+
mode: "summary"
|
|
239
|
+
});
|
|
240
|
+
for (const workspace of workspaces.entries) {
|
|
241
|
+
workspacesScanned += 1;
|
|
242
|
+
const workspaceResult = await reconcileWorkspaceCountersOperation({
|
|
243
|
+
tenantId: tenant.id,
|
|
244
|
+
workspaceId: workspace.id,
|
|
245
|
+
tableName
|
|
246
|
+
});
|
|
247
|
+
drift.push(...workspaceResult.drift);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
const users = await listUsersOperation({
|
|
251
|
+
context: driverContext(""),
|
|
252
|
+
tableName,
|
|
253
|
+
mode: "summary"
|
|
254
|
+
});
|
|
255
|
+
for (const user of users.entries) {
|
|
256
|
+
usersScanned += 1;
|
|
257
|
+
const userResult = await reconcileUserCountersOperation({
|
|
258
|
+
userId: user.id,
|
|
259
|
+
tableName
|
|
260
|
+
});
|
|
261
|
+
drift.push(...userResult.drift);
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
drift,
|
|
265
|
+
scanned: {
|
|
266
|
+
tenants: tenantsScanned,
|
|
267
|
+
workspaces: workspacesScanned,
|
|
268
|
+
users: usersScanned
|
|
269
|
+
},
|
|
270
|
+
countersCorrected: drift.length
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// src/workflows/control-plane/counter-reconciliation/counter-reconciliation.handler.ts
|
|
275
|
+
var runCounterReconciliation = async (deps) => {
|
|
276
|
+
const report = await deps.reconcileAll();
|
|
277
|
+
console.log(
|
|
278
|
+
JSON.stringify({
|
|
279
|
+
message: "counter-reconciliation complete",
|
|
280
|
+
scanned: report.scanned,
|
|
281
|
+
countersCorrected: report.countersCorrected,
|
|
282
|
+
drift: report.drift
|
|
283
|
+
})
|
|
284
|
+
);
|
|
285
|
+
return report;
|
|
286
|
+
};
|
|
287
|
+
var productionDependencies = () => ({
|
|
288
|
+
reconcileAll: () => reconcileAllCountersOperation()
|
|
289
|
+
});
|
|
290
|
+
var handler = async () => runCounterReconciliation(productionDependencies());
|
|
291
|
+
export {
|
|
292
|
+
handler,
|
|
293
|
+
runCounterReconciliation
|
|
294
|
+
};
|
|
295
|
+
//# sourceMappingURL=counter-reconciliation.handler.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/data/operations/control/counters/counter-reconcile-operation.ts","../src/data/operations/control/counters/counter-reconcile-driver.ts","../src/workflows/control-plane/counter-reconciliation/counter-reconciliation.handler.ts"],"sourcesContent":["import {\n COUNTER_TARGET,\n type CounterTarget,\n type TenantCounter,\n type UserCounter,\n type WorkspaceCounter,\n} from \"./counter-apply-operation\";\nimport { isAdminRoleAssignment } from \"./role-admin-classification\";\nimport { getDynamoControlService } from \"../../../dynamo/dynamo-control-service\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport { extractRoleLevel } from \"../control-event-publisher\";\nimport { countMembershipsByUserOperation } from \"../membership/membership-count-by-user-operation\";\nimport { membershipListByWorkspaceOperation } from \"../membership/membership-list-by-workspace-operation\";\nimport { listMembershipsOperation } from \"../membership/membership-list-operation\";\nimport { extractReferenceSlug } from \"../membership/membership-user-projection\";\nimport { roleAssignmentListByWorkspaceOperation } from \"../roleassignment/roleassignment-list-by-workspace-operation\";\nimport { listWorkspacesOperation } from \"../workspace/workspace-list-operation\";\n\n/**\n * ADR-028 counter reconciliation — recompute the denormalized\n * control-plane counters from canonical data and repair drift.\n *\n * The atomic-ADD path ({@link applyCounterDeltaOperation}) maintains the\n * counters incrementally off domain events, but events can be missed,\n * replayed, or arrive after a record was created without one (rows that\n * predate the counter work). This operation is the correctness backstop\n * ADR-028 names: it ignores the current counter value, recomputes the\n * true value from canonical records, and writes the absolute recomputed\n * value back with a DynamoDB `SET` (not `ADD`). A `SET` repairs both\n * directions of drift and backfills an absent / `0` attribute to its\n * correct value in one write.\n *\n * Counter semantics recomputed here MUST match {@link counterEventRouter}:\n *\n * - `Tenant.usersInTenant` = # tenant-scoped Memberships in the tenant\n * (membership with NO workspace reference).\n * - `Tenant.workspacesInTenant` = # Workspaces in the tenant.\n * - `Workspace.usersInWorkspace` = # workspace-scoped Memberships for the workspace.\n * - `Workspace.adminUsersInWorkspace` / `normalUsersInWorkspace` =\n * # workspace-scoped RoleAssignments for the workspace, bucketed by\n * {@link isAdminRoleAssignment} on the assignment's role level / role id.\n * - `User.tenantsForUser` = # tenant-scoped Memberships for the user.\n * - `User.workspacesForUser` = # workspace-scoped Memberships for the user.\n *\n * @see counter-apply-operation.ts — the incremental ADD path this reconciles against.\n * @see counter-event-router.ts — the event → counter semantics this mirrors.\n */\n\n/** One counter's old → new transition, recorded only when `old !== new`. */\nexport interface CounterDriftEntry {\n /** Which canonical entity the counter lives on. */\n readonly target: CounterTarget;\n /** Identity of the canonical record (tenantId for Tenant, workspaceId for Workspace, userId for User). */\n readonly id: string;\n /** Tenant the record belongs to (Workspace only; omitted for Tenant / User). */\n readonly tenantId?: string;\n /** The counter attribute name. */\n readonly counter: string;\n /** The value found on the record before reconciliation (0 when the attribute was absent). */\n readonly old: number;\n /** The recomputed-from-canonical value written back. */\n readonly new: number;\n}\n\n/** Result of reconciling one target record. */\nexport interface CounterReconcileResult {\n /** Every counter whose value changed (empty when the record was already correct). */\n readonly drift: Array<CounterDriftEntry>;\n}\n\n/** Coerce a possibly-absent counter attribute to a non-negative number (default 0). */\nfunction counterValue(value: unknown): number {\n return typeof value === \"number\" && Number.isFinite(value) ? value : 0;\n}\n\n/** Minimal actor context the underlying list operations need (they read only `tenantId`). */\nfunction reconcileContext(tenantId: string): OpenHiContext {\n return {\n tenantId,\n workspaceId: \"\",\n date: new Date().toISOString(),\n actorId: \"counter-reconciliation\",\n actorName: \"Counter Reconciliation Job\",\n actorType: \"internal-system\",\n source: \"step-function\",\n };\n}\n\n/**\n * Recompute and repair the two counters on one Tenant record.\n *\n * - `workspacesInTenant` is the workspace count from\n * {@link listWorkspacesOperation} (`mode: \"count\"`, GSI1 fan-out).\n * - `usersInTenant` is the number of *tenant-scoped* Memberships in the\n * tenant. Memberships have no tenant-partition projection, so this\n * enumerates the tenant's canonical Memberships via\n * {@link listMembershipsOperation} (`mode: \"full\"`) and counts the rows\n * whose `resource` carries no `workspace` reference — the same\n * tenant-vs-workspace discriminator the create path uses\n * ({@link extractReferenceSlug} on the `workspace` field).\n */\nexport async function reconcileTenantCountersOperation(params: {\n readonly tenantId: string;\n readonly tableName?: string;\n}): Promise<CounterReconcileResult> {\n const { tenantId, tableName } = params;\n const service = getDynamoControlService(tableName);\n const context = reconcileContext(tenantId);\n\n const workspacesResult = await listWorkspacesOperation({\n context,\n tableName,\n mode: \"count\",\n });\n const workspacesInTenant = workspacesResult.total;\n\n // Full enumeration of the tenant's canonical Memberships; discriminate\n // tenant-scoped (no workspace reference) from workspace-scoped by the\n // resource's `workspace` reference, mirroring the create path.\n const memberships = await listMembershipsOperation({\n context,\n tableName,\n mode: \"full\",\n });\n let usersInTenant = 0;\n for (const entry of memberships.entries) {\n const workspaceSlug = extractReferenceSlug(entry.resource, \"workspace\");\n if (workspaceSlug === undefined) {\n usersInTenant += 1;\n }\n }\n\n const current = await service.entities.tenant\n .get({ tenantId, sk: \"CURRENT\" })\n .go();\n\n const drift: Array<CounterDriftEntry> = [];\n const recomputed: Record<TenantCounter, number> = {\n usersInTenant,\n workspacesInTenant,\n };\n\n for (const counter of Object.keys(recomputed) as Array<TenantCounter>) {\n const oldValue = counterValue(current.data?.[counter]);\n const newValue = recomputed[counter];\n if (oldValue !== newValue) {\n drift.push({\n target: COUNTER_TARGET.Tenant,\n id: tenantId,\n counter,\n old: oldValue,\n new: newValue,\n });\n }\n }\n\n if (drift.length > 0) {\n await service.entities.tenant\n .patch({ tenantId, sk: \"CURRENT\" })\n .set(recomputed)\n .go();\n }\n\n return { drift };\n}\n\n/**\n * Recompute and repair the three counters on one Workspace record.\n *\n * - `usersInWorkspace` pages every workspace-scoped Membership via\n * {@link membershipListByWorkspaceOperation} (ADR-018 pattern #2).\n * - `adminUsersInWorkspace` / `normalUsersInWorkspace` page every\n * workspace-scoped RoleAssignment via\n * {@link roleAssignmentListByWorkspaceOperation} (pattern #9), then\n * classify each with {@link isAdminRoleAssignment}. The projection row\n * does not carry the ADR-019 role level (its `summary` is the\n * id/displayName/status projection), so each assignment's canonical\n * RoleAssignment resource is read to extract the role level via\n * {@link extractRoleLevel} — the same signal the create path publishes.\n * The projection's `roleId` is passed alongside as the fallback signal.\n */\nexport async function reconcileWorkspaceCountersOperation(params: {\n readonly tenantId: string;\n readonly workspaceId: string;\n readonly tableName?: string;\n}): Promise<CounterReconcileResult> {\n const { tenantId, workspaceId, tableName } = params;\n const service = getDynamoControlService(tableName);\n\n // usersInWorkspace — page every workspace-scoped membership.\n let usersInWorkspace = 0;\n let membershipCursor: string | null = null;\n do {\n const page = await membershipListByWorkspaceOperation({\n tenantId,\n workspaceId,\n cursor: membershipCursor,\n tableName,\n });\n usersInWorkspace += page.items.length;\n membershipCursor = page.cursor;\n } while (membershipCursor !== null);\n\n // admin/normal — page every workspace-scoped role assignment, then read\n // each canonical RoleAssignment to recover the role level for the\n // admin/normal split (the projection summary does not carry it).\n let adminUsersInWorkspace = 0;\n let normalUsersInWorkspace = 0;\n let roleAssignmentCursor: string | null = null;\n do {\n const page = await roleAssignmentListByWorkspaceOperation({\n tenantId,\n workspaceId,\n cursor: roleAssignmentCursor,\n tableName,\n });\n for (const item of page.items) {\n const roleLevel = await readRoleLevel(\n service,\n tenantId,\n item.roleAssignmentId,\n );\n if (isAdminRoleAssignment({ roleLevel, roleId: item.roleId })) {\n adminUsersInWorkspace += 1;\n } else {\n normalUsersInWorkspace += 1;\n }\n }\n roleAssignmentCursor = page.cursor;\n } while (roleAssignmentCursor !== null);\n\n const current = await service.entities.workspace\n .get({ tenantId, id: workspaceId, sk: \"CURRENT\" })\n .go();\n\n const drift: Array<CounterDriftEntry> = [];\n const recomputed: Record<WorkspaceCounter, number> = {\n usersInWorkspace,\n adminUsersInWorkspace,\n normalUsersInWorkspace,\n };\n\n for (const counter of Object.keys(recomputed) as Array<WorkspaceCounter>) {\n const oldValue = counterValue(current.data?.[counter]);\n const newValue = recomputed[counter];\n if (oldValue !== newValue) {\n drift.push({\n target: COUNTER_TARGET.Workspace,\n id: workspaceId,\n tenantId,\n counter,\n old: oldValue,\n new: newValue,\n });\n }\n }\n\n if (drift.length > 0) {\n await service.entities.workspace\n .patch({ tenantId, id: workspaceId, sk: \"CURRENT\" })\n .set(recomputed)\n .go();\n }\n\n return { drift };\n}\n\n/**\n * Recompute and repair the two counters on one User record.\n *\n * Both derive from {@link countMembershipsByUserOperation} over the\n * ADR-018 user-partition projection lanes: `tenantsForUser` from the\n * `tenant` lane (pattern #3), `workspacesForUser` from the `workspace`\n * lane (pattern #4).\n */\nexport async function reconcileUserCountersOperation(params: {\n readonly userId: string;\n readonly tableName?: string;\n}): Promise<CounterReconcileResult> {\n const { userId, tableName } = params;\n const service = getDynamoControlService(tableName);\n\n const tenantsForUser = await countMembershipsByUserOperation({\n userId,\n mode: \"tenant\",\n tableName,\n });\n const workspacesForUser = await countMembershipsByUserOperation({\n userId,\n mode: \"workspace\",\n tableName,\n });\n\n const current = await service.entities.user\n .get({ id: userId, sk: \"CURRENT\" })\n .go();\n\n const drift: Array<CounterDriftEntry> = [];\n const recomputed: Record<UserCounter, number> = {\n tenantsForUser,\n workspacesForUser,\n };\n\n for (const counter of Object.keys(recomputed) as Array<UserCounter>) {\n const oldValue = counterValue(current.data?.[counter]);\n const newValue = recomputed[counter];\n if (oldValue !== newValue) {\n drift.push({\n target: COUNTER_TARGET.User,\n id: userId,\n counter,\n old: oldValue,\n new: newValue,\n });\n }\n }\n\n if (drift.length > 0) {\n await service.entities.user\n .patch({ id: userId, sk: \"CURRENT\" })\n .set(recomputed)\n .go();\n }\n\n return { drift };\n}\n\n/**\n * Read the ADR-019 role level off a canonical RoleAssignment so the\n * admin/normal split classifies the same way the create path published\n * it. Returns `undefined` when the record or its code is missing — the\n * classifier then falls back to the `roleId` signal.\n */\nasync function readRoleLevel(\n service: ReturnType<typeof getDynamoControlService>,\n tenantId: string,\n roleAssignmentId: string,\n): Promise<string | undefined> {\n const response = await service.entities.roleAssignment\n .get({ tenantId, id: roleAssignmentId, sk: \"CURRENT\" })\n .go();\n if (!response.data) {\n return undefined;\n }\n const resource = JSON.parse(response.data.resource) as Record<\n string,\n unknown\n >;\n return extractRoleLevel(resource);\n}\n","import {\n type CounterDriftEntry,\n reconcileTenantCountersOperation,\n reconcileUserCountersOperation,\n reconcileWorkspaceCountersOperation,\n} from \"./counter-reconcile-operation\";\nimport type { OpenHiContext } from \"../../../openhi-context\";\nimport { listTenantsOperation } from \"../tenant/tenant-list-operation\";\nimport { listUsersOperation } from \"../user/user-list-operation\";\nimport { listWorkspacesOperation } from \"../workspace/workspace-list-operation\";\n\n/**\n * ADR-028 counter-reconciliation driver — walks every canonical Tenant,\n * Workspace, and User, reconciles each record's denormalized counters\n * against canonical data, and accumulates a single drift report.\n *\n * Enumeration reuses the existing GSI1-sharded list operations\n * (`summary` mode — ids only, no per-record BatchGet hydration):\n *\n * - All Tenants via {@link listTenantsOperation}.\n * - Per tenant, all Workspaces in that tenant via\n * {@link listWorkspacesOperation} (the workspace GSI1 partition is\n * tenant-scoped).\n * - All Users via {@link listUsersOperation}.\n *\n * Each record is then handed to the matching per-target recompute\n * ({@link reconcileTenantCountersOperation},\n * {@link reconcileWorkspaceCountersOperation},\n * {@link reconcileUserCountersOperation}), which owns the SET-back repair\n * and returns the per-counter old → new drift it corrected.\n *\n * @see counter-reconcile-operation.ts — the per-target recompute + repair.\n */\n\n/** Totals summarizing one reconciliation run, alongside the per-counter drift list. */\nexport interface CounterReconcileReport {\n /** Every counter that changed across every record, in walk order. */\n readonly drift: Array<CounterDriftEntry>;\n /** How many canonical records of each kind were scanned. */\n readonly scanned: {\n readonly tenants: number;\n readonly workspaces: number;\n readonly users: number;\n };\n /** Total number of individual counters corrected (== `drift.length`). */\n readonly countersCorrected: number;\n}\n\n/** Minimal actor context the list operations need (they read only `tenantId`). */\nfunction driverContext(tenantId: string): OpenHiContext {\n return {\n tenantId,\n workspaceId: \"\",\n date: new Date().toISOString(),\n actorId: \"counter-reconciliation\",\n actorName: \"Counter Reconciliation Job\",\n actorType: \"internal-system\",\n source: \"step-function\",\n };\n}\n\n/**\n * Run a full reconciliation sweep across every Tenant, Workspace, and\n * User. Returns the accumulated drift report; the per-target operations\n * have already written the repairs by the time this resolves.\n */\nexport async function reconcileAllCountersOperation(\n params: {\n readonly tableName?: string;\n } = {},\n): Promise<CounterReconcileReport> {\n const { tableName } = params;\n const drift: Array<CounterDriftEntry> = [];\n let tenantsScanned = 0;\n let workspacesScanned = 0;\n let usersScanned = 0;\n\n // Tenants (and, per tenant, the tenant's workspaces).\n const tenants = await listTenantsOperation({\n context: driverContext(\"\"),\n tableName,\n mode: \"summary\",\n });\n for (const tenant of tenants.entries) {\n tenantsScanned += 1;\n const tenantResult = await reconcileTenantCountersOperation({\n tenantId: tenant.id,\n tableName,\n });\n drift.push(...tenantResult.drift);\n\n const workspaces = await listWorkspacesOperation({\n context: driverContext(tenant.id),\n tableName,\n mode: \"summary\",\n });\n for (const workspace of workspaces.entries) {\n workspacesScanned += 1;\n const workspaceResult = await reconcileWorkspaceCountersOperation({\n tenantId: tenant.id,\n workspaceId: workspace.id,\n tableName,\n });\n drift.push(...workspaceResult.drift);\n }\n }\n\n // Users (platform-wide, no tenant scope).\n const users = await listUsersOperation({\n context: driverContext(\"\"),\n tableName,\n mode: \"summary\",\n });\n for (const user of users.entries) {\n usersScanned += 1;\n const userResult = await reconcileUserCountersOperation({\n userId: user.id,\n tableName,\n });\n drift.push(...userResult.drift);\n }\n\n return {\n drift,\n scanned: {\n tenants: tenantsScanned,\n workspaces: workspacesScanned,\n users: usersScanned,\n },\n countersCorrected: drift.length,\n };\n}\n","import {\n reconcileAllCountersOperation,\n type CounterReconcileReport,\n} from \"../../../data/operations/control/counters/counter-reconcile-driver\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/constructs/workflows/control-plane/counter-reconciliation/counter-reconciliation-handler.md\n *\n * ADR-028 counter-reconciliation job handler. Invoked on demand (manual\n * `aws lambda invoke`, an operator runbook, or a scheduled trigger) — not\n * an EventBridge consumer. Walks every canonical Tenant / Workspace /\n * User, recomputes the denormalized counters from canonical data, repairs\n * any drift with a `SET` write, and logs the per-counter old → new drift\n * report.\n *\n * Idempotent by construction: each per-target recompute writes the\n * absolute recomputed value, so a second run over unchanged data corrects\n * nothing and reports zero drift. That is why the job needs no dedup\n * circuit-breaker (unlike the event-driven counter-maintenance consumer,\n * whose atomic ADDs are not idempotent).\n */\n\n/** Dependency seam for tests; production wires the real driver. */\nexport interface CounterReconciliationDependencies {\n /**\n * Run the full reconciliation sweep. Defaults to\n * {@link reconcileAllCountersOperation}; tests inject a fake.\n */\n readonly reconcileAll: () => Promise<CounterReconcileReport>;\n}\n\n/**\n * Test-visible orchestrator. The production `handler` calls this with the\n * real driver; unit tests inject a fake. Returns the drift report so an\n * invoker (or test) can assert on what was corrected.\n */\nexport const runCounterReconciliation = async (\n deps: CounterReconciliationDependencies,\n): Promise<CounterReconcileReport> => {\n const report = await deps.reconcileAll();\n\n // Structured, loggable summary. One JSON line so a log query can pluck\n // the totals; the full per-counter drift list rides along for an audit.\n console.log(\n JSON.stringify({\n message: \"counter-reconciliation complete\",\n scanned: report.scanned,\n countersCorrected: report.countersCorrected,\n drift: report.drift,\n }),\n );\n\n return report;\n};\n\nconst productionDependencies = (): CounterReconciliationDependencies => ({\n reconcileAll: () => reconcileAllCountersOperation(),\n});\n\nexport const handler = async (): Promise<CounterReconcileReport> =>\n runCounterReconciliation(productionDependencies());\n"],"mappings":"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","names":[]}
|
|
@@ -139,7 +139,7 @@ var require_control_plane = __commonJS({
|
|
|
139
139
|
"../workflows/lib/detail-types/control-plane.js"(exports2) {
|
|
140
140
|
"use strict";
|
|
141
141
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
142
|
-
exports2.ControlPlaneRenameFailedV1 = exports2.ControlPlaneRenameCompleteV1 = exports2.ControlPlaneRenameV1 = exports2.RENAMABLE_ENTITY_TYPE = exports2.ControlPlaneOwningDeleteFailedV1 = exports2.ControlPlaneOwningDeleteCompleteV1 = exports2.ControlPlaneOwningDeleteV1 = exports2.OWNING_ENTITY_TYPE = void 0;
|
|
142
|
+
exports2.ControlPlaneWorkspaceDeletedV1 = exports2.ControlPlaneWorkspaceCreatedV1 = exports2.ControlPlaneRoleAssignmentDeletedV1 = exports2.ControlPlaneRoleAssignmentCreatedV1 = exports2.ControlPlaneMembershipDeletedV1 = exports2.ControlPlaneMembershipCreatedV1 = exports2.ControlPlaneRenameFailedV1 = exports2.ControlPlaneRenameCompleteV1 = exports2.ControlPlaneRenameV1 = exports2.RENAMABLE_ENTITY_TYPE = exports2.ControlPlaneOwningDeleteFailedV1 = exports2.ControlPlaneOwningDeleteCompleteV1 = exports2.ControlPlaneOwningDeleteV1 = exports2.OWNING_ENTITY_TYPE = void 0;
|
|
143
143
|
var sources_1 = require_sources();
|
|
144
144
|
var registry_1 = require_registry();
|
|
145
145
|
exports2.OWNING_ENTITY_TYPE = {
|
|
@@ -181,6 +181,36 @@ var require_control_plane = __commonJS({
|
|
|
181
181
|
source: sources_1.OPENHI_OPS_SOURCE,
|
|
182
182
|
dedupRequired: true
|
|
183
183
|
});
|
|
184
|
+
exports2.ControlPlaneMembershipCreatedV1 = (0, registry_1.defineDetailType)({
|
|
185
|
+
detailType: "control-plane.membership-created.v1",
|
|
186
|
+
source: sources_1.OPENHI_CONTROL_SOURCE,
|
|
187
|
+
dedupRequired: true
|
|
188
|
+
});
|
|
189
|
+
exports2.ControlPlaneMembershipDeletedV1 = (0, registry_1.defineDetailType)({
|
|
190
|
+
detailType: "control-plane.membership-deleted.v1",
|
|
191
|
+
source: sources_1.OPENHI_CONTROL_SOURCE,
|
|
192
|
+
dedupRequired: true
|
|
193
|
+
});
|
|
194
|
+
exports2.ControlPlaneRoleAssignmentCreatedV1 = (0, registry_1.defineDetailType)({
|
|
195
|
+
detailType: "control-plane.role-assignment-created.v1",
|
|
196
|
+
source: sources_1.OPENHI_CONTROL_SOURCE,
|
|
197
|
+
dedupRequired: true
|
|
198
|
+
});
|
|
199
|
+
exports2.ControlPlaneRoleAssignmentDeletedV1 = (0, registry_1.defineDetailType)({
|
|
200
|
+
detailType: "control-plane.role-assignment-deleted.v1",
|
|
201
|
+
source: sources_1.OPENHI_CONTROL_SOURCE,
|
|
202
|
+
dedupRequired: true
|
|
203
|
+
});
|
|
204
|
+
exports2.ControlPlaneWorkspaceCreatedV1 = (0, registry_1.defineDetailType)({
|
|
205
|
+
detailType: "control-plane.workspace-created.v1",
|
|
206
|
+
source: sources_1.OPENHI_CONTROL_SOURCE,
|
|
207
|
+
dedupRequired: true
|
|
208
|
+
});
|
|
209
|
+
exports2.ControlPlaneWorkspaceDeletedV1 = (0, registry_1.defineDetailType)({
|
|
210
|
+
detailType: "control-plane.workspace-deleted.v1",
|
|
211
|
+
source: sources_1.OPENHI_CONTROL_SOURCE,
|
|
212
|
+
dedupRequired: true
|
|
213
|
+
});
|
|
184
214
|
}
|
|
185
215
|
});
|
|
186
216
|
|
|
@@ -578,7 +608,7 @@ var require_lib = __commonJS({
|
|
|
578
608
|
"../workflows/lib/index.js"(exports2) {
|
|
579
609
|
"use strict";
|
|
580
610
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
581
|
-
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.RENAMABLE_ENTITY_TYPE = exports2.PlatformSystemDataSeededV1 = exports2.PlatformDeploymentCompletedV1 = exports2.OWNING_ENTITY_TYPE = exports2.InvalidDetailTypeRegistrationError = exports2.ControlPlaneRenameV1 = exports2.ControlPlaneRenameFailedV1 = exports2.ControlPlaneRenameCompleteV1 = exports2.ControlPlaneOwningDeleteV1 = exports2.ControlPlaneOwningDeleteFailedV1 = exports2.ControlPlaneOwningDeleteCompleteV1 = 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;
|
|
611
|
+
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.RENAMABLE_ENTITY_TYPE = exports2.PlatformSystemDataSeededV1 = exports2.PlatformDeploymentCompletedV1 = exports2.OWNING_ENTITY_TYPE = exports2.InvalidDetailTypeRegistrationError = exports2.ControlPlaneWorkspaceDeletedV1 = exports2.ControlPlaneWorkspaceCreatedV1 = exports2.ControlPlaneRoleAssignmentDeletedV1 = exports2.ControlPlaneRoleAssignmentCreatedV1 = exports2.ControlPlaneRenameV1 = exports2.ControlPlaneRenameFailedV1 = exports2.ControlPlaneRenameCompleteV1 = exports2.ControlPlaneOwningDeleteV1 = exports2.ControlPlaneOwningDeleteFailedV1 = exports2.ControlPlaneOwningDeleteCompleteV1 = exports2.ControlPlaneMembershipDeletedV1 = exports2.ControlPlaneMembershipCreatedV1 = 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;
|
|
582
612
|
var envelope_version_1 = require_envelope_version();
|
|
583
613
|
Object.defineProperty(exports2, "ENVELOPE_VERSION", { enumerable: true, get: function() {
|
|
584
614
|
return envelope_version_1.ENVELOPE_VERSION;
|
|
@@ -613,6 +643,12 @@ var require_lib = __commonJS({
|
|
|
613
643
|
return sources_1.OPENHI_OPS_SOURCE;
|
|
614
644
|
} });
|
|
615
645
|
var detail_types_1 = require_detail_types();
|
|
646
|
+
Object.defineProperty(exports2, "ControlPlaneMembershipCreatedV1", { enumerable: true, get: function() {
|
|
647
|
+
return detail_types_1.ControlPlaneMembershipCreatedV1;
|
|
648
|
+
} });
|
|
649
|
+
Object.defineProperty(exports2, "ControlPlaneMembershipDeletedV1", { enumerable: true, get: function() {
|
|
650
|
+
return detail_types_1.ControlPlaneMembershipDeletedV1;
|
|
651
|
+
} });
|
|
616
652
|
Object.defineProperty(exports2, "ControlPlaneOwningDeleteCompleteV1", { enumerable: true, get: function() {
|
|
617
653
|
return detail_types_1.ControlPlaneOwningDeleteCompleteV1;
|
|
618
654
|
} });
|
|
@@ -631,6 +667,18 @@ var require_lib = __commonJS({
|
|
|
631
667
|
Object.defineProperty(exports2, "ControlPlaneRenameV1", { enumerable: true, get: function() {
|
|
632
668
|
return detail_types_1.ControlPlaneRenameV1;
|
|
633
669
|
} });
|
|
670
|
+
Object.defineProperty(exports2, "ControlPlaneRoleAssignmentCreatedV1", { enumerable: true, get: function() {
|
|
671
|
+
return detail_types_1.ControlPlaneRoleAssignmentCreatedV1;
|
|
672
|
+
} });
|
|
673
|
+
Object.defineProperty(exports2, "ControlPlaneRoleAssignmentDeletedV1", { enumerable: true, get: function() {
|
|
674
|
+
return detail_types_1.ControlPlaneRoleAssignmentDeletedV1;
|
|
675
|
+
} });
|
|
676
|
+
Object.defineProperty(exports2, "ControlPlaneWorkspaceCreatedV1", { enumerable: true, get: function() {
|
|
677
|
+
return detail_types_1.ControlPlaneWorkspaceCreatedV1;
|
|
678
|
+
} });
|
|
679
|
+
Object.defineProperty(exports2, "ControlPlaneWorkspaceDeletedV1", { enumerable: true, get: function() {
|
|
680
|
+
return detail_types_1.ControlPlaneWorkspaceDeletedV1;
|
|
681
|
+
} });
|
|
634
682
|
Object.defineProperty(exports2, "InvalidDetailTypeRegistrationError", { enumerable: true, get: function() {
|
|
635
683
|
return detail_types_1.InvalidDetailTypeRegistrationError;
|
|
636
684
|
} });
|