@authhero/multi-tenancy 15.3.0 → 15.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/multi-tenancy.cjs +1 -1
  2. package/dist/multi-tenancy.mjs +1366 -621
  3. package/dist/types/inheritance/report.d.ts +6 -2
  4. package/dist/types/inheritance/report.d.ts.map +1 -1
  5. package/dist/types/init.d.ts +57 -2
  6. package/dist/types/init.d.ts.map +1 -1
  7. package/dist/types/middleware/config-sync-mode.d.ts +4 -1
  8. package/dist/types/middleware/config-sync-mode.d.ts.map +1 -1
  9. package/dist/types/operations/detach.d.ts +85 -0
  10. package/dist/types/operations/detach.d.ts.map +1 -0
  11. package/dist/types/operations/index.d.ts +4 -0
  12. package/dist/types/operations/index.d.ts.map +1 -1
  13. package/dist/types/operations/sync-defaults.d.ts +4 -1
  14. package/dist/types/operations/sync-defaults.d.ts.map +1 -1
  15. package/dist/types/operations/tenant-members-request.d.ts +97 -0
  16. package/dist/types/operations/tenant-members-request.d.ts.map +1 -0
  17. package/dist/types/rollout/resolved-sync.d.ts +21 -0
  18. package/dist/types/rollout/resolved-sync.d.ts.map +1 -1
  19. package/dist/types/rollouts/index.d.ts +2 -0
  20. package/dist/types/rollouts/index.d.ts.map +1 -1
  21. package/dist/types/rollouts/status.d.ts +1 -1
  22. package/dist/types/rollouts/status.d.ts.map +1 -1
  23. package/dist/types/rollouts/verify.d.ts +50 -0
  24. package/dist/types/rollouts/verify.d.ts.map +1 -0
  25. package/dist/types/routes/tenants.d.ts.map +1 -1
  26. package/dist/types/types.d.ts +9 -1
  27. package/dist/types/types.d.ts.map +1 -1
  28. package/dist/types/utils/tenant-settings.d.ts +13 -0
  29. package/dist/types/utils/tenant-settings.d.ts.map +1 -0
  30. package/package.json +5 -5
@@ -1,9 +1,10 @@
1
1
  import { Hono as e } from "hono";
2
- import { LogTypes as t, MANAGEMENT_API_AUDIENCE as n, MANAGEMENT_API_SCOPES as r, actionInsertSchema as i, auth0QuerySchema as a, brandingSchema as o, canDecrypt as s, connectionInsertSchema as c, connectionOptionsSchema as l, connectionSchema as u, deepMergePatch as d, emailProviderSchema as f, escapeLuceneValue as p, fetchAll as m, hookCodeInsertSchema as h, hookInsertSchema as g, init as _, isInteractiveClient as v, isSyncedRowId as y, listControlPlaneKeys as b, promptSettingSchema as ee, provisionDefaultClients as te, resourceServerInsertSchema as x, tenantInsertSchema as S, tenantSchema as C } from "authhero";
3
- import { HTTPException as w } from "hono/http-exception";
4
- import { OpenAPIHono as T, createRoute as E, z as D } from "@hono/zod-openapi";
2
+ import { LogTypes as t, MANAGEMENT_API_AUDIENCE as n, MANAGEMENT_API_SCOPES as r, TenantMemberRequestRejected as i, actionInsertSchema as a, auth0QuerySchema as o, brandingSchema as s, canDecrypt as c, connectionInsertSchema as l, connectionOptionsSchema as u, connectionSchema as d, deepMergePatch as f, emailProviderSchema as p, escapeLuceneValue as m, executeTenantMemberRequest as h, fetchAll as g, hookCodeInsertSchema as _, hookInsertSchema as v, init as y, isInteractiveClient as b, isSyncedRowId as x, listControlPlaneKeys as S, promptSettingSchema as C, provisionDefaultClients as w, resourceServerInsertSchema as T, tenantInsertSchema as E, tenantSchema as D } from "authhero";
3
+ import { HTTPException as O } from "hono/http-exception";
4
+ import { OpenAPIHono as k, createRoute as A, z as j } from "@hono/zod-openapi";
5
+ import { escapeLuceneValue as ee } from "@authhero/adapter-interfaces";
5
6
  //#region src/hooks/access-control.ts
6
- function ne(e) {
7
+ function M(e) {
7
8
  let { controlPlaneTenantId: t, requireOrganizationMatch: n = !0 } = e;
8
9
  return { async onTenantAccessValidation(e, r) {
9
10
  if (r === t) return !0;
@@ -14,14 +15,14 @@ function ne(e) {
14
15
  return !0;
15
16
  } };
16
17
  }
17
- function O(e, t, n, r) {
18
+ function N(e, t, n, r) {
18
19
  if (t === n) return !0;
19
20
  let i = r || e;
20
21
  return i ? i.toLowerCase() === t.toLowerCase() : !1;
21
22
  }
22
23
  //#endregion
23
24
  //#region src/hooks/database.ts
24
- function re(e) {
25
+ function te(e) {
25
26
  return { async resolveDataAdapters(t) {
26
27
  try {
27
28
  return await e.getAdapters(t);
@@ -33,18 +34,18 @@ function re(e) {
33
34
  }
34
35
  //#endregion
35
36
  //#region src/operations/instance-id.ts
36
- var k = 64;
37
- function ie(e) {
37
+ var P = 64;
38
+ function ne(e) {
38
39
  return e.replace(/[^a-zA-Z0-9_-]/g, "-");
39
40
  }
40
- function ae(e) {
41
- let t = ie(e.id), n = Math.max(0, k - (5 + t.length)), r = ie(e.kind).slice(0, n), i = 3 + r.length + 2 + t.length, a = Math.max(0, k - i);
42
- return `op-${r}-${ie(e.tenant_id ?? "fleet").slice(0, a)}-${t}`.slice(0, k);
41
+ function re(e) {
42
+ let t = ne(e.id), n = Math.max(0, P - (5 + t.length)), r = ne(e.kind).slice(0, n), i = 3 + r.length + 2 + t.length, a = Math.max(0, P - i);
43
+ return `op-${r}-${ne(e.tenant_id ?? "fleet").slice(0, a)}-${t}`.slice(0, P);
43
44
  }
44
45
  //#endregion
45
46
  //#region src/operations/recorder.ts
46
- var oe = 2048;
47
- function se(e) {
47
+ var ie = 2048;
48
+ function F(e) {
48
49
  let t;
49
50
  if (e instanceof Error) t = e.message;
50
51
  else try {
@@ -52,9 +53,9 @@ function se(e) {
52
53
  } catch {
53
54
  t = Object.prototype.toString.call(e);
54
55
  }
55
- return t.slice(0, oe);
56
+ return t.slice(0, ie);
56
57
  }
57
- function A(e) {
58
+ function I(e) {
58
59
  let { tenantOperations: t, tenantOperationEvents: n } = e;
59
60
  return {
60
61
  async markRunning(e, n) {
@@ -88,24 +89,24 @@ function A(e) {
88
89
  async markFailed(e, n) {
89
90
  await t.update(e, {
90
91
  status: "failed",
91
- error: se(n),
92
+ error: F(n),
92
93
  finished_at: (/* @__PURE__ */ new Date()).toISOString()
93
94
  });
94
95
  }
95
96
  };
96
97
  }
97
- function j(e) {
98
+ function L(e) {
98
99
  return e === "succeeded" || e === "failed" || e === "cancelled";
99
100
  }
100
101
  //#endregion
101
102
  //#region src/operations/inline-executor.ts
102
- var ce = { async do(e, t, n) {
103
+ var ae = { async do(e, t, n) {
103
104
  let r = typeof t == "function" ? t : n;
104
105
  if (!r) throw Error("StepRunner.do called without a function");
105
106
  return r();
106
107
  } };
107
- function le(e) {
108
- let t = A(e.stores);
108
+ function oe(e) {
109
+ let t = I(e.stores);
109
110
  return {
110
111
  engine: "inline",
111
112
  async start(n) {
@@ -124,7 +125,7 @@ function le(e) {
124
125
  try {
125
126
  let r = await e.run({
126
127
  operation: n,
127
- step: ce
128
+ step: ae
128
129
  });
129
130
  await t.appendEvent(n.id, {
130
131
  step: e.name,
@@ -135,7 +136,7 @@ function le(e) {
135
136
  throw await t.appendEvent(n.id, {
136
137
  step: e.name,
137
138
  outcome: "failed",
138
- detail: { message: se(r) }
139
+ detail: { message: F(r) }
139
140
  }), await t.markFailed(n.id, r), r;
140
141
  }
141
142
  }
@@ -145,7 +146,7 @@ function le(e) {
145
146
  }
146
147
  //#endregion
147
148
  //#region src/operations/enqueue.ts
148
- async function M(e, t, n) {
149
+ async function se(e, t, n) {
149
150
  let r = await e.tenantOperations.create({
150
151
  tenant_id: t.tenant_id,
151
152
  rollout_id: t.rollout_id,
@@ -155,12 +156,12 @@ async function M(e, t, n) {
155
156
  target_worker_version: t.target_worker_version,
156
157
  target_database_version: t.target_database_version,
157
158
  input: t.input
158
- }), i = ae(r);
159
+ }), i = re(r);
159
160
  try {
160
161
  await e.tenantOperations.update(r.id, { engine_instance_id: i });
161
162
  } catch (t) {
162
163
  try {
163
- await A(e).markFailed(r.id, t);
164
+ await I(e).markFailed(r.id, t);
164
165
  } catch {}
165
166
  throw t;
166
167
  }
@@ -169,15 +170,15 @@ async function M(e, t, n) {
169
170
  engine_instance_id: i
170
171
  };
171
172
  }
172
- async function ue(e, t, n, r = {}) {
173
- let i = A(e), a = await M(e, n, t.engine);
173
+ async function ce(e, t, n, r = {}) {
174
+ let i = I(e), a = await se(e, n, t.engine);
174
175
  try {
175
176
  await t.start(a);
176
177
  } catch (t) {
177
178
  let n = null;
178
179
  try {
179
180
  let r = await e.tenantOperations.get(a.id);
180
- r && !j(r.status) && await i.markFailed(a.id, t), n = await e.tenantOperations.get(a.id);
181
+ r && !L(r.status) && await i.markFailed(a.id, t), n = await e.tenantOperations.get(a.id);
181
182
  } catch (e) {
182
183
  console.warn("Failed to record tenant operation failure:", e);
183
184
  }
@@ -190,17 +191,17 @@ async function ue(e, t, n, r = {}) {
190
191
  return console.warn("Failed to re-fetch tenant operation after start:", e), a;
191
192
  }
192
193
  }
193
- async function de(e) {
194
+ async function le(e) {
194
195
  let { tenantId: t, parentTenantId: n, getTenant: r, getChildren: i } = e, a = e.maxDepth ?? 2;
195
196
  if (!n) return;
196
- if (t && n === t) throw new w(400, { message: "A tenant cannot be its own parent" });
197
+ if (t && n === t) throw new O(400, { message: "A tenant cannot be its own parent" });
197
198
  let o = new Set(t ? [t] : []), s = 0, c = n;
198
199
  for (; c;) {
199
- if (o.has(c)) throw new w(400, { message: `Setting parent_tenant_id to '${n}' would create a cycle` });
200
+ if (o.has(c)) throw new O(400, { message: `Setting parent_tenant_id to '${n}' would create a cycle` });
200
201
  o.add(c);
201
202
  let e = await r(c);
202
- if (!e) throw new w(400, { message: `Parent tenant '${c}' not found` });
203
- if (s += 1, s > a) throw new w(400, { message: `Tenant tree is limited to ${a} levels above a tenant` });
203
+ if (!e) throw new O(400, { message: `Parent tenant '${c}' not found` });
204
+ if (s += 1, s > a) throw new O(400, { message: `Tenant tree is limited to ${a} levels above a tenant` });
204
205
  c = e.parent_tenant_id;
205
206
  }
206
207
  if (t && i) {
@@ -208,20 +209,20 @@ async function de(e) {
208
209
  for (; o.length > 0;) {
209
210
  let t = [];
210
211
  for (let n of o) for (let r of await i(n)) e.has(r) || (e.add(r), t.push(r));
211
- if (t.length > 0 && (r += 1, s + r > a)) throw new w(400, { message: `Moving tenant under '${n}' would make its descendant '${t[0]}' exceed the tenant tree limit of ${a} levels` });
212
+ if (t.length > 0 && (r += 1, s + r > a)) throw new O(400, { message: `Moving tenant under '${n}' would make its descendant '${t[0]}' exceed the tenant tree limit of ${a} levels` });
212
213
  o = t;
213
214
  }
214
215
  }
215
216
  }
216
217
  //#endregion
217
218
  //#region src/inheritance/chain.ts
218
- async function N(e) {
219
+ async function R(e) {
219
220
  let { tenantId: t, getTenant: n, legacyControlPlane: r } = e, i = e.maxDepth ?? 2, a = await n(t);
220
221
  if (!a?.parent_tenant_id) return r && r !== t ? [r] : [];
221
222
  let o = [], s = new Set([t]), c = a.parent_tenant_id;
222
223
  for (; c;) {
223
- if (s.has(c)) throw new w(400, { message: `Tenant chain for '${t}' contains a cycle at '${c}'` });
224
- if (s.add(c), o.length >= i) throw new w(400, { message: `Tenant chain for '${t}' is deeper than ${i}` });
224
+ if (s.has(c)) throw new O(400, { message: `Tenant chain for '${t}' contains a cycle at '${c}'` });
225
+ if (s.add(c), o.length >= i) throw new O(400, { message: `Tenant chain for '${t}' is deeper than ${i}` });
225
226
  let e = await n(c);
226
227
  if (!e) break;
227
228
  o.push(c), c = e.parent_tenant_id;
@@ -230,18 +231,18 @@ async function N(e) {
230
231
  }
231
232
  //#endregion
232
233
  //#region src/inheritance/legacy.ts
233
- function fe(e) {
234
+ function ue(e) {
234
235
  let t = {};
235
236
  for (let n of e ?? []) n.value !== void 0 && (t[n.name] = n.value);
236
237
  return t;
237
238
  }
238
- function pe(e, t) {
239
+ function de(e, t) {
239
240
  if (!e.inherit) return e;
240
241
  let n = t.find((t) => t.name === e.name && t.is_system);
241
242
  if (!n) return e;
242
243
  let r = {
243
- ...fe(n.secrets),
244
- ...fe(e.secrets)
244
+ ...ue(n.secrets),
245
+ ...ue(e.secrets)
245
246
  };
246
247
  return {
247
248
  ...e,
@@ -252,15 +253,15 @@ function pe(e, t) {
252
253
  }))
253
254
  };
254
255
  }
255
- function me(e, t) {
256
+ function fe(e, t) {
256
257
  if (!t) return e;
257
- let n = new Set(e.hooks.map((e) => e.hook_id)), r = t.hooks.filter((e) => B(e) && !n.has(e.hook_id));
258
+ let n = new Set(e.hooks.map((e) => e.hook_id)), r = t.hooks.filter((e) => He(e) && !n.has(e.hook_id));
258
259
  return {
259
- connections: e.connections.map((e) => R(e, t.connections)),
260
+ connections: e.connections.map((e) => Ne(e, t.connections)),
260
261
  resourceServers: e.resourceServers.map((e) => e.is_system ? Ie(e, t.resourceServers.find((t) => t.id === e.id) ?? null) : e),
261
262
  hooks: [...e.hooks, ...r],
262
263
  hookCode: e.hookCode,
263
- actions: e.actions.map((e) => pe(e, t.actions)),
264
+ actions: e.actions.map((e) => de(e, t.actions)),
264
265
  emailProvider: e.emailProvider ?? t.emailProvider,
265
266
  branding: e.branding,
266
267
  promptSettings: e.promptSettings
@@ -268,7 +269,7 @@ function me(e, t) {
268
269
  }
269
270
  //#endregion
270
271
  //#region src/rollout/defaults-projection.ts
271
- function he(e = {}) {
272
+ function pe(e = {}) {
272
273
  return {
273
274
  connections: e.connections ?? !0,
274
275
  resourceServers: e.resourceServers ?? !0,
@@ -278,28 +279,28 @@ function he(e = {}) {
278
279
  promptSettings: e.promptSettings ?? !0
279
280
  };
280
281
  }
281
- function P() {
282
+ function z() {
282
283
  return {
283
284
  upserted: 0,
284
285
  errors: []
285
286
  };
286
287
  }
287
- function ge(e) {
288
+ function me(e) {
288
289
  return {
289
290
  tenantId: e,
290
- connections: P(),
291
- resourceServers: P(),
292
- hooks: P(),
293
- emailProvider: P(),
294
- branding: P(),
295
- promptSettings: P()
291
+ connections: z(),
292
+ resourceServers: z(),
293
+ hooks: z(),
294
+ emailProvider: z(),
295
+ branding: z(),
296
+ promptSettings: z()
296
297
  };
297
298
  }
298
- function _e(e) {
299
+ function he(e) {
299
300
  let t = e.metadata;
300
301
  return !!(t && t.inheritable === !0);
301
302
  }
302
- async function F(e, t, n, r) {
303
+ async function B(e, t, n, r) {
303
304
  try {
304
305
  await r();
305
306
  } catch (r) {
@@ -308,17 +309,17 @@ async function F(e, t, n, r) {
308
309
  e.errors.push(i);
309
310
  }
310
311
  }
311
- async function ve(e, t, n) {
312
+ async function ge(e, t, n) {
312
313
  return {
313
- connections: n.connections ? await m((n) => e.connections.list(t, n), "connections", {
314
+ connections: n.connections ? await g((n) => e.connections.list(t, n), "connections", {
314
315
  cursorField: "id",
315
316
  pageSize: 100
316
317
  }) : [],
317
- resourceServers: n.resourceServers ? await m((n) => e.resourceServers.list(t, n), "resource_servers", {
318
+ resourceServers: n.resourceServers ? await g((n) => e.resourceServers.list(t, n), "resource_servers", {
318
319
  cursorField: "id",
319
320
  pageSize: 100
320
321
  }) : [],
321
- hooks: n.hooks ? await m((n) => e.hooks.list(t, n), "hooks", {
322
+ hooks: n.hooks ? await g((n) => e.hooks.list(t, n), "hooks", {
322
323
  cursorField: "hook_id",
323
324
  pageSize: 100
324
325
  }) : [],
@@ -327,46 +328,46 @@ async function ve(e, t, n) {
327
328
  promptSettings: n.promptSettings ? await e.promptSettings.get(t) ?? null : null
328
329
  };
329
330
  }
330
- async function ye(e, t, n, r, i, a) {
331
+ async function _e(e, t, n, r, i, a) {
331
332
  if (r.connections) for (let r of e.connections) {
332
333
  let e = r.id;
333
- e && await F(a.connections, `connection ${e}`, i, async () => {
334
- let i = c.parse(r);
334
+ e && await B(a.connections, `connection ${e}`, i, async () => {
335
+ let i = l.parse(r);
335
336
  await t.connections.get(n, e) ? await t.connections.update(n, e, i) : await t.connections.create(n, i), a.connections.upserted += 1;
336
337
  });
337
338
  }
338
- if (r.resourceServers) for (let r of e.resourceServers) !r.is_system || !r.id || await F(a.resourceServers, `resource_server ${r.id}`, i, async () => {
339
- let e = x.parse(r);
339
+ if (r.resourceServers) for (let r of e.resourceServers) !r.is_system || !r.id || await B(a.resourceServers, `resource_server ${r.id}`, i, async () => {
340
+ let e = T.parse(r);
340
341
  await t.resourceServers.get(n, r.id) ? await t.resourceServers.update(n, r.id, e) : await t.resourceServers.create(n, e), a.resourceServers.upserted += 1;
341
342
  });
342
- if (r.hooks) for (let r of e.hooks) !_e(r) || !r.hook_id || await F(a.hooks, `hook ${r.hook_id}`, i, async () => {
343
- let e = g.parse(r);
343
+ if (r.hooks) for (let r of e.hooks) !he(r) || !r.hook_id || await B(a.hooks, `hook ${r.hook_id}`, i, async () => {
344
+ let e = v.parse(r);
344
345
  await t.hooks.get(n, r.hook_id) ? await t.hooks.update(n, r.hook_id, e) : await t.hooks.create(n, e), a.hooks.upserted += 1;
345
346
  });
346
- r.emailProvider && e.emailProvider && await F(a.emailProvider, "email_provider", i, async () => {
347
+ r.emailProvider && e.emailProvider && await B(a.emailProvider, "email_provider", i, async () => {
347
348
  let r = e.emailProvider;
348
349
  await t.emailProviders.get(n) ? await t.emailProviders.update(n, r) : await t.emailProviders.create(n, r), a.emailProvider.upserted += 1;
349
- }), r.branding && e.branding && await F(a.branding, "branding", i, async () => {
350
+ }), r.branding && e.branding && await B(a.branding, "branding", i, async () => {
350
351
  await t.branding.set(n, e.branding), a.branding.upserted += 1;
351
- }), r.promptSettings && e.promptSettings && await F(a.promptSettings, "prompt_settings", i, async () => {
352
+ }), r.promptSettings && e.promptSettings && await B(a.promptSettings, "prompt_settings", i, async () => {
352
353
  await t.promptSettings.set(n, e.promptSettings), a.promptSettings.upserted += 1;
353
354
  });
354
355
  }
355
- async function be(e, t) {
356
- let { controlPlaneTenantId: n, getControlPlaneAdapters: r, getAdapters: i, entities: a, continueOnError: o = !1 } = e, s = he(a), c = await ve(await r(), n, s), l = await i(t), u = ge(t);
357
- return await ye(c, l, n, s, o, u), u;
356
+ async function ve(e, t) {
357
+ let { controlPlaneTenantId: n, getControlPlaneAdapters: r, getAdapters: i, entities: a, continueOnError: o = !1 } = e, s = pe(a), c = await ge(await r(), n, s), l = await i(t), u = me(t);
358
+ return await _e(c, l, n, s, o, u), u;
358
359
  }
359
360
  //#endregion
360
361
  //#region src/inheritance/read.ts
361
- async function I(e, t) {
362
- let n = await ve(e, t, {
362
+ async function V(e, t) {
363
+ let n = await ge(e, t, {
363
364
  connections: !0,
364
365
  resourceServers: !0,
365
366
  hooks: !0,
366
367
  emailProvider: !0,
367
368
  branding: !0,
368
369
  promptSettings: !0
369
- }), r = await m((n) => e.actions.list(t, n), "actions", {
370
+ }), r = await g((n) => e.actions.list(t, n), "actions", {
370
371
  cursorField: "id",
371
372
  pageSize: 100
372
373
  }), i = new Set(r.map((e) => e.id)), a = /* @__PURE__ */ new Set();
@@ -387,7 +388,7 @@ async function I(e, t) {
387
388
  }
388
389
  //#endregion
389
390
  //#region src/inheritance/shadow.ts
390
- var xe = /secret|password|private_key|api_key|token/i, Se = new Set([
391
+ var ye = /secret|password|private_key|api_key|token/i, be = new Set([
391
392
  "id",
392
393
  "tenant_id",
393
394
  "created_at",
@@ -397,40 +398,40 @@ var xe = /secret|password|private_key|api_key|token/i, Se = new Set([
397
398
  "enforce",
398
399
  "enabled_clients"
399
400
  ]);
400
- async function L(e) {
401
+ async function H(e) {
401
402
  let t = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(e));
402
403
  return [...new Uint8Array(t)].map((e) => e.toString(16).padStart(2, "0")).join("").slice(0, 16);
403
404
  }
404
- async function Ce(e, t = "") {
405
+ async function xe(e, t = "") {
405
406
  if (Array.isArray(e)) {
406
407
  if (t === "secrets") {
407
408
  let t = {};
408
- for (let n of e) t[n.name] = n.value === void 0 ? null : `sha256:${await L(n.value)}`;
409
+ for (let n of e) t[n.name] = n.value === void 0 ? null : `sha256:${await H(n.value)}`;
409
410
  return t;
410
411
  }
411
- return Promise.all(e.map((e) => Ce(e, t)));
412
+ return Promise.all(e.map((e) => xe(e, t)));
412
413
  }
413
414
  if (e && typeof e == "object") {
414
415
  let t = {};
415
416
  for (let n of Object.keys(e).sort()) {
416
417
  let r = e[n];
417
- r != null && (t[n] = typeof r == "string" && xe.test(n) ? `sha256:${await L(r)}` : await Ce(r, n));
418
+ r != null && (t[n] = typeof r == "string" && ye.test(n) ? `sha256:${await H(r)}` : await xe(r, n));
418
419
  }
419
420
  return t;
420
421
  }
421
422
  return e;
422
423
  }
423
- async function we(e) {
424
+ async function Se(e) {
424
425
  let t = {};
425
- for (let [n, r] of Object.entries(e)) Se.has(n) || (t[n] = r);
426
- return await Ce(t);
426
+ for (let [n, r] of Object.entries(e)) be.has(n) || (t[n] = r);
427
+ return await xe(t);
427
428
  }
428
- var Te = {
429
+ var Ce = {
429
430
  connection: (e) => `${e.strategy}:${e.name}`,
430
431
  resourceServer: (e) => e.identifier,
431
432
  hook: (e) => e.hook_id,
432
433
  action: (e) => e.name
433
- }, Ee = new Set([
434
+ }, we = new Set([
434
435
  "connection",
435
436
  "resourceServer",
436
437
  "action",
@@ -438,12 +439,12 @@ var Te = {
438
439
  "branding",
439
440
  "promptSettings"
440
441
  ]);
441
- async function De(e) {
442
+ async function Te(e) {
442
443
  let t = /* @__PURE__ */ new Map(), n = async (e, n, r) => {
443
444
  let i = t.get(e) ?? /* @__PURE__ */ new Map();
444
- i.set(n, await we(r)), t.set(e, i);
445
+ i.set(n, await Se(r)), t.set(e, i);
445
446
  };
446
- for (let [t, r] of Object.entries(Te)) {
447
+ for (let [t, r] of Object.entries(Ce)) {
447
448
  let i = e[{
448
449
  connection: "connections",
449
450
  resourceServer: "resourceServers",
@@ -459,8 +460,8 @@ async function De(e) {
459
460
  ]) e[t] && await n(t, "singleton", e[t]);
460
461
  return t;
461
462
  }
462
- async function Oe(e, t) {
463
- let [n, r] = await Promise.all([De(e), De(t)]), i = [], a = new Set([...n.keys(), ...r.keys()]);
463
+ async function Ee(e, t) {
464
+ let [n, r] = await Promise.all([Te(e), Te(t)]), i = [], a = new Set([...n.keys(), ...r.keys()]);
464
465
  for (let e of a) {
465
466
  let t = n.get(e) ?? /* @__PURE__ */ new Map(), a = r.get(e) ?? /* @__PURE__ */ new Map();
466
467
  for (let n of new Set([...t.keys(), ...a.keys()])) {
@@ -477,7 +478,7 @@ async function Oe(e, t) {
477
478
  key: n,
478
479
  kind: "extra",
479
480
  fields: [],
480
- expected: Ee.has(e)
481
+ expected: we.has(e)
481
482
  });
482
483
  else if (r && o) {
483
484
  let t = JSON.stringify(r), a = JSON.stringify(o);
@@ -489,54 +490,54 @@ async function Oe(e, t) {
489
490
  kind: "changed",
490
491
  fields: s,
491
492
  expected: !1,
492
- legacy_hash: await L(t),
493
- new_hash: await L(a)
493
+ legacy_hash: await H(t),
494
+ new_hash: await H(a)
494
495
  });
495
496
  }
496
497
  }
497
498
  }
498
499
  return i;
499
500
  }
500
- async function ke(e) {
501
- let { adapters: t, tenantId: n, legacyControlPlane: r } = e, i = await N({
501
+ async function De(e) {
502
+ let { adapters: t, tenantId: n, legacyControlPlane: r } = e, i = await R({
502
503
  tenantId: n,
503
504
  getTenant: (e) => t.tenants.get(e),
504
505
  legacyControlPlane: r,
505
506
  maxDepth: e.maxDepth
506
- }), a = await I(t, n), o = await Promise.all(i.map((e) => I(t, e))), s = r && r !== n ? await I(t, r) : void 0, { hidden: c, ...l } = Ze(o, a), u = new Set(c);
507
- return (await Oe(me(a, s), l)).filter((e) => !u.has(`${e.entity}:${e.key}`));
507
+ }), a = await V(t, n), o = await Promise.all(i.map((e) => V(t, e))), s = r && r !== n ? await V(t, r) : void 0, { hidden: c, ...l } = $e(o, a), u = new Set(c);
508
+ return (await Ee(fe(a, s), l)).filter((e) => !u.has(`${e.entity}:${e.key}`));
508
509
  }
509
510
  //#endregion
510
511
  //#region src/inheritance/report.ts
511
- var Ae = 3600 * 1e3, je = 1e4;
512
- function Me(e, t) {
512
+ var Oe = 3600 * 1e3, ke = 1e4;
513
+ function Ae(e, t) {
513
514
  let n = t.sample ?? 1, r = t.intervalMs ?? 6e4, i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map();
514
515
  async function s(n, r) {
515
- let i = await ke({
516
+ let i = await De({
516
517
  adapters: e,
517
518
  tenantId: n,
518
519
  legacyControlPlane: r
519
520
  }), a = Date.now();
520
- o.size > je && o.clear();
521
+ o.size > ke && o.clear();
521
522
  for (let s of i) {
522
523
  if (s.expected && !t.includeExpected) continue;
523
- let i = await L([
524
+ let i = await H([
524
525
  n,
525
526
  s.entity,
526
527
  s.key,
527
528
  s.kind,
528
529
  s.fields.join(",")
529
530
  ].join("|")), c = o.get(i);
530
- c !== void 0 && a - c < Ae || (o.set(i, a), await Ne(e, n, s, r));
531
+ c !== void 0 && a - c < Oe || (o.set(i, a), await je(e, n, s, r));
531
532
  }
532
533
  }
533
534
  return { schedule(e, t) {
534
535
  if (a.has(e) || n < 1 && Math.random() >= n) return;
535
536
  let o = Date.now(), c = i.get(e);
536
- c !== void 0 && o - c < r || (i.set(e, o), a.add(e), s(e, t).catch(() => {}).finally(() => a.delete(e)));
537
+ if (!(c !== void 0 && o - c < r)) return i.set(e, o), a.add(e), s(e, t).catch(() => {}).finally(() => a.delete(e));
537
538
  } };
538
539
  }
539
- async function Ne(e, n, r, i) {
540
+ async function je(e, n, r, i) {
540
541
  await e.logs.create(n, {
541
542
  type: t.CONFIG_INHERITANCE_DIFF,
542
543
  date: (/* @__PURE__ */ new Date()).toISOString(),
@@ -549,20 +550,18 @@ async function Ne(e, n, r, i) {
549
550
  }
550
551
  });
551
552
  }
552
- //#endregion
553
- //#region src/middleware/config-sync-mode.ts
554
- function Pe(e) {
555
- let { base: t, getTenant: n, controlPlaneTenantId: r } = e, i = e.ttlMs ?? 3e4, a = e.maxEntries ?? 1e3, o = /* @__PURE__ */ new Map();
553
+ function Me(e) {
554
+ let { base: t, getTenant: n, controlPlaneTenantId: r } = e, i = e.ttlMs ?? 1e4, a = e.maxEntries ?? 1e3, o = /* @__PURE__ */ new Map();
556
555
  async function s(e) {
557
556
  if (e === r) return !1;
558
557
  let t = o.get(e), s = Date.now();
559
558
  if (t && t.expires > s) return t.synced;
560
559
  try {
561
- let t = (await n(e))?.config_sync === "synced";
560
+ let t = await n(e), r = t?.config_sync === "synced" || t?.config_sync === "detached";
562
561
  return o.size >= a && o.clear(), o.set(e, {
563
- synced: t,
562
+ synced: r,
564
563
  expires: s + i
565
- }), t;
564
+ }), r;
566
565
  } catch {
567
566
  return !1;
568
567
  }
@@ -580,19 +579,19 @@ function Pe(e) {
580
579
  }
581
580
  //#endregion
582
581
  //#region src/middleware/settings-inheritance.ts
583
- function R(e, t) {
582
+ function Ne(e, t) {
584
583
  let n = t.find((t) => t.strategy === e.strategy);
585
584
  if (!n?.options) return e;
586
- let r = u.passthrough().parse({
585
+ let r = d.passthrough().parse({
587
586
  ...n,
588
587
  ...e
589
588
  });
590
- return r.options = l.passthrough().parse({
589
+ return r.options = u.passthrough().parse({
591
590
  ...n.options || {},
592
591
  ...e.options
593
592
  }), r;
594
593
  }
595
- function z(e, t) {
594
+ function Pe(e, t) {
596
595
  let n = [...t || [], ...e || []];
597
596
  return [...new Set(n)];
598
597
  }
@@ -613,10 +612,10 @@ function Ie(e, t) {
613
612
  function Le(e, t) {
614
613
  return t ? {
615
614
  ...e,
616
- callbacks: z(e.callbacks, t.callbacks),
617
- web_origins: z(e.web_origins, t.web_origins),
618
- allowed_logout_urls: z(e.allowed_logout_urls, t.allowed_logout_urls),
619
- allowed_origins: z(e.allowed_origins, t.allowed_origins)
615
+ callbacks: Pe(e.callbacks, t.callbacks),
616
+ web_origins: Pe(e.web_origins, t.web_origins),
617
+ allowed_logout_urls: Pe(e.allowed_logout_urls, t.allowed_logout_urls),
618
+ allowed_origins: Pe(e.allowed_origins, t.allowed_origins)
620
619
  } : e;
621
620
  }
622
621
  function Re(e) {
@@ -667,7 +666,7 @@ function Be(e, t) {
667
666
  };
668
667
  }
669
668
  function Ve(e, t) {
670
- let { controlPlaneTenantId: n, controlPlaneClientId: r, resolveControlPlane: i, inheritanceShadow: a } = t, o = t.configSync ?? Pe({
669
+ let { controlPlaneTenantId: n, controlPlaneClientId: r, resolveControlPlane: i, inheritanceShadow: a } = t, o = t.configSync ?? Me({
671
670
  base: Re({
672
671
  controlPlaneTenantId: n,
673
672
  controlPlaneClientId: r,
@@ -675,7 +674,7 @@ function Ve(e, t) {
675
674
  }),
676
675
  getTenant: async (t) => await e.tenants.get(t) ?? null,
677
676
  controlPlaneTenantId: n
678
- }), s = (e) => o.resolve({ tenant_id: e }), c = a ? Me(e, a === !0 ? {} : a) : void 0, l = c ? async (e) => {
677
+ }), s = (e) => o.resolve({ tenant_id: e }), c = a ? Ae(e, a === !0 ? {} : a) : void 0, l = c ? async (e) => {
679
678
  let t = await s(e);
680
679
  return await o.isSynced(e) || c.schedule(e, t?.tenantId), t;
681
680
  } : s;
@@ -692,12 +691,12 @@ function Ve(e, t) {
692
691
  let r = await e.connections.get(t, n);
693
692
  if (!r) return r;
694
693
  let i = await l(t);
695
- return !i || t === i.tenantId ? r : R(r, (await e.connections.list(i.tenantId)).connections || []);
694
+ return !i || t === i.tenantId ? r : Ne(r, (await e.connections.list(i.tenantId)).connections || []);
696
695
  },
697
696
  list: async (t, n) => {
698
697
  let r = await e.connections.list(t, n), i = await l(t);
699
698
  if (!i || t === i.tenantId) return r;
700
- let a = await e.connections.list(i.tenantId), o = r.connections.map((e) => R(e, a.connections || []));
699
+ let a = await e.connections.list(i.tenantId), o = r.connections.map((e) => Ne(e, a.connections || []));
701
700
  return {
702
701
  ...r,
703
702
  connections: o
@@ -712,7 +711,7 @@ function Ve(e, t) {
712
711
  let i = await l(t);
713
712
  if (!i || t === i.tenantId) return r;
714
713
  let a = await e.connections.list(i.tenantId);
715
- return r.map((e) => R(e, a.connections || []));
714
+ return r.map((e) => Ne(e, a.connections || []));
716
715
  }
717
716
  },
718
717
  emailProviders: {
@@ -725,24 +724,24 @@ function Ve(e, t) {
725
724
  }
726
725
  },
727
726
  resourceServers: ze(e, l),
728
- hooks: He(e, l)
727
+ hooks: Ue(e, l)
729
728
  };
730
729
  }
731
- function B(e) {
730
+ function He(e) {
732
731
  if (!e || typeof e != "object") return !1;
733
732
  let t = e.metadata;
734
733
  return !t || typeof t != "object" ? !1 : t.inheritable === !0;
735
734
  }
736
- function He(e, t) {
735
+ function Ue(e, t) {
737
736
  return {
738
737
  ...e.hooks,
739
738
  list: async (n, r) => {
740
739
  let i = await e.hooks.list(n, r), a = await t(n);
741
740
  if (!a || n === a.tenantId) return i;
742
- let o = ((await e.hooks.list(a.tenantId, r)).hooks || []).filter(B);
741
+ let o = ((await e.hooks.list(a.tenantId, r)).hooks || []).filter(He);
743
742
  if (o.length === 0) return i;
744
743
  let s = new Set((i.hooks || []).map((e) => e.hook_id)), c = [];
745
- for (let e of o) s.has(e.hook_id) || e.hook_id && s.has(await W("hook", n, e.hook_id)) || c.push(e);
744
+ for (let e of o) s.has(e.hook_id) || e.hook_id && s.has(await it("hook", n, e.hook_id)) || c.push(e);
746
745
  return {
747
746
  ...i,
748
747
  hooks: [...i.hooks || [], ...c],
@@ -755,16 +754,16 @@ function He(e, t) {
755
754
  let a = await t(n);
756
755
  if (!a || n === a.tenantId) return i;
757
756
  let o = await e.hooks.get(a.tenantId, r);
758
- return o && B(o) ? o : null;
757
+ return o && He(o) ? o : null;
759
758
  }
760
759
  };
761
760
  }
762
- function Ue(e, t) {
761
+ function We(e, t) {
763
762
  return Ve(e, t);
764
763
  }
765
764
  //#endregion
766
765
  //#region src/inheritance/types.ts
767
- var We = () => ({
766
+ var Ge = () => ({
768
767
  connections: [],
769
768
  resourceServers: [],
770
769
  hooks: [],
@@ -776,28 +775,28 @@ var We = () => ({
776
775
  });
777
776
  //#endregion
778
777
  //#region src/inheritance/merge.ts
779
- function V(e, t) {
778
+ function U(e, t) {
780
779
  if (t.scope) return t.scope;
781
780
  switch (e) {
782
781
  case "connection":
783
782
  case "emailProvider": return "shared";
784
783
  case "resourceServer":
785
784
  case "action": return t.is_system ? "shared" : "local";
786
- case "hook": return B(t) ? "shared" : "local";
785
+ case "hook": return He(t) ? "shared" : "local";
787
786
  default: return "local";
788
787
  }
789
788
  }
790
- function H(e) {
789
+ function Ke(e) {
791
790
  return e.override ?? "fields";
792
791
  }
793
- var Ge = /secret|password|private_key|api_key|token/i;
794
- function Ke(e, t) {
792
+ var qe = /secret|password|private_key|api_key|token/i;
793
+ function Je(e, t) {
795
794
  let n = { ...e ?? {} };
796
- for (let [e, r] of Object.entries(t ?? {})) Ge.test(e) && (n[e] = r);
795
+ for (let [e, r] of Object.entries(t ?? {})) qe.test(e) && (n[e] = r);
797
796
  return n;
798
797
  }
799
- function qe(e, t) {
800
- switch (H(e)) {
798
+ function Ye(e, t) {
799
+ switch (Ke(e)) {
801
800
  case "none": return {
802
801
  ...e,
803
802
  id: t.id
@@ -805,7 +804,7 @@ function qe(e, t) {
805
804
  case "secrets": return {
806
805
  ...e,
807
806
  id: t.id,
808
- options: Ke(e.options, t.options)
807
+ options: Je(e.options, t.options)
809
808
  };
810
809
  default: return {
811
810
  ...e,
@@ -817,8 +816,8 @@ function qe(e, t) {
817
816
  };
818
817
  }
819
818
  }
820
- function Je(e, t) {
821
- switch (H(e)) {
819
+ function Xe(e, t) {
820
+ switch (Ke(e)) {
822
821
  case "none": return {
823
822
  ...e,
824
823
  id: t.id
@@ -834,42 +833,42 @@ function Je(e, t) {
834
833
  };
835
834
  }
836
835
  }
837
- function Ye(e) {
836
+ function Ze(e) {
838
837
  return new Map((e ?? []).map((e) => [e.name, e]));
839
838
  }
840
- function Xe(e, t) {
841
- let n = H(e);
839
+ function Qe(e, t) {
840
+ let n = Ke(e);
842
841
  if (n === "none") return {
843
842
  ...e,
844
843
  id: t.id
845
844
  };
846
- let r = Ye(e.secrets);
847
- if (n === "secrets" || n === "fields") for (let [e, n] of Ye(t.secrets)) r.set(e, n);
845
+ let r = Ze(e.secrets);
846
+ if (n === "secrets" || n === "fields") for (let [e, n] of Ze(t.secrets)) r.set(e, n);
848
847
  return {
849
848
  ...n === "fields" && !t.inherit ? t : e,
850
849
  id: t.id,
851
850
  secrets: [...r.values()]
852
851
  };
853
852
  }
854
- function Ze(e, t) {
853
+ function $e(e, t) {
855
854
  let n = /* @__PURE__ */ new Set(), r = [...e].reverse().concat(t), i = (e, t, r, i) => r ? t : t.filter((t) => {
856
- let r = V(e, t);
855
+ let r = U(e, t);
857
856
  return r === "local" ? !1 : (r === "platform" && n.add(`${e}:${i(t)}`), !0);
858
- }), a = We(), o = (e) => `${e.strategy}:${e.name}`, s = (e) => e.identifier, c = (e) => e.hook_id ?? "", l = (e) => e.name, u = /* @__PURE__ */ new Map(), d = [], f = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), m = /* @__PURE__ */ new Map();
857
+ }), a = Ge(), o = (e) => `${e.strategy}:${e.name}`, s = (e) => e.identifier, c = (e) => e.hook_id ?? "", l = (e) => e.name, u = /* @__PURE__ */ new Map(), d = [], f = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), m = /* @__PURE__ */ new Map();
859
858
  r.forEach((e, t) => {
860
859
  let h = t === r.length - 1;
861
860
  for (let t of i("connection", e.connections, h, o)) {
862
861
  let e = u.get(t.strategy);
863
- h ? d.push(e ? qe(e, t) : t) : u.set(t.strategy, e ? qe(e, t) : t);
862
+ h ? d.push(e ? Ye(e, t) : t) : u.set(t.strategy, e ? Ye(e, t) : t);
864
863
  }
865
864
  for (let t of i("resourceServer", e.resourceServers, h, s)) {
866
865
  let e = f.get(s(t));
867
- f.set(s(t), e ? Je(e, t) : t);
866
+ f.set(s(t), e ? Xe(e, t) : t);
868
867
  }
869
868
  for (let t of i("hook", e.hooks, h, c)) p.set(c(t), t);
870
869
  for (let t of i("action", e.actions, h, l)) {
871
870
  let e = m.get(l(t));
872
- m.set(l(t), e ? Xe(e, t) : t);
871
+ m.set(l(t), e ? Qe(e, t) : t);
873
872
  }
874
873
  for (let t of [
875
874
  "emailProvider",
@@ -877,7 +876,7 @@ function Ze(e, t) {
877
876
  "promptSettings"
878
877
  ]) {
879
878
  let r = e[t];
880
- r && (h || V(t, r) !== "local") && (!h && V(t, r) === "platform" && n.add(`${t}:singleton`), a[t] = r);
879
+ r && (h || U(t, r) !== "local") && (!h && U(t, r) === "platform" && n.add(`${t}:singleton`), a[t] = r);
881
880
  }
882
881
  });
883
882
  let h = new Set(r[r.length - 1].connections.map((e) => e.strategy));
@@ -891,25 +890,32 @@ function Ze(e, t) {
891
890
  }
892
891
  //#endregion
893
892
  //#region src/rollout/resolved-sync.ts
894
- function U(e) {
895
- return Array.isArray(e) ? `[${e.map(U).join(",")}]` : e && typeof e == "object" ? `{${Object.entries(e).filter(([, e]) => e !== void 0).sort(([e], [t]) => e < t ? -1 : 1).map(([e, t]) => `${JSON.stringify(e)}:${U(t)}`).join(",")}}` : JSON.stringify(e) ?? "null";
893
+ var et = [
894
+ "connection",
895
+ "resourceServer",
896
+ "hookCode",
897
+ "action",
898
+ "hook"
899
+ ];
900
+ function tt(e) {
901
+ return Array.isArray(e) ? `[${e.map(tt).join(",")}]` : e && typeof e == "object" ? `{${Object.entries(e).filter(([, e]) => e !== void 0).sort(([e], [t]) => e < t ? -1 : 1).map(([e, t]) => `${JSON.stringify(e)}:${tt(t)}`).join(",")}}` : JSON.stringify(e) ?? "null";
896
902
  }
897
- async function Qe(e) {
903
+ async function nt(e) {
898
904
  let t = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(e));
899
905
  return [...new Uint8Array(t)].map((e) => e.toString(16).padStart(2, "0")).join("");
900
906
  }
901
- var $e = {
907
+ var rt = {
902
908
  connection: "con_",
903
909
  resourceServer: "api_",
904
910
  hook: "h_",
905
911
  hookCode: "hc_",
906
912
  action: "act_"
907
913
  };
908
- async function W(e, t, n) {
909
- let r = await Qe(`${t}|${e}|${n}`);
910
- return `${$e[e]}sy${r.slice(0, 15)}`;
914
+ async function it(e, t, n) {
915
+ let r = await nt(`${t}|${e}|${n}`);
916
+ return `${rt[e]}sy${r.slice(0, 15)}`;
911
917
  }
912
- function G(e, t) {
918
+ function W(e, t) {
913
919
  let n = t;
914
920
  switch (e) {
915
921
  case "connection": return `${n.strategy}:${n.name}`;
@@ -919,13 +925,13 @@ function G(e, t) {
919
925
  case "hook": return n.hook_id;
920
926
  }
921
927
  }
922
- async function et(e, t, n = {}) {
923
- let r = await N({
928
+ async function at(e, t, n = {}) {
929
+ let r = await R({
924
930
  tenantId: t,
925
931
  getTenant: (t) => e.tenants.get(t),
926
932
  legacyControlPlane: n.legacyControlPlane,
927
933
  maxDepth: n.maxDepth
928
- }), i = Ze(await Promise.all(r.map((t) => I(e, t))), We()), a = {
934
+ }), i = $e(await Promise.all(r.map((t) => V(e, t))), Ge()), a = {
929
935
  version: 1,
930
936
  chain: r,
931
937
  connections: i.connections,
@@ -941,107 +947,146 @@ async function et(e, t, n = {}) {
941
947
  };
942
948
  return {
943
949
  ...a,
944
- hash: await Qe(U(a))
950
+ hash: await nt(tt(a))
945
951
  };
946
952
  }
947
- function tt(e, t) {
953
+ function ot(e, t) {
948
954
  if (typeof e == "string") e.startsWith("enc:v1:") && t.add(e);
949
- else if (Array.isArray(e)) for (let n of e) tt(n, t);
950
- else if (e && typeof e == "object") for (let n of Object.values(e)) tt(n, t);
955
+ else if (Array.isArray(e)) for (let n of e) ot(n, t);
956
+ else if (e && typeof e == "object") for (let n of Object.values(e)) ot(n, t);
951
957
  }
952
- function nt(e) {
958
+ function st(e) {
953
959
  let t = e.slice(7), n = t.indexOf(":");
954
960
  return n === -1 ? "default" : t.slice(0, n);
955
961
  }
956
- async function rt(e, t) {
962
+ async function ct(e, t) {
957
963
  let n = /* @__PURE__ */ new Set();
958
- tt(e, n);
964
+ ot(e, n);
959
965
  let r = /* @__PURE__ */ new Set();
960
- for (let e of n) await s(e, t) || r.add(nt(e));
966
+ for (let e of n) await c(e, t) || r.add(st(e));
961
967
  return [...r].sort();
962
968
  }
963
- var K = () => ({
969
+ var G = () => ({
964
970
  added: 0,
965
971
  changed: 0,
966
972
  unchanged: 0,
967
973
  deleted: 0,
968
974
  errors: []
969
- }), it = (e) => U(e);
970
- async function at(e, t, n, r = {}) {
971
- let { dryRun: a = !1, continueOnError: s = !0 } = r, l = {
972
- status: a ? "dry-run" : "applied",
975
+ }), lt = (e) => tt(e);
976
+ async function ut(e, t, n, r = {}) {
977
+ let { dryRun: i = !1, continueOnError: o = !0 } = r;
978
+ if (r.prune && e.chain.length === 0) throw Error(`Cannot prune '${n}': the block resolved no ancestors, so every synced copy would look stale. Nothing was written.`);
979
+ let c = {
980
+ status: i ? "dry-run" : "applied",
973
981
  hash: e.hash,
974
982
  entities: {
975
- connection: K(),
976
- resourceServer: K(),
977
- hookCode: K(),
978
- action: K(),
979
- hook: K(),
980
- emailProvider: K(),
981
- branding: K(),
982
- promptSettings: K()
983
+ connection: G(),
984
+ resourceServer: G(),
985
+ hookCode: G(),
986
+ action: G(),
987
+ hook: G(),
988
+ emailProvider: G(),
989
+ branding: G(),
990
+ promptSettings: G()
983
991
  },
984
- changes: []
992
+ changes: [],
993
+ rows: []
985
994
  }, u = await t.tenants.get(n), d = !!r.deletes && e.deletes.length > 0;
986
- if (!a && !r.force && !d && u?.config_sync_hash === e.hash) return {
987
- ...l,
995
+ if (!i && !r.force && !d && !r.prune && u?.config_sync_hash === e.hash) return {
996
+ ...c,
988
997
  status: "up-to-date"
989
998
  };
990
999
  if (r.keyRing) {
991
- let t = await rt(e, r.keyRing);
1000
+ let t = await ct(e, r.keyRing);
992
1001
  if (t.length > 0) throw Error(`Cannot sync config to '${n}': its key ring cannot decrypt key id(s) ${t.map((e) => `"${e}"`).join(", ")} carried by the payload. Nothing was written.`);
993
1002
  }
994
- let p = async (e, t, n) => {
995
- let r = l.entities[e];
1003
+ let f = await V(t, n), m = (i || r.prune) && e.chain.length > 0 ? f : null, h = {
1004
+ connection: /* @__PURE__ */ new Set(),
1005
+ resourceServer: /* @__PURE__ */ new Set(),
1006
+ action: /* @__PURE__ */ new Set()
1007
+ };
1008
+ for (let e of f.connections) x(e.id) || h.connection.add(W("connection", e));
1009
+ for (let e of f.resourceServers) x(e.id) || h.resourceServer.add(W("resourceServer", e));
1010
+ for (let e of f.actions) x(e.id) || h.action.add(W("action", e));
1011
+ let y = async (e, t, n) => {
1012
+ let r = c.entities[e];
996
1013
  try {
997
1014
  let i = await n();
998
- r[i] += 1, i !== "unchanged" && l.changes.push(`${e}:${t}`);
1015
+ r[i] += 1, i !== "unchanged" && (c.changes.push(`${e}:${t}`), c.rows.push({
1016
+ entity: e,
1017
+ key: t,
1018
+ action: i
1019
+ }));
999
1020
  } catch (n) {
1000
1021
  let i = `${e} ${t}: ${n instanceof Error ? n.message : String(n)}`;
1001
- if (!s) throw Error(i, { cause: n });
1022
+ if (!o) throw Error(i, { cause: n });
1002
1023
  r.errors.push(i);
1003
1024
  }
1004
- }, m = async (e) => e.existing ? it(e.view(e.existing)) === it(e.view(e.desired)) ? "unchanged" : (a || await e.update(), "changed") : (a || await e.create(), "added"), _ = (e, t) => W(e, n, t), v = /* @__PURE__ */ new Map();
1005
- for (let t of e.hookCode) v.set(t.id, await _("hookCode", G("hookCode", t)));
1006
- for (let t of e.actions) v.set(t.id, await _("action", G("action", t)));
1025
+ }, b = async (e) => e.existing ? lt(e.view(e.existing)) === lt(e.view(e.desired)) ? "unchanged" : (i || await e.update(), "changed") : (i || await e.create(), "added"), S = (e, t) => it(e, n, t), w = /* @__PURE__ */ new Map();
1026
+ for (let t of e.hookCode) w.set(t.id, await S("hookCode", W("hookCode", t)));
1027
+ for (let t of e.actions) w.set(t.id, await S("action", W("action", t)));
1028
+ let E, D = async (e) => {
1029
+ if (!E) {
1030
+ E = [];
1031
+ let e = await g((e) => t.clients.list(n, e), "clients", {
1032
+ cursorField: "client_id",
1033
+ pageSize: 100
1034
+ });
1035
+ for (let r of e) (await t.clientConnections.listByClient(n, r.client_id)).length > 0 && E.push(r.client_id);
1036
+ }
1037
+ for (let r of E) await t.clientConnections.addClientToConnection(n, e, r);
1038
+ }, O = (e, t) => h[e].has(t) ? (c.changes.push(`skip ${e}:${t} (the tenant has its own)`), c.rows.push({
1039
+ entity: e,
1040
+ key: t,
1041
+ action: "skipped"
1042
+ }), !0) : !1;
1007
1043
  for (let r of e.connections) {
1008
- let e = G("connection", r), i = await _("connection", e);
1009
- await p("connection", e, async () => {
1010
- let { enabled_clients: e, ...a } = r, o = c.parse({
1011
- ...a,
1044
+ let e = W("connection", r), i = await S("connection", e);
1045
+ await y("connection", e, async () => {
1046
+ if (O("connection", e)) return "unchanged";
1047
+ let { enabled_clients: a, ...o } = r, s = l.parse({
1048
+ ...o,
1012
1049
  id: i
1013
- }), s = await t.connections.get(n, i);
1014
- return m({
1015
- existing: s ? c.parse(s) : null,
1016
- desired: o,
1017
- create: () => t.connections.create(n, o),
1018
- update: () => t.connections.update(n, i, o),
1050
+ }), c = await t.connections.get(n, i);
1051
+ return b({
1052
+ existing: c ? l.parse(c) : null,
1053
+ desired: s,
1054
+ create: async () => {
1055
+ await t.connections.create(n, s);
1056
+ try {
1057
+ await D(i);
1058
+ } catch (e) {
1059
+ throw await t.connections.remove(n, i).catch(() => {}), e;
1060
+ }
1061
+ },
1062
+ update: () => t.connections.update(n, i, s),
1019
1063
  view: (e) => e
1020
1064
  });
1021
1065
  });
1022
1066
  }
1023
1067
  for (let r of e.resourceServers) {
1024
- let e = G("resourceServer", r), i = await _("resourceServer", e);
1025
- await p("resourceServer", e, async () => {
1026
- let e = x.parse({
1068
+ let e = W("resourceServer", r), i = await S("resourceServer", e);
1069
+ await y("resourceServer", e, async () => {
1070
+ if (O("resourceServer", e)) return "unchanged";
1071
+ let a = T.parse({
1027
1072
  ...r,
1028
1073
  id: i
1029
- }), a = await t.resourceServers.get(n, i);
1030
- return m({
1031
- existing: a ? x.parse(a) : null,
1032
- desired: e,
1033
- create: () => t.resourceServers.create(n, e),
1034
- update: () => t.resourceServers.update(n, i, e),
1074
+ }), o = await t.resourceServers.get(n, i);
1075
+ return b({
1076
+ existing: o ? T.parse(o) : null,
1077
+ desired: a,
1078
+ create: () => t.resourceServers.create(n, a),
1079
+ update: () => t.resourceServers.update(n, i, a),
1035
1080
  view: (e) => e
1036
1081
  });
1037
1082
  });
1038
1083
  }
1039
1084
  for (let r of e.hookCode) {
1040
- let e = G("hookCode", r), i = v.get(r.id);
1041
- await p("hookCode", e, async () => {
1042
- let e = h.parse(r), a = await t.hookCode.get(n, i);
1043
- return m({
1044
- existing: a ? h.parse(a) : null,
1085
+ let e = W("hookCode", r), i = w.get(r.id);
1086
+ await y("hookCode", e, async () => {
1087
+ let e = _.parse(r), a = await t.hookCode.get(n, i);
1088
+ return b({
1089
+ existing: a ? _.parse(a) : null,
1045
1090
  desired: e,
1046
1091
  create: () => t.hookCode.create(n, e, { importMetadata: { id: i } }),
1047
1092
  update: () => t.hookCode.update(n, i, e),
@@ -1050,28 +1095,29 @@ async function at(e, t, n, r = {}) {
1050
1095
  });
1051
1096
  }
1052
1097
  for (let r of e.actions) {
1053
- let e = G("action", r), a = v.get(r.id);
1054
- await p("action", e, async () => {
1055
- let e = i.parse(r), o = await t.actions.get(n, a);
1056
- return m({
1057
- existing: o ? i.parse(o) : null,
1058
- desired: e,
1059
- create: () => t.actions.create(n, e, { importMetadata: { id: a } }),
1060
- update: () => t.actions.update(n, a, e),
1098
+ let e = W("action", r), i = w.get(r.id);
1099
+ await y("action", e, async () => {
1100
+ if (O("action", e)) return "unchanged";
1101
+ let o = a.parse(r), s = await t.actions.get(n, i);
1102
+ return b({
1103
+ existing: s ? a.parse(s) : null,
1104
+ desired: o,
1105
+ create: () => t.actions.create(n, o, { importMetadata: { id: i } }),
1106
+ update: () => t.actions.update(n, i, o),
1061
1107
  view: (e) => e
1062
1108
  });
1063
1109
  });
1064
1110
  }
1065
1111
  for (let r of e.hooks) {
1066
- let e = G("hook", r), i = await _("hook", e);
1067
- await p("hook", e, async () => {
1068
- let e = r.code_id, a = g.parse({
1112
+ let e = W("hook", r), i = await S("hook", e);
1113
+ await y("hook", e, async () => {
1114
+ let e = r.code_id, a = v.parse({
1069
1115
  ...r,
1070
1116
  hook_id: i,
1071
- ...e ? { code_id: v.get(e) ?? e } : {}
1117
+ ...e ? { code_id: w.get(e) ?? e } : {}
1072
1118
  }), o = await t.hooks.get(n, i);
1073
- return m({
1074
- existing: o ? g.parse(o) : null,
1119
+ return b({
1120
+ existing: o ? v.parse(o) : null,
1075
1121
  desired: a,
1076
1122
  create: () => t.hooks.create(n, a),
1077
1123
  update: () => t.hooks.update(n, i, a),
@@ -1079,29 +1125,109 @@ async function at(e, t, n, r = {}) {
1079
1125
  });
1080
1126
  });
1081
1127
  }
1082
- e.emailProvider && await p("emailProvider", "singleton", async () => {
1083
- let r = f.parse(e.emailProvider);
1084
- return await t.emailProviders.get(n) ? "unchanged" : (a || await t.emailProviders.create(n, r), "added");
1085
- }), e.branding && await p("branding", "singleton", async () => {
1086
- let r = o.parse(e.branding);
1087
- return await t.branding.get(n) ? "unchanged" : (a || await t.branding.set(n, r), "added");
1128
+ let k = (e) => e.override === "none" || e.enforce === !0, A = (e, t, n) => lt(e.parse(t)) === lt(n), j = (e, t) => {
1129
+ let n = { ...t };
1130
+ for (let [t, r] of Object.entries(e)) r != null && n[t] === void 0 && (n[t] = null);
1131
+ return n;
1132
+ };
1133
+ e.emailProvider && await y("emailProvider", "singleton", async () => {
1134
+ let r = p.parse(e.emailProvider), a = await t.emailProviders.get(n);
1135
+ if (!a) return i || await t.emailProviders.create(n, r), "added";
1136
+ if (!k(r) || A(p, a, r)) return "unchanged";
1137
+ if (!i) {
1138
+ let e = p.parse(a);
1139
+ await t.emailProviders.update(n, j(e, r));
1140
+ }
1141
+ return "changed";
1142
+ }), e.branding && await y("branding", "singleton", async () => {
1143
+ let r = s.parse(e.branding), a = await t.branding.get(n);
1144
+ if (!a) return i || await t.branding.set(n, r), "added";
1145
+ if (!k(r) || A(s, a, r)) return "unchanged";
1146
+ if (!i) {
1147
+ let e = s.parse(a), i = j(e, r);
1148
+ e.colors && !r.colors && (i.colors = { primary: null }), e.font && !r.font && (i.font = { url: null }), await t.branding.set(n, i);
1149
+ }
1150
+ return "changed";
1151
+ }), e.promptSettings && k(e.promptSettings) && await y("promptSettings", "singleton", async () => {
1152
+ let r = C.parse(e.promptSettings);
1153
+ return A(C, await t.promptSettings.get(n), r) ? "unchanged" : (i || await t.promptSettings.set(n, r), "changed");
1088
1154
  });
1089
- for (let i of e.deletes) {
1090
- let e = await _(i.entity, i.key), o = `${i.entity}:${i.key}`;
1155
+ for (let a of e.deletes) {
1156
+ let e = await S(a.entity, a.key), o = `${a.entity}:${a.key}`;
1091
1157
  try {
1092
- if (!await ot(t, n, i.entity, e)) continue;
1093
- l.changes.push(`delete ${o}`), r.deletes && !a && (await st(t, n, i.entity, e), l.entities[i.entity].deleted += 1);
1158
+ if (!await pt(t, n, a.entity, e)) continue;
1159
+ c.changes.push(`delete ${o}`), c.rows.push({
1160
+ entity: a.entity,
1161
+ key: a.key,
1162
+ action: "delete"
1163
+ }), r.deletes && !i && (await mt(t, n, a.entity, e), c.entities[a.entity].deleted += 1);
1094
1164
  } catch (e) {
1095
- l.entities[i.entity].errors.push(`delete ${o}: ${e instanceof Error ? e.message : e}`);
1165
+ c.entities[a.entity].errors.push(`delete ${o}: ${e instanceof Error ? e.message : e}`);
1166
+ }
1167
+ }
1168
+ let ee = () => Object.values(c.entities).some((e) => e.errors.length > 0);
1169
+ if (m && !ee()) {
1170
+ let a = /* @__PURE__ */ new Set();
1171
+ for (let t of et) for (let n of dt(e, t)) (t === "connection" || t === "resourceServer" || t === "action") && h[t].has(W(t, n)) || a.add(t === "hookCode" || t === "action" ? w.get(n.id) : await S(t, W(t, n)));
1172
+ for (let e of ft(m, a)) {
1173
+ let a = `${e.entity}:${e.label}`;
1174
+ try {
1175
+ c.changes.push(`delete ${a}`), c.rows.push({
1176
+ entity: e.entity,
1177
+ key: e.label,
1178
+ action: "delete"
1179
+ }), r.prune && !i && (await mt(t, n, e.entity, e.id), c.entities[e.entity].deleted += 1);
1180
+ } catch (t) {
1181
+ c.entities[e.entity].errors.push(`delete ${a}: ${t instanceof Error ? t.message : t}`);
1182
+ }
1096
1183
  }
1097
1184
  }
1098
- let y = Object.values(l.entities).some((e) => e.errors.length > 0);
1099
- return !a && !y && u && await t.tenants.update(n, {
1185
+ let M = ee();
1186
+ return !i && !M && u && await t.tenants.update(n, {
1100
1187
  config_sync_hash: e.hash,
1101
1188
  config_synced_at: (/* @__PURE__ */ new Date()).toISOString()
1102
- }), l;
1189
+ }), c;
1190
+ }
1191
+ function dt(e, t) {
1192
+ switch (t) {
1193
+ case "connection": return e.connections;
1194
+ case "resourceServer": return e.resourceServers;
1195
+ case "hookCode": return e.hookCode;
1196
+ case "action": return e.actions;
1197
+ case "hook": return e.hooks;
1198
+ }
1199
+ }
1200
+ function ft(e, t) {
1201
+ let n = (e) => !!e && x(e) && !t.has(e);
1202
+ return [
1203
+ ...e.hooks.filter((e) => n(e.hook_id)).map((e) => ({
1204
+ entity: "hook",
1205
+ id: e.hook_id,
1206
+ label: e.hook_id
1207
+ })),
1208
+ ...e.actions.filter((e) => n(e.id)).map((e) => ({
1209
+ entity: "action",
1210
+ id: e.id,
1211
+ label: e.name
1212
+ })),
1213
+ ...e.hookCode.filter((e) => n(e.id)).map((e) => ({
1214
+ entity: "hookCode",
1215
+ id: e.id,
1216
+ label: e.id
1217
+ })),
1218
+ ...e.connections.filter((e) => n(e.id)).map((e) => ({
1219
+ entity: "connection",
1220
+ id: e.id,
1221
+ label: `${e.strategy}:${e.name}`
1222
+ })),
1223
+ ...e.resourceServers.filter((e) => n(e.id)).map((e) => ({
1224
+ entity: "resourceServer",
1225
+ id: e.id,
1226
+ label: e.identifier
1227
+ }))
1228
+ ];
1103
1229
  }
1104
- async function ot(e, t, n, r) {
1230
+ async function pt(e, t, n, r) {
1105
1231
  switch (n) {
1106
1232
  case "connection": return !!await e.connections.get(t, r);
1107
1233
  case "resourceServer": return !!await e.resourceServers.get(t, r);
@@ -1110,7 +1236,7 @@ async function ot(e, t, n, r) {
1110
1236
  case "hook": return !!await e.hooks.get(t, r);
1111
1237
  }
1112
1238
  }
1113
- async function st(e, t, n, r) {
1239
+ async function mt(e, t, n, r) {
1114
1240
  switch (n) {
1115
1241
  case "connection":
1116
1242
  await e.connections.remove(t, r);
@@ -1131,22 +1257,27 @@ async function st(e, t, n, r) {
1131
1257
  }
1132
1258
  //#endregion
1133
1259
  //#region src/operations/sync-defaults.ts
1134
- function ct(e) {
1260
+ function ht(e) {
1135
1261
  let t = e.input ?? {};
1136
1262
  return {
1137
1263
  dryRun: t.dry_run === !0,
1138
- force: t.force === !0
1264
+ force: t.force === !0,
1265
+ prune: t.prune === !0
1139
1266
  };
1140
1267
  }
1141
- function lt(e) {
1268
+ function gt(e) {
1142
1269
  return Object.values(e.entities).flatMap((e) => e.errors);
1143
1270
  }
1144
- function ut(e, t) {
1271
+ var _t = 20, vt = 300;
1272
+ function yt(e, t) {
1145
1273
  return {
1146
1274
  dry_run: t.dryRun,
1275
+ prune: t.prune,
1147
1276
  status: e.status,
1148
1277
  hash: e.hash,
1149
1278
  changes: e.changes,
1279
+ rows: e.rows ?? [],
1280
+ error_messages: gt(e).slice(0, _t).map((e) => e.slice(0, vt)),
1150
1281
  entities: Object.fromEntries(Object.entries(e.entities).map(([e, t]) => [e, {
1151
1282
  added: t.added,
1152
1283
  changed: t.changed,
@@ -1156,47 +1287,315 @@ function ut(e, t) {
1156
1287
  }]))
1157
1288
  };
1158
1289
  }
1159
- async function dt(e) {
1290
+ async function bt(e) {
1160
1291
  let { operation: t, syncConfig: n, recorder: r } = e;
1161
1292
  if (!t.tenant_id) throw Error("sync-defaults operations require a tenant_id");
1162
- let i = ct(t), a = await n(t.tenant_id, i), o = ut(a, i);
1293
+ let i = ht(t), a = await n(t.tenant_id, i), o = yt(a, i);
1163
1294
  await r.setResult(t.id, o);
1164
- let s = lt(a);
1295
+ let s = gt(a);
1165
1296
  if (s.length > 0) {
1166
1297
  let e = s.slice(0, 3).join("; ");
1167
1298
  throw Error(`sync-defaults reported ${s.length} error(s): ${e}${s.length > 3 ? "; ..." : ""}`);
1168
1299
  }
1169
1300
  return o;
1170
1301
  }
1171
- function ft(e, t) {
1302
+ function xt(e, t) {
1172
1303
  return async (n, r) => {
1173
1304
  let i = await e.tenants.get(n);
1174
1305
  if (!i) throw Error(`Tenant "${n}" not found`);
1306
+ if (i.config_sync === "detached") throw Error(`Tenant "${n}" is detached from its parent: set config_sync back to "inherit-on-read" or "synced" before syncing it`);
1175
1307
  if (i.deployment_type === "wfp") throw Error(`Tenant "${n}" has its own database: configure a dispatch sync (syncDefaults) for it`);
1176
- return at(await et(e, n, {
1308
+ return ut(await at(e, n, {
1177
1309
  legacyControlPlane: (t.resolveControlPlane ? await t.resolveControlPlane({ tenant_id: n }) : { tenantId: t.controlPlaneTenantId })?.tenantId,
1178
1310
  maxDepth: t.maxDepth
1179
1311
  }), e, n, {
1180
1312
  dryRun: r.dryRun,
1181
- force: r.force
1313
+ force: r.force,
1314
+ prune: r.prune
1182
1315
  });
1183
1316
  };
1184
1317
  }
1185
1318
  //#endregion
1319
+ //#region src/operations/detach.ts
1320
+ function St(e) {
1321
+ let t = e.input ?? {};
1322
+ return {
1323
+ dryRun: t.dry_run === !0,
1324
+ clean: t.clean === !0
1325
+ };
1326
+ }
1327
+ var Ct = 20, wt = 300;
1328
+ function Tt(e) {
1329
+ return Object.entries(e.entities).flatMap(([e, t]) => t.errors.map((t) => `${e} ${t}`));
1330
+ }
1331
+ function Et(e, t) {
1332
+ return {
1333
+ dry_run: t.dryRun,
1334
+ clean: t.clean,
1335
+ status: e.status,
1336
+ changes: e.changes,
1337
+ rows: e.rows ?? [],
1338
+ error_messages: Tt(e).slice(0, Ct).map((e) => e.slice(0, wt)),
1339
+ entities: Object.fromEntries(Object.entries(e.entities).map(([e, t]) => [e, {
1340
+ converted: t.converted,
1341
+ removed: t.removed,
1342
+ skipped: t.skipped,
1343
+ errors: t.errors.length
1344
+ }]))
1345
+ };
1346
+ }
1347
+ async function Dt(e) {
1348
+ let { operation: t, detachTenant: n, recorder: r, onDetached: i } = e;
1349
+ if (!t.tenant_id) throw Error("detach operations require a tenant_id");
1350
+ let a = St(t), o = await n(t.tenant_id, a), s = Et(o, a);
1351
+ await r.setResult(t.id, s);
1352
+ let c = Tt(o);
1353
+ if (c.length === 0 && !a.dryRun && o.status === "detached" && i?.(t.tenant_id), c.length > 0) {
1354
+ let e = c.slice(0, 3).join("; ");
1355
+ throw Error(`detach reported ${c.length} error(s): ${e}${c.length > 3 ? "; ..." : ""}`);
1356
+ }
1357
+ return s;
1358
+ }
1359
+ var K = () => ({
1360
+ converted: 0,
1361
+ removed: 0,
1362
+ skipped: 0,
1363
+ errors: []
1364
+ });
1365
+ function q(e) {
1366
+ let { id: t, hook_id: n, scope: r, override: i, enforce: a, ...o } = e;
1367
+ return o;
1368
+ }
1369
+ function Ot(e) {
1370
+ return {
1371
+ status: e,
1372
+ changes: [],
1373
+ rows: [],
1374
+ entities: {
1375
+ connection: K(),
1376
+ resourceServer: K(),
1377
+ hookCode: K(),
1378
+ action: K(),
1379
+ hook: K()
1380
+ }
1381
+ };
1382
+ }
1383
+ function kt(e, t) {
1384
+ if (t.config_sync !== "synced") throw Error(`Tenant "${e}" is not synced: sync its parent's config into it (config_sync "synced") before detaching, otherwise it would lose what it inherits`);
1385
+ }
1386
+ async function At(e, t) {
1387
+ await e.tenants.update(t, {
1388
+ parent_tenant_id: null,
1389
+ config_sync: "detached",
1390
+ config_sync_hash: null,
1391
+ config_synced_at: null
1392
+ });
1393
+ }
1394
+ async function jt(e, t, n) {
1395
+ let r = Ot(n.dryRun ? "dry-run" : "detached"), { dryRun: i, clean: o } = n, s = await V(e, t), c = {
1396
+ connection: s.connections.filter((e) => x(e.id)),
1397
+ resourceServer: s.resourceServers.filter((e) => x(e.id)),
1398
+ hookCode: s.hookCode.filter((e) => x(e.id)),
1399
+ action: s.actions.filter((e) => x(e.id)),
1400
+ hook: s.hooks.filter((e) => x(e.hook_id))
1401
+ }, u = (e) => e.scope === "platform", d = /* @__PURE__ */ new Set();
1402
+ for (let e of c.hook) {
1403
+ let t = e.code_id;
1404
+ u(e) && t && d.add(t);
1405
+ }
1406
+ for (let e of c.action) u(e) && d.add(e.id);
1407
+ let f = (e, t, n, i = "") => {
1408
+ r.changes.push(`${t} ${e}:${n}${i}`), r.rows.push({
1409
+ entity: e,
1410
+ key: n,
1411
+ action: t === "convert" ? "converted" : t === "remove" ? "removed" : "kept"
1412
+ });
1413
+ }, p = async (e, t, n) => {
1414
+ try {
1415
+ await n();
1416
+ } catch (n) {
1417
+ r.entities[e].errors.push(`${t}: ${n instanceof Error ? n.message : String(n)}`);
1418
+ }
1419
+ }, m = (e, t) => {
1420
+ r.entities[e].skipped += 1, f(e, "skip", t, " (platform: stays a copy)");
1421
+ }, h = [];
1422
+ if (o) {
1423
+ let n = async (n) => {
1424
+ for (let r of await e.clientConnections.listByConnection(t, n)) await e.clientConnections.removeClientFromConnection(t, n, r);
1425
+ }, a = [
1426
+ ...c.hook.map((n) => [
1427
+ "hook",
1428
+ n.hook_id,
1429
+ () => e.hooks.remove(t, n.hook_id)
1430
+ ]),
1431
+ ...c.action.map((n) => [
1432
+ "action",
1433
+ n.name,
1434
+ () => e.actions.remove(t, n.id)
1435
+ ]),
1436
+ ...c.hookCode.map((n) => [
1437
+ "hookCode",
1438
+ n.id,
1439
+ () => e.hookCode.remove(t, n.id)
1440
+ ]),
1441
+ ...c.connection.map((r) => [
1442
+ "connection",
1443
+ `${r.strategy}:${r.name}`,
1444
+ async () => {
1445
+ await n(r.id), await e.connections.remove(t, r.id);
1446
+ }
1447
+ ]),
1448
+ ...c.resourceServer.map((n) => [
1449
+ "resourceServer",
1450
+ n.identifier,
1451
+ () => e.resourceServers.remove(t, n.id)
1452
+ ])
1453
+ ];
1454
+ for (let [e, t, n] of a) f(e, "remove", t), await p(e, t, async () => {
1455
+ i || await n(), r.entities[e].removed += 1;
1456
+ });
1457
+ } else {
1458
+ let n = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Set();
1459
+ for (let a of c.hookCode) {
1460
+ if (d.has(a.id)) {
1461
+ m("hookCode", a.id);
1462
+ continue;
1463
+ }
1464
+ f("hookCode", "convert", a.id), o.add(a.id), await p("hookCode", a.id, async () => {
1465
+ if (!i) {
1466
+ let r = await e.hookCode.create(t, _.parse(q(a)));
1467
+ n.set(a.id, r.id), h.push(async () => {
1468
+ await e.hookCode.remove(t, a.id);
1469
+ });
1470
+ }
1471
+ r.entities.hookCode.converted += 1;
1472
+ });
1473
+ }
1474
+ for (let s of c.action) {
1475
+ if (u(s)) {
1476
+ m("action", s.name);
1477
+ continue;
1478
+ }
1479
+ f("action", "convert", s.name), o.add(s.id), await p("action", s.name, async () => {
1480
+ if (!i) {
1481
+ let r = await e.actions.create(t, a.parse(q(s)));
1482
+ n.set(s.id, r.id), h.push(async () => {
1483
+ await e.actions.remove(t, s.id);
1484
+ });
1485
+ }
1486
+ r.entities.action.converted += 1;
1487
+ });
1488
+ }
1489
+ let s = i ? [] : await g((n) => e.organizations.list(t, n), "organizations", {
1490
+ cursorField: "id",
1491
+ pageSize: 100
1492
+ });
1493
+ for (let n of c.connection) {
1494
+ let a = `${n.strategy}:${n.name}`;
1495
+ if (u(n)) {
1496
+ m("connection", a);
1497
+ continue;
1498
+ }
1499
+ f("connection", "convert", a), await p("connection", a, async () => {
1500
+ if (!i) {
1501
+ let { enabled_clients: r, ...i } = q(n), a = await e.connections.create(t, l.parse(i));
1502
+ for (let r of await e.clientConnections.listByConnection(t, n.id)) await e.clientConnections.addClientToConnection(t, a.id, r), await e.clientConnections.removeClientFromConnection(t, n.id, r);
1503
+ for (let r of s) {
1504
+ let i = (await e.organizationConnections.list(t, r.id)).find((e) => e.connection_id === n.id);
1505
+ if (!i) continue;
1506
+ let { connection_id: o, organization_id: s, ...c } = i;
1507
+ await e.organizationConnections.create(t, r.id, {
1508
+ ...c,
1509
+ connection_id: a.id
1510
+ }), await e.organizationConnections.remove(t, r.id, n.id);
1511
+ }
1512
+ h.push(async () => {
1513
+ await e.connections.remove(t, n.id);
1514
+ });
1515
+ }
1516
+ r.entities.connection.converted += 1;
1517
+ });
1518
+ }
1519
+ for (let n of c.resourceServer) {
1520
+ if (u(n)) {
1521
+ m("resourceServer", n.identifier);
1522
+ continue;
1523
+ }
1524
+ f("resourceServer", "convert", n.identifier), await p("resourceServer", n.identifier, async () => {
1525
+ if (!i) {
1526
+ await e.resourceServers.remove(t, n.id);
1527
+ try {
1528
+ await e.resourceServers.create(t, T.parse(q(n)));
1529
+ } catch (r) {
1530
+ throw await e.resourceServers.create(t, T.parse(n)), r;
1531
+ }
1532
+ }
1533
+ r.entities.resourceServer.converted += 1;
1534
+ });
1535
+ }
1536
+ let y = [];
1537
+ for (let a of c.hook) {
1538
+ let s = a.hook_id, c = a.code_id;
1539
+ if (u(a)) {
1540
+ m("hook", s);
1541
+ continue;
1542
+ }
1543
+ if (c && !(i ? o.has(c) : n.has(c))) {
1544
+ r.entities.hook.skipped += 1, f("hook", "skip", s, " (its code is not converted)");
1545
+ continue;
1546
+ }
1547
+ f("hook", "convert", s), await p("hook", s, async () => {
1548
+ i || (await e.hooks.create(t, v.parse({
1549
+ ...q(a),
1550
+ ...c ? { code_id: n.get(c) } : {}
1551
+ })), y.push(async () => {
1552
+ await e.hooks.remove(t, s);
1553
+ })), r.entities.hook.converted += 1;
1554
+ });
1555
+ }
1556
+ h.unshift(...y);
1557
+ }
1558
+ if (Object.values(r.entities).some((e) => e.errors.length > 0)) return {
1559
+ ...r,
1560
+ status: "partial"
1561
+ };
1562
+ if (i) return r;
1563
+ for (let e of h) try {
1564
+ await e();
1565
+ } catch (e) {
1566
+ r.entities.hook.errors.push(`remove: ${e instanceof Error ? e.message : String(e)}`);
1567
+ }
1568
+ return Object.values(r.entities).some((e) => e.errors.length > 0) ? {
1569
+ ...r,
1570
+ status: "partial"
1571
+ } : r;
1572
+ }
1573
+ function Mt(e) {
1574
+ return async (t, n) => {
1575
+ let r = await e.tenants.get(t);
1576
+ if (!r) throw Error(`Tenant "${t}" not found`);
1577
+ if (r.deployment_type === "wfp") throw Error(`Tenant "${t}" has its own database: configure a dispatch detach for it`);
1578
+ if (r.config_sync === "detached") return Ot("already-detached");
1579
+ kt(t, r);
1580
+ let i = await jt(e, t, n);
1581
+ return i.status === "detached" && await At(e, t), i;
1582
+ };
1583
+ }
1584
+ //#endregion
1186
1585
  //#region src/operations/record-provision.ts
1187
- function pt(e) {
1586
+ function Nt(e) {
1188
1587
  if (e.tenantOperations && e.tenantOperationEvents) return {
1189
1588
  tenantOperations: e.tenantOperations,
1190
1589
  tenantOperationEvents: e.tenantOperationEvents
1191
1590
  };
1192
1591
  }
1193
- async function mt(e, t, n) {
1194
- let r = pt(e);
1592
+ async function Pt(e, t, n) {
1593
+ let r = Nt(e);
1195
1594
  if (!r) {
1196
1595
  await n(void 0);
1197
1596
  return;
1198
1597
  }
1199
- let i = A(r), a = async (e) => {
1598
+ let i = I(r), a = async (e) => {
1200
1599
  try {
1201
1600
  await e();
1202
1601
  } catch (e) {
@@ -1204,7 +1603,7 @@ async function mt(e, t, n) {
1204
1603
  }
1205
1604
  }, o;
1206
1605
  if (await a(async () => {
1207
- let e = await M(r, t, "inline");
1606
+ let e = await se(r, t, "inline");
1208
1607
  o = e.id, await i.markRunning(e.id);
1209
1608
  }), !o) {
1210
1609
  await n(void 0);
@@ -1226,7 +1625,7 @@ async function mt(e, t, n) {
1226
1625
  c || await i.appendEvent(s, {
1227
1626
  step: t.kind,
1228
1627
  outcome: "failed",
1229
- detail: { message: se(e) }
1628
+ detail: { message: F(e) }
1230
1629
  }), await i.markFailed(s, e);
1231
1630
  }), e;
1232
1631
  }
@@ -1238,29 +1637,154 @@ async function mt(e, t, n) {
1238
1637
  });
1239
1638
  }
1240
1639
  //#endregion
1640
+ //#region src/operations/tenant-members-request.ts
1641
+ function Ft(e) {
1642
+ let t = () => {
1643
+ if (!e.tenantMemberRequests) throw Error("The data adapter has no tenantMemberRequests adapter");
1644
+ return e.tenantMemberRequests;
1645
+ };
1646
+ return {
1647
+ get: (e, n) => t().get(e, n),
1648
+ async report(e, n, r) {
1649
+ return t().update(e, n, {
1650
+ status: r.status,
1651
+ result: r.result ?? null,
1652
+ error: r.error ?? null,
1653
+ finished_at: (/* @__PURE__ */ new Date()).toISOString()
1654
+ }, "pending");
1655
+ },
1656
+ async listPending(e, { olderThan: n }) {
1657
+ return (await t().list(e, {
1658
+ status: "pending",
1659
+ created_before: n,
1660
+ per_page: 100
1661
+ })).requests;
1662
+ }
1663
+ };
1664
+ }
1665
+ function It(e) {
1666
+ let t = e.input?.request_id;
1667
+ return typeof t == "string" && t ? t : void 0;
1668
+ }
1669
+ var Lt = 300;
1670
+ async function Rt(e) {
1671
+ let { operation: t, store: n, getBackend: r, recorder: a } = e, o = t.tenant_id, s = It(t);
1672
+ if (!o || !s) throw Error("tenant-members-request operations require a tenant_id and a request_id");
1673
+ let c = await n.get(o, s);
1674
+ if (!c) throw Error(`Request ${s} was not found for tenant ${o}`);
1675
+ if (c.status !== "pending") {
1676
+ let e = {
1677
+ request_id: s,
1678
+ outcome: "already_finished",
1679
+ status: c.status
1680
+ };
1681
+ return await a.setResult(t.id, e), e;
1682
+ }
1683
+ let l;
1684
+ try {
1685
+ l = {
1686
+ status: "succeeded",
1687
+ result: await h(await r(), o, c, e.executeOptions)
1688
+ };
1689
+ } catch (e) {
1690
+ if (!(e instanceof i)) throw e;
1691
+ l = {
1692
+ status: "failed",
1693
+ error: F(e).slice(0, Lt)
1694
+ };
1695
+ }
1696
+ let u = await n.report(o, s, l), d = {
1697
+ request_id: s,
1698
+ outcome: l.status,
1699
+ reported: u,
1700
+ ...l.status === "failed" ? { reason: l.error } : {}
1701
+ };
1702
+ return await a.setResult(t.id, d), d;
1703
+ }
1704
+ var zt = 5;
1705
+ async function Bt(e, t, n, r = {}) {
1706
+ let { operations: i } = await e.stores.tenantOperations.list({
1707
+ tenant_id: t,
1708
+ kind: "tenant-members-request",
1709
+ per_page: 100
1710
+ });
1711
+ return i.find((e) => It(e) === n && (e.status === "pending" || e.status === "running" || e.status === "succeeded")) || ce(e.stores, e.executor, {
1712
+ kind: "tenant-members-request",
1713
+ tenant_id: t,
1714
+ initiated_by: r.initiatedBy,
1715
+ input: { request_id: n }
1716
+ }, { returnFailed: !0 });
1717
+ }
1718
+ async function Vt(e) {
1719
+ let t = e.now?.() ?? /* @__PURE__ */ new Date(), n = new Date(t.getTime() - (e.graceMs ?? 5 * 6e4)).toISOString(), r = e.maxAttempts ?? 5, i = {
1720
+ checked: 0,
1721
+ enqueued: 0,
1722
+ gaveUp: 0,
1723
+ unreachable: []
1724
+ };
1725
+ for (let t of await e.tenantIds()) {
1726
+ let a;
1727
+ try {
1728
+ a = await e.store.listPending(t, { olderThan: n });
1729
+ } catch (e) {
1730
+ console.warn(`[tenant-members] could not read the requests of ${t}:`, e), i.unreachable.push(t);
1731
+ continue;
1732
+ }
1733
+ if (a.length === 0) continue;
1734
+ let { operations: o } = await e.stores.tenantOperations.list({
1735
+ tenant_id: t,
1736
+ kind: "tenant-members-request",
1737
+ per_page: 100
1738
+ });
1739
+ for (let n of a) {
1740
+ i.checked += 1;
1741
+ let a = o.filter((e) => It(e) === n.id);
1742
+ if (!a.some((e) => e.status === "pending" || e.status === "running")) {
1743
+ if (a.filter((e) => e.status === "failed").length >= r) {
1744
+ try {
1745
+ await e.store.report(t, n.id, {
1746
+ status: "failed",
1747
+ error: "The control plane could not carry out this request"
1748
+ }) && (i.gaveUp += 1);
1749
+ } catch (e) {
1750
+ console.warn(`[tenant-members] could not report request ${n.id} as failed:`, e);
1751
+ }
1752
+ continue;
1753
+ }
1754
+ try {
1755
+ await Bt(e, t, n.id), i.enqueued += 1;
1756
+ } catch (e) {
1757
+ console.warn(`[tenant-members] could not enqueue request ${n.id}:`, e);
1758
+ }
1759
+ }
1760
+ }
1761
+ }
1762
+ return i;
1763
+ }
1764
+ //#endregion
1241
1765
  //#region src/hooks/provisioning.ts
1242
- function ht(e) {
1766
+ function Ht(e) {
1243
1767
  return `urn:authhero:tenant:${e.toLowerCase()}`;
1244
1768
  }
1245
- function gt(e) {
1769
+ function Ut(e) {
1246
1770
  return {
1247
1771
  async beforeCreate(e, t) {
1248
1772
  return !t.audience && t.id ? {
1249
1773
  ...t,
1250
- audience: ht(t.id)
1774
+ audience: Ht(t.id)
1251
1775
  } : t;
1252
1776
  },
1253
1777
  async afterCreate(t, i) {
1254
1778
  let { accessControl: a, databaseIsolation: o } = e;
1255
- if (a && t.ctx && await _t(t, i, a), o?.onProvision) {
1779
+ if (a && t.ctx && await Wt(t, i, a), o?.onProvision) {
1256
1780
  let e = o.onProvision;
1257
- o.recordProvisionOperations === !1 ? await e(i.id) : await mt(t.adapters, {
1781
+ o.recordProvisionOperations === !1 ? await e(i.id) : await Pt(t.adapters, {
1258
1782
  kind: "provision",
1259
1783
  tenant_id: i.id,
1260
1784
  initiated_by: t.ctx?.var.user?.sub
1261
1785
  }, (t) => e(i.id, t));
1262
1786
  } else try {
1263
- await te(t.adapters, i.id, {
1787
+ await w(t.adapters, i.id, {
1264
1788
  managementApiIdentifier: n,
1265
1789
  managementApiScopes: r
1266
1790
  });
@@ -1284,14 +1808,14 @@ function gt(e) {
1284
1808
  }
1285
1809
  };
1286
1810
  }
1287
- async function _t(e, t, n) {
1811
+ async function Wt(e, t, n) {
1288
1812
  let { controlPlaneTenantId: r, defaultPermissions: i, defaultRoles: a, issuer: o, adminRoleName: s = "Tenant Admin", adminRoleDescription: c = "Full access to all tenant management operations", addCreatorToOrganization: l = !0 } = n, u = await e.adapters.organizations.create(r, {
1289
1813
  name: t.id,
1290
1814
  display_name: t.friendly_name || t.id
1291
1815
  }), d;
1292
- if (o && (d = await yt(e, r, s, c)), l && e.ctx) {
1816
+ if (o && (d = await Kt(e, r, s, c)), l && e.ctx) {
1293
1817
  let t = e.ctx.var.user;
1294
- if (t?.sub && !await vt(e, r, t.sub)) try {
1818
+ if (t?.sub && !await Gt(e, r, t.sub)) try {
1295
1819
  await e.adapters.userOrganizations.create(r, {
1296
1820
  user_id: t.sub,
1297
1821
  organization_id: u.id
@@ -1302,12 +1826,12 @@ async function _t(e, t, n) {
1302
1826
  }
1303
1827
  a && a.length > 0 && console.log(`Would assign roles ${a.join(", ")} to organization ${u.id}`), i && i.length > 0 && console.log(`Would grant permissions ${i.join(", ")} to organization ${u.id}`);
1304
1828
  }
1305
- async function vt(e, t, r) {
1829
+ async function Gt(e, t, r) {
1306
1830
  let i = await e.adapters.userRoles.list(t, r, void 0, "");
1307
1831
  for (let r of i) if ((await e.adapters.rolePermissions.list(t, r.id, { per_page: 1e3 })).some((e) => e.permission_name === "admin:organizations" && e.resource_server_identifier === n)) return !0;
1308
1832
  return !1;
1309
1833
  }
1310
- async function yt(e, t, i, a) {
1834
+ async function Kt(e, t, i, a) {
1311
1835
  let o = (await e.adapters.roles.list(t, {})).roles.find((e) => e.name === i);
1312
1836
  if (o) return o.id;
1313
1837
  let s = await e.adapters.roles.create(t, {
@@ -1322,11 +1846,11 @@ async function yt(e, t, i, a) {
1322
1846
  }
1323
1847
  //#endregion
1324
1848
  //#region src/hooks/sync.ts
1325
- function bt(e, t, n = () => !0) {
1849
+ function qt(e, t, n = () => !0) {
1326
1850
  let { controlPlaneTenantId: r, getChildTenantIds: i, getAdapters: a } = e, o = /* @__PURE__ */ new Map();
1327
1851
  async function s(e, n, r) {
1328
1852
  return (await t(e).list(n, {
1329
- q: `name:${p(r)}`,
1853
+ q: `name:${m(r)}`,
1330
1854
  per_page: 1
1331
1855
  }))[0] ?? null;
1332
1856
  }
@@ -1377,11 +1901,11 @@ function bt(e, t, n = () => !0) {
1377
1901
  }
1378
1902
  };
1379
1903
  }
1380
- function xt(e, t, n = () => !0) {
1904
+ function Jt(e, t, n = () => !0) {
1381
1905
  let { controlPlaneTenantId: r, getControlPlaneAdapters: i, getAdapters: a } = e;
1382
1906
  return { async afterCreate(e, o) {
1383
1907
  if (o.id !== r) try {
1384
- let e = await i(), s = await a(o.id), c = t(e), l = t(s), u = await m((e) => c.listPaginated(r, e), c.listKey, {
1908
+ let e = await i(), s = await a(o.id), c = t(e), l = t(s), u = await g((e) => c.listPaginated(r, e), c.listKey, {
1385
1909
  cursorField: "id",
1386
1910
  pageSize: 100
1387
1911
  });
@@ -1401,7 +1925,7 @@ function xt(e, t, n = () => !0) {
1401
1925
  }
1402
1926
  } };
1403
1927
  }
1404
- var St = (e) => ({
1928
+ var Yt = (e) => ({
1405
1929
  list: async (t, n) => (await e.resourceServers.list(t, n)).resource_servers,
1406
1930
  listPaginated: (t, n) => e.resourceServers.list(t, n),
1407
1931
  get: (t, n) => e.resourceServers.get(t, n),
@@ -1419,7 +1943,7 @@ var St = (e) => ({
1419
1943
  token_lifetime: e.token_lifetime,
1420
1944
  token_lifetime_for_web: e.token_lifetime_for_web
1421
1945
  })
1422
- }), Ct = (e) => ({
1946
+ }), Xt = (e) => ({
1423
1947
  list: async (t, n) => (await e.roles.list(t, n)).roles,
1424
1948
  listPaginated: (t, n) => e.roles.list(t, n),
1425
1949
  get: (t, n) => e.roles.get(t, n),
@@ -1434,15 +1958,15 @@ var St = (e) => ({
1434
1958
  description: e.description
1435
1959
  })
1436
1960
  });
1437
- function wt(e) {
1961
+ function Zt(e) {
1438
1962
  return e.metadata?.sync !== !1;
1439
1963
  }
1440
- function Tt(e) {
1441
- let { sync: t = {}, filters: n = {} } = e, r = t.resourceServers ?? !0, i = t.roles ?? !0, a = (e) => wt(e) ? n.resourceServers ? n.resourceServers(e) : !0 : !1, o = (e) => wt(e) ? n.roles ? n.roles(e) : !0 : !1, s = r ? bt(e, St, a) : void 0, c = i ? bt(e, Ct, o) : void 0, l = r ? xt(e, St, a) : void 0, u = i ? xt(e, Ct, o) : void 0, d = i ? { async afterCreate(t, r) {
1964
+ function Qt(e) {
1965
+ let { sync: t = {}, filters: n = {} } = e, r = t.resourceServers ?? !0, i = t.roles ?? !0, a = (e) => Zt(e) ? n.resourceServers ? n.resourceServers(e) : !0 : !1, o = (e) => Zt(e) ? n.roles ? n.roles(e) : !0 : !1, s = r ? qt(e, Yt, a) : void 0, c = i ? qt(e, Xt, o) : void 0, l = r ? Jt(e, Yt, a) : void 0, u = i ? Jt(e, Xt, o) : void 0, d = i ? { async afterCreate(t, r) {
1442
1966
  if (r.id !== e.controlPlaneTenantId) {
1443
1967
  await u?.afterCreate?.(t, r);
1444
1968
  try {
1445
- let t = await e.getControlPlaneAdapters(), i = await e.getAdapters(r.id), a = await m((n) => t.roles.list(e.controlPlaneTenantId, n), "roles", {
1969
+ let t = await e.getControlPlaneAdapters(), i = await e.getAdapters(r.id), a = await g((n) => t.roles.list(e.controlPlaneTenantId, n), "roles", {
1446
1970
  cursorField: "id",
1447
1971
  pageSize: 100
1448
1972
  }), o = /* @__PURE__ */ new Map();
@@ -1470,7 +1994,7 @@ function Tt(e) {
1470
1994
  } } : void 0;
1471
1995
  async function f(e, t, n) {
1472
1996
  return (await e.roles.list(t, {
1473
- q: `name:${p(n)}`,
1997
+ q: `name:${m(n)}`,
1474
1998
  per_page: 1
1475
1999
  })).roles[0] ?? null;
1476
2000
  }
@@ -1493,54 +2017,67 @@ function Tt(e) {
1493
2017
  }
1494
2018
  //#endregion
1495
2019
  //#region src/middleware/request-data.ts
1496
- function q(e) {
2020
+ function J(e) {
1497
2021
  return e.var.data ?? e.env.data;
1498
2022
  }
1499
2023
  //#endregion
2024
+ //#region src/utils/tenant-settings.ts
2025
+ async function $t(e, t, n) {
2026
+ let r = !n || n === t, { totals: i } = await e.list({
2027
+ per_page: 1,
2028
+ include_totals: !0,
2029
+ ...r ? {} : { q: `parent_tenant_id:${ee(t)}` }
2030
+ });
2031
+ return {
2032
+ is_control_plane: r,
2033
+ has_children: (i?.length ?? 0) > +!!r
2034
+ };
2035
+ }
2036
+ //#endregion
1500
2037
  //#region src/routes/tenants.ts
1501
- var Et = D.object({
1502
- sub: D.string(),
1503
- tenant_id: D.string().optional(),
1504
- org_id: D.string().optional(),
1505
- scope: D.string().optional(),
1506
- permissions: D.array(D.string()).optional()
2038
+ var en = j.object({
2039
+ sub: j.string(),
2040
+ tenant_id: j.string().optional(),
2041
+ org_id: j.string().optional(),
2042
+ scope: j.string().optional(),
2043
+ permissions: j.array(j.string()).optional()
1507
2044
  }).passthrough();
1508
- function Dt(e) {
1509
- let t = Et.safeParse(e);
2045
+ function tn(e) {
2046
+ let t = en.safeParse(e);
1510
2047
  return t.success ? t.data : void 0;
1511
2048
  }
1512
- function Ot(e, t, n) {
2049
+ function nn(e, t, n) {
1513
2050
  return t ? !e || n ? !1 : e.tenant_id === t : !0;
1514
2051
  }
1515
- function kt(e) {
2052
+ function rn(e) {
1516
2053
  let t = e.permissions ?? [], n = e.scope ? e.scope.split(" ").filter(Boolean) : [], r = new Set([...t, ...n]);
1517
2054
  return r.has("delete:tenants") || r.has("admin:organizations");
1518
2055
  }
1519
- function At(e, t) {
1520
- let n = new T(), r = (t) => {
1521
- let n = Dt(t.var.user);
1522
- return Ot(n, e.accessControl?.controlPlaneTenantId ?? q(t).multiTenancyConfig?.controlPlaneTenantId, !!(n?.org_id ?? t.var.organization_id ?? t.var.org_name));
1523
- };
1524
- if (n.openapi(E({
2056
+ function an(e, t) {
2057
+ let n = new k(), r = (t) => {
2058
+ let n = tn(t.var.user);
2059
+ return nn(n, e.accessControl?.controlPlaneTenantId ?? J(t).multiTenancyConfig?.controlPlaneTenantId, !!(n?.org_id ?? t.var.organization_id ?? t.var.org_name));
2060
+ }, i = (t, n) => $t(J(t).tenants, n, e.accessControl?.controlPlaneTenantId ?? J(t).multiTenancyConfig?.controlPlaneTenantId);
2061
+ if (n.openapi(A({
1525
2062
  tags: ["tenants"],
1526
2063
  method: "get",
1527
2064
  path: "/",
1528
- request: { query: a },
2065
+ request: { query: o },
1529
2066
  security: [{ Bearer: [] }],
1530
2067
  responses: { 200: {
1531
- content: { "application/json": { schema: D.object({
1532
- tenants: D.array(C),
1533
- start: D.number().optional(),
1534
- limit: D.number().optional(),
1535
- length: D.number().optional(),
1536
- total: D.number().optional()
2068
+ content: { "application/json": { schema: j.object({
2069
+ tenants: j.array(D),
2070
+ start: j.number().optional(),
2071
+ limit: j.number().optional(),
2072
+ length: j.number().optional(),
2073
+ total: j.number().optional()
1537
2074
  }) } },
1538
2075
  description: "List of tenants"
1539
2076
  } }
1540
2077
  }), async (t) => {
1541
2078
  let { page: n, per_page: r, include_totals: i, q: a } = t.req.valid("query"), o = t.var.user, s = o?.permissions || [];
1542
2079
  if (!(o?.org_id ?? t.var.organization_id) && s.includes("admin:organizations")) {
1543
- let e = await q(t).tenants.list({
2080
+ let e = await J(t).tenants.list({
1544
2081
  page: n,
1545
2082
  per_page: r,
1546
2083
  include_totals: i,
@@ -1554,10 +2091,10 @@ function At(e, t) {
1554
2091
  total: e.totals?.length
1555
2092
  }) : t.json({ tenants: e.tenants });
1556
2093
  }
1557
- let c = e.accessControl?.controlPlaneTenantId ?? q(t).multiTenancyConfig?.controlPlaneTenantId;
1558
- if (c && !o?.sub) throw new w(403, { message: "Access denied: token has no subject" });
2094
+ let c = e.accessControl?.controlPlaneTenantId ?? J(t).multiTenancyConfig?.controlPlaneTenantId;
2095
+ if (c && !o?.sub) throw new O(403, { message: "Access denied: token has no subject" });
1559
2096
  if (c && o?.sub) {
1560
- let e = (await m((e) => q(t).userOrganizations.listUserOrganizations(c, o.sub, e), "organizations")).map((e) => e.name);
2097
+ let e = (await g((e) => J(t).userOrganizations.listUserOrganizations(c, o.sub, e), "organizations")).map((e) => e.name);
1561
2098
  if (e.length === 0) return i ? t.json({
1562
2099
  tenants: [],
1563
2100
  start: 0,
@@ -1573,20 +2110,20 @@ function At(e, t) {
1573
2110
  length: 0,
1574
2111
  total: s
1575
2112
  }) : t.json({ tenants: [] });
1576
- let p = f.map((e) => `id:${e}`).join(" OR "), h = a ? `(${p}) AND (${a})` : p, g = await q(t).tenants.list({
1577
- q: h,
2113
+ let p = f.map((e) => `id:${e}`).join(" OR "), m = a ? `(${p}) AND (${a})` : p, h = await J(t).tenants.list({
2114
+ q: m,
1578
2115
  per_page: u,
1579
2116
  include_totals: !1
1580
2117
  });
1581
2118
  return i ? t.json({
1582
- tenants: g.tenants,
2119
+ tenants: h.tenants,
1583
2120
  start: d,
1584
2121
  limit: u,
1585
- length: g.tenants.length,
2122
+ length: h.tenants.length,
1586
2123
  total: s
1587
- }) : t.json({ tenants: g.tenants });
2124
+ }) : t.json({ tenants: h.tenants });
1588
2125
  }
1589
- let l = await q(t).tenants.list({
2126
+ let l = await J(t).tenants.list({
1590
2127
  page: n,
1591
2128
  per_page: r,
1592
2129
  include_totals: i,
@@ -1599,44 +2136,44 @@ function At(e, t) {
1599
2136
  length: l.tenants.length,
1600
2137
  total: l.totals?.length
1601
2138
  }) : t.json({ tenants: l.tenants });
1602
- }), n.openapi(E({
2139
+ }), n.openapi(A({
1603
2140
  tags: ["tenants"],
1604
2141
  method: "post",
1605
2142
  path: "/",
1606
- request: { body: { content: { "application/json": { schema: S } } } },
2143
+ request: { body: { content: { "application/json": { schema: E } } } },
1607
2144
  security: [{ Bearer: [] }],
1608
2145
  responses: {
1609
2146
  201: {
1610
- content: { "application/json": { schema: C } },
2147
+ content: { "application/json": { schema: D } },
1611
2148
  description: "Tenant created"
1612
2149
  },
1613
2150
  400: { description: "Validation error" },
1614
2151
  409: { description: "Tenant with this ID already exists" }
1615
2152
  }
1616
2153
  }), async (n) => {
1617
- if (!n.var.user?.sub) throw new w(401, { message: "Authentication required to create tenants" });
2154
+ if (!n.var.user?.sub) throw new O(401, { message: "Authentication required to create tenants" });
1618
2155
  let { config_sync_hash: i, config_synced_at: a, config_sync: o, ...s } = n.req.valid("json"), c = s;
1619
- if (c.parent_tenant_id && !r(n)) throw new w(403, { message: "Only the control plane can set a tenant's parent" });
2156
+ if (c.parent_tenant_id && !r(n)) throw new O(403, { message: "Only the control plane can set a tenant's parent" });
1620
2157
  o !== void 0 && r(n) && (c = {
1621
2158
  ...c,
1622
2159
  config_sync: o
1623
2160
  });
1624
2161
  let l = {
1625
- adapters: q(n),
2162
+ adapters: J(n),
1626
2163
  ctx: n
1627
2164
  };
1628
- t.tenants?.beforeCreate && (c = await t.tenants.beforeCreate(l, c)), await de({
2165
+ t.tenants?.beforeCreate && (c = await t.tenants.beforeCreate(l, c)), await le({
1629
2166
  tenantId: c.id,
1630
2167
  parentTenantId: c.parent_tenant_id,
1631
- getTenant: (e) => q(n).tenants.get(e)
2168
+ getTenant: (e) => J(n).tenants.get(e)
1632
2169
  });
1633
- let u = await q(n).tenants.create(c);
2170
+ let u = await J(n).tenants.create(c);
1634
2171
  return t.tenants?.afterCreate && await t.tenants.afterCreate(l, u), e.onConfigSyncChange?.(u.id), n.json(u, 201);
1635
- }), n.openapi(E({
2172
+ }), n.openapi(A({
1636
2173
  tags: ["tenants"],
1637
2174
  method: "delete",
1638
2175
  path: "/{id}",
1639
- request: { params: D.object({ id: D.string() }) },
2176
+ request: { params: j.object({ id: j.string() }) },
1640
2177
  security: [{ Bearer: ["delete:tenants"] }],
1641
2178
  responses: {
1642
2179
  204: { description: "Tenant deleted" },
@@ -1644,44 +2181,103 @@ function At(e, t) {
1644
2181
  404: { description: "Tenant not found" }
1645
2182
  }
1646
2183
  }), async (n) => {
1647
- let { id: r } = n.req.valid("param"), i = e.accessControl?.controlPlaneTenantId ?? q(n).multiTenancyConfig?.controlPlaneTenantId;
2184
+ let { id: r } = n.req.valid("param"), i = e.accessControl?.controlPlaneTenantId ?? J(n).multiTenancyConfig?.controlPlaneTenantId;
1648
2185
  if (i) {
1649
- let e = Dt(n.var.user);
1650
- if (!e?.sub) throw new w(401, { message: "Authentication required" });
1651
- if (r === i) throw new w(403, { message: "Cannot delete the control plane" });
2186
+ let e = tn(n.var.user);
2187
+ if (!e?.sub) throw new O(401, { message: "Authentication required" });
2188
+ if (r === i) throw new O(403, { message: "Cannot delete the control plane" });
1652
2189
  let t = n.var.org_name, a = r.toLowerCase(), o = !!t && t.toLowerCase() === a;
1653
2190
  if (!o) {
1654
2191
  let r = !!(e.org_id ?? n.var.organization_id ?? t), a = !e.tenant_id || e.tenant_id === i;
1655
- !r && a && kt(e) && (o = !0);
2192
+ !r && a && rn(e) && (o = !0);
1656
2193
  }
1657
- if (o ||= (await m((t) => q(n).userOrganizations.listUserOrganizations(i, e.sub, t), "organizations")).some((e) => e.name?.toLowerCase() === a), !o) throw new w(403, { message: "Access denied to this tenant" });
2194
+ if (o ||= (await g((t) => J(n).userOrganizations.listUserOrganizations(i, e.sub, t), "organizations")).some((e) => e.name?.toLowerCase() === a), !o) throw new O(403, { message: "Access denied to this tenant" });
1658
2195
  }
1659
- if (!await q(n).tenants.get(r)) throw new w(404, { message: "Tenant not found" });
2196
+ if (!await J(n).tenants.get(r)) throw new O(404, { message: "Tenant not found" });
1660
2197
  let a = {
1661
- adapters: q(n),
2198
+ adapters: J(n),
1662
2199
  ctx: n
1663
2200
  };
1664
- return t.tenants?.beforeDelete && await t.tenants.beforeDelete(a, r), await q(n).tenants.remove(r), t.tenants?.afterDelete && await t.tenants.afterDelete(a, r), n.body(null, 204);
1665
- }), e.configSyncStatus) {
2201
+ return t.tenants?.beforeDelete && await t.tenants.beforeDelete(a, r), await J(n).tenants.remove(r), t.tenants?.afterDelete && await t.tenants.afterDelete(a, r), n.body(null, 204);
2202
+ }), e.verifyConfigSync) {
2203
+ let t = e.verifyConfigSync;
2204
+ n.openapi(A({
2205
+ tags: ["tenants"],
2206
+ method: "get",
2207
+ path: "/{id}/config-sync/verify",
2208
+ request: { params: j.object({ id: j.string() }) },
2209
+ security: [{ Bearer: ["read:tenants"] }],
2210
+ responses: {
2211
+ 200: {
2212
+ content: { "application/json": { schema: j.object({
2213
+ tenant_id: j.string(),
2214
+ config_sync: j.enum([
2215
+ "inherit-on-read",
2216
+ "synced",
2217
+ "detached"
2218
+ ]),
2219
+ method: j.enum([
2220
+ "read-time",
2221
+ "sync-dry-run",
2222
+ "not-applicable"
2223
+ ]),
2224
+ ok: j.boolean(),
2225
+ differences: j.array(j.object({
2226
+ entity: j.string(),
2227
+ key: j.string(),
2228
+ kind: j.enum([
2229
+ "missing",
2230
+ "extra",
2231
+ "changed",
2232
+ "stale"
2233
+ ]),
2234
+ fields: j.array(j.string()).optional()
2235
+ })),
2236
+ errors: j.array(j.string())
2237
+ }) } },
2238
+ description: "The tenant's config compared with what its parents publish"
2239
+ },
2240
+ 403: { description: "Not allowed to verify this tenant" },
2241
+ 404: { description: "Tenant not found" },
2242
+ 502: { description: "The tenant's database could not be reached" }
2243
+ }
2244
+ }), async (e) => {
2245
+ let { id: n } = e.req.valid("param");
2246
+ if (n !== e.var.tenant_id && !r(e)) throw new O(403, { message: "Config can only be verified for your own tenant" });
2247
+ let i;
2248
+ try {
2249
+ i = await t(n);
2250
+ } catch (e) {
2251
+ throw console.error(`[multi-tenancy] config verify failed for "${n}":`, e), new O(502, { message: "Could not verify: the tenant's config could not be checked" });
2252
+ }
2253
+ if (!i) throw new O(404, { message: "Tenant not found" });
2254
+ return e.json(i);
2255
+ });
2256
+ }
2257
+ if (e.configSyncStatus) {
1666
2258
  let t = e.configSyncStatus;
1667
- n.openapi(E({
2259
+ n.openapi(A({
1668
2260
  tags: ["tenants"],
1669
2261
  method: "get",
1670
2262
  path: "/{id}/config-sync",
1671
- request: { params: D.object({ id: D.string() }) },
2263
+ request: { params: j.object({ id: j.string() }) },
1672
2264
  security: [{ Bearer: ["read:tenants"] }],
1673
2265
  responses: {
1674
2266
  200: {
1675
- content: { "application/json": { schema: D.object({
1676
- tenant_id: D.string(),
1677
- parent_tenant_id: D.string().nullable(),
1678
- config_sync: D.enum(["inherit-on-read", "synced"]),
1679
- config_sync_hash: D.string().nullable(),
1680
- config_synced_at: D.string().nullable(),
1681
- expected_hash: D.string().nullable(),
1682
- drifted: D.boolean(),
1683
- chain: D.array(D.string()),
1684
- inherited: D.record(D.string(), D.string())
2267
+ content: { "application/json": { schema: j.object({
2268
+ tenant_id: j.string(),
2269
+ parent_tenant_id: j.string().nullable(),
2270
+ config_sync: j.enum([
2271
+ "inherit-on-read",
2272
+ "synced",
2273
+ "detached"
2274
+ ]),
2275
+ config_sync_hash: j.string().nullable(),
2276
+ config_synced_at: j.string().nullable(),
2277
+ expected_hash: j.string().nullable(),
2278
+ drifted: j.boolean(),
2279
+ chain: j.array(j.string()),
2280
+ inherited: j.record(j.string(), j.string())
1685
2281
  }) } },
1686
2282
  description: "Config sync status of the tenant"
1687
2283
  },
@@ -1690,70 +2286,76 @@ function At(e, t) {
1690
2286
  }
1691
2287
  }), async (e) => {
1692
2288
  let { id: n } = e.req.valid("param");
1693
- if (n !== e.var.tenant_id && !r(e)) throw new w(403, { message: "Config sync status is only readable for your own tenant" });
2289
+ if (n !== e.var.tenant_id && !r(e)) throw new O(403, { message: "Config sync status is only readable for your own tenant" });
1694
2290
  let i = await t(n);
1695
- if (!i) throw new w(404, { message: "Tenant not found" });
2291
+ if (!i) throw new O(404, { message: "Tenant not found" });
1696
2292
  return e.json(i);
1697
2293
  });
1698
2294
  }
1699
- return n.openapi(E({
2295
+ return n.openapi(A({
1700
2296
  tags: ["tenants", "settings"],
1701
2297
  method: "get",
1702
2298
  path: "/settings",
1703
- request: { headers: D.object({ "tenant-id": D.string().optional() }) },
2299
+ request: { headers: j.object({ "tenant-id": j.string().optional() }) },
1704
2300
  security: [{ Bearer: ["read:tenants"] }],
1705
2301
  responses: { 200: {
1706
- content: { "application/json": { schema: C } },
2302
+ content: { "application/json": { schema: D } },
1707
2303
  description: "Current tenant settings"
1708
2304
  } }
1709
2305
  }), async (e) => {
1710
- let t = await q(e).tenants.get(e.var.tenant_id);
1711
- if (!t) throw new w(404, { message: "Tenant not found" });
1712
- return e.json(t);
1713
- }), n.openapi(E({
2306
+ let t = await J(e).tenants.get(e.var.tenant_id);
2307
+ if (!t) throw new O(404, { message: "Tenant not found" });
2308
+ return e.json({
2309
+ ...t,
2310
+ ...await i(e, t.id)
2311
+ });
2312
+ }), n.openapi(A({
1714
2313
  tags: ["tenants", "settings"],
1715
2314
  method: "patch",
1716
2315
  path: "/settings",
1717
2316
  request: {
1718
- headers: D.object({ "tenant-id": D.string().optional() }),
1719
- body: { content: { "application/json": { schema: D.object(S.shape).partial() } } }
2317
+ headers: j.object({ "tenant-id": j.string().optional() }),
2318
+ body: { content: { "application/json": { schema: j.object(E.shape).partial() } } }
1720
2319
  },
1721
2320
  security: [{ Bearer: ["update:tenants"] }],
1722
2321
  responses: { 200: {
1723
- content: { "application/json": { schema: C } },
2322
+ content: { "application/json": { schema: D } },
1724
2323
  description: "Updated tenant settings"
1725
2324
  } }
1726
2325
  }), async (t) => {
1727
- let { id: n, config_sync_hash: i, config_synced_at: a, ...o } = t.req.valid("json"), s = await q(t).tenants.get(t.var.tenant_id);
1728
- if (!s) throw new w(404, { message: "Tenant not found" });
1729
- if ("config_sync" in o && (o.config_sync ?? "inherit-on-read") !== (s.config_sync ?? "inherit-on-read") && !r(t)) throw new w(403, { message: "Only the control plane can change a tenant's config_sync mode" });
1730
- if ("default_client_id" in o) {
1731
- let e = o.default_client_id;
2326
+ let { id: n, config_sync_hash: a, config_synced_at: o, ...s } = t.req.valid("json"), c = await J(t).tenants.get(t.var.tenant_id);
2327
+ if (!c) throw new O(404, { message: "Tenant not found" });
2328
+ if ("config_sync" in s && (s.config_sync ?? "inherit-on-read") !== (c.config_sync ?? "inherit-on-read") && !r(t)) throw new O(403, { message: "Only the control plane can change a tenant's config_sync mode" });
2329
+ if ("default_client_id" in s) {
2330
+ let e = s.default_client_id;
1732
2331
  if (typeof e == "string" && e.length > 0) {
1733
- let n = await q(t).clients.get(t.var.tenant_id, e);
1734
- if (!n) throw new w(400, { message: `Client with id '${e}' not found` });
1735
- if (!v(n)) throw new w(400, { message: `Client '${e}' is not an interactive client and cannot be used as the default client` });
2332
+ let n = await J(t).clients.get(t.var.tenant_id, e);
2333
+ if (!n) throw new O(400, { message: `Client with id '${e}' not found` });
2334
+ if (!b(n)) throw new O(400, { message: `Client '${e}' is not an interactive client and cannot be used as the default client` });
1736
2335
  }
1737
2336
  }
1738
- if ("parent_tenant_id" in o) {
1739
- if ((o.parent_tenant_id ?? null) !== (s.parent_tenant_id ?? null) && !r(t)) throw new w(403, { message: "Only the control plane can change a tenant's parent" });
1740
- await de({
2337
+ if ("parent_tenant_id" in s) {
2338
+ if ((s.parent_tenant_id ?? null) !== (c.parent_tenant_id ?? null) && !r(t)) throw new O(403, { message: "Only the control plane can change a tenant's parent" });
2339
+ await le({
1741
2340
  tenantId: t.var.tenant_id,
1742
- parentTenantId: o.parent_tenant_id,
1743
- getTenant: (e) => q(t).tenants.get(e),
1744
- getChildren: async (e) => (await m((e) => q(t).tenants.list(e), "tenants")).filter((t) => t.parent_tenant_id === e).map((e) => e.id)
2341
+ parentTenantId: s.parent_tenant_id,
2342
+ getTenant: (e) => J(t).tenants.get(e),
2343
+ getChildren: async (e) => (await g((e) => J(t).tenants.list(e), "tenants")).filter((t) => t.parent_tenant_id === e).map((e) => e.id)
1745
2344
  });
1746
2345
  }
1747
- let c = d(s, o);
1748
- await q(t).tenants.update(t.var.tenant_id, c), "config_sync" in o && e.onConfigSyncChange?.(t.var.tenant_id);
1749
- let l = await q(t).tenants.get(t.var.tenant_id);
1750
- if (!l) throw new w(500, { message: "Failed to retrieve updated tenant" });
1751
- return t.json(l);
2346
+ let l = f(c, s);
2347
+ await J(t).tenants.update(t.var.tenant_id, l), "config_sync" in s && e.onConfigSyncChange?.(t.var.tenant_id);
2348
+ let u = await J(t).tenants.get(t.var.tenant_id);
2349
+ if (!u) throw new O(500, { message: "Failed to retrieve updated tenant" });
2350
+ return t.json({
2351
+ ...u,
2352
+ ...await i(t, u.id)
2353
+ });
1752
2354
  }), n;
1753
2355
  }
1754
2356
  //#endregion
1755
2357
  //#region src/middleware/protect-synced.ts
1756
- function jt(e) {
2358
+ function on(e) {
1757
2359
  for (let { pattern: t, type: n } of [
1758
2360
  {
1759
2361
  pattern: /\/api\/v2\/resource-servers\/([^/]+)$/,
@@ -1776,7 +2378,7 @@ function jt(e) {
1776
2378
  }
1777
2379
  return null;
1778
2380
  }
1779
- async function Mt(e, t, n) {
2381
+ async function sn(e, t, n) {
1780
2382
  try {
1781
2383
  switch (n.type) {
1782
2384
  case "resource_server": return (await e.resourceServers.get(t, n.id))?.is_system === !0;
@@ -1788,14 +2390,14 @@ async function Mt(e, t, n) {
1788
2390
  return !1;
1789
2391
  }
1790
2392
  }
1791
- function Nt(e) {
2393
+ function cn(e) {
1792
2394
  return {
1793
2395
  resource_server: "resource server",
1794
2396
  role: "role",
1795
2397
  connection: "connection"
1796
2398
  }[e];
1797
2399
  }
1798
- function Pt(e) {
2400
+ function ln(e) {
1799
2401
  for (let { pattern: t, type: n } of [
1800
2402
  {
1801
2403
  pattern: /\/api\/v2\/connections\/([^/]+)$/,
@@ -1826,7 +2428,7 @@ function Pt(e) {
1826
2428
  }
1827
2429
  return null;
1828
2430
  }
1829
- async function Ft(e, t, n) {
2431
+ async function un(e, t, n) {
1830
2432
  try {
1831
2433
  switch (n.type) {
1832
2434
  case "connection": return await e.connections.get(t, n.id);
@@ -1839,38 +2441,38 @@ async function Ft(e, t, n) {
1839
2441
  return null;
1840
2442
  }
1841
2443
  }
1842
- var It = {
2444
+ var dn = {
1843
2445
  connection: ["options"],
1844
2446
  resource_server: ["signing_secret"],
1845
2447
  action: ["secrets"],
1846
2448
  hook: [],
1847
2449
  hook_code: []
1848
- }, Lt = new Set([
2450
+ }, fn = new Set([
1849
2451
  "client_secret",
1850
2452
  "app_secret",
1851
2453
  "twilio_token"
1852
2454
  ]);
1853
- function Rt(e, t) {
2455
+ function pn(e, t) {
1854
2456
  let n = (e) => {
1855
2457
  let { client_secret: t, ...n } = e ?? {};
1856
2458
  return n;
1857
2459
  };
1858
- return zt(n(e), n(t));
2460
+ return mn(n(e), n(t));
1859
2461
  }
1860
- var zt = (e, t) => JSON.stringify(e) === JSON.stringify(t);
1861
- function J(e, t) {
1862
- return new w(403, { message: `This ${e.type.replace("_", " ")} is synced from a parent tenant and ${t}. Make changes in the parent tenant instead.` });
2462
+ var mn = (e, t) => JSON.stringify(e) === JSON.stringify(t);
2463
+ function Y(e, t) {
2464
+ return new O(403, { message: `This ${e.type.replace("_", " ")} is synced from a parent tenant and ${t}. Make changes in the parent tenant instead.` });
1863
2465
  }
1864
- async function Bt(e, t, n) {
1865
- let r = await Ft(q(e), t, n);
2466
+ async function hn(e, t, n) {
2467
+ let r = await un(J(e), t, n);
1866
2468
  if (!r) return;
1867
- if (n.type === "hook_code") throw J(n, "cannot be modified");
2469
+ if (n.type === "hook_code") throw Y(n, "cannot be modified");
1868
2470
  if (e.req.method === "DELETE") {
1869
- if (r.enforce === !0) throw J(n, "cannot be deleted");
2471
+ if (r.enforce === !0) throw Y(n, "cannot be deleted");
1870
2472
  return;
1871
2473
  }
1872
2474
  let i = r.override ?? "fields";
1873
- if (i === "none") throw J(n, "cannot be edited");
2475
+ if (i === "none") throw Y(n, "cannot be edited");
1874
2476
  let a = {};
1875
2477
  try {
1876
2478
  let t = await e.req.raw.clone().json();
@@ -1880,56 +2482,56 @@ async function Bt(e, t, n) {
1880
2482
  "scope",
1881
2483
  "override",
1882
2484
  "enforce"
1883
- ]) if (e in a && !zt(a[e] ?? null, r[e] ?? null)) throw J(n, `has a locked ${e}`);
1884
- if (r.enforce === !0 && a.enabled === !1) throw J(n, "cannot be disabled");
2485
+ ]) if (e in a && !mn(a[e] ?? null, r[e] ?? null)) throw Y(n, `has a locked ${e}`);
2486
+ if (r.enforce === !0 && a.enabled === !1) throw Y(n, "cannot be disabled");
1885
2487
  if (i === "secrets") {
1886
- let e = It[n.type];
2488
+ let e = dn[n.type];
1887
2489
  for (let [t, i] of Object.entries(a)) if (![
1888
2490
  "scope",
1889
2491
  "override",
1890
2492
  "enforce"
1891
- ].includes(t) && !zt(i, r[t])) {
1892
- if (!e.includes(t)) throw J(n, `only allows its secrets to be changed (not ${t})`);
2493
+ ].includes(t) && !mn(i, r[t])) {
2494
+ if (!e.includes(t)) throw Y(n, `only allows its secrets to be changed (not ${t})`);
1893
2495
  if (t === "options" && i && typeof i == "object") {
1894
2496
  let e = r.options ?? {};
1895
- for (let [t, r] of Object.entries(i)) if (!zt(r, e[t]) && !t.endsWith("_hint") && !(Lt.has(t) || t === "configuration" && Rt(r, e[t]))) throw J(n, `only allows its secrets to be changed (not options.${t})`);
2497
+ for (let [t, r] of Object.entries(i)) if (!mn(r, e[t]) && !t.endsWith("_hint") && !(fn.has(t) || t === "configuration" && pn(r, e[t]))) throw Y(n, `only allows its secrets to be changed (not options.${t})`);
1896
2498
  }
1897
2499
  }
1898
2500
  }
1899
2501
  }
1900
- function Vt() {
2502
+ function gn() {
1901
2503
  return async (e, t) => {
1902
2504
  if (![
1903
2505
  "PATCH",
1904
2506
  "PUT",
1905
2507
  "DELETE"
1906
2508
  ].includes(e.req.method)) return t();
1907
- let n = jt(e.req.path), r = Pt(e.req.path);
2509
+ let n = on(e.req.path), r = ln(e.req.path);
1908
2510
  if (!n && !r) return t();
1909
2511
  let i = e.var.tenant_id || e.req.header("x-tenant-id") || e.req.header("tenant-id");
1910
2512
  if (!i) return t();
1911
- if (n && await Mt(q(e), i, n)) throw new w(403, { message: `This ${Nt(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.` });
1912
- return r && y(r.id) && await Bt(e, i, r), t();
2513
+ if (n && await sn(J(e), i, n)) throw new O(403, { message: `This ${cn(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.` });
2514
+ return r && x(r.id) && await hn(e, i, r), t();
1913
2515
  };
1914
2516
  }
1915
2517
  //#endregion
1916
2518
  //#region src/middleware/index.ts
1917
- function Ht(e) {
2519
+ function _n(e) {
1918
2520
  return async (t, n) => {
1919
2521
  let r = t.var.user;
1920
2522
  return r?.tenant_id === e && r.org_name && t.set("tenant_id", r.org_name), n();
1921
2523
  };
1922
2524
  }
1923
- function Ut(e) {
2525
+ function vn(e) {
1924
2526
  return async (t, r) => {
1925
2527
  if (!e.accessControl) return r();
1926
2528
  let { controlPlaneTenantId: i } = e.accessControl, a = t.var.org_name, o = t.var.organization_id, s = a || o, c = t.var.tenant_id, l = t.var.user, u = (l?.aud ? Array.isArray(l.aud) ? l.aud : [l.aud] : []).includes(n);
1927
- if (!c && s && u && (t.set("tenant_id", s), c = s), !c) throw new w(400, { message: "Tenant ID not found in request" });
1928
- if (!O(o, c, i, a)) throw new w(403, { message: `Access denied to tenant ${c}` });
2529
+ if (!c && s && u && (t.set("tenant_id", s), c = s), !c) throw new O(400, { message: "Tenant ID not found in request" });
2530
+ if (!N(o, c, i, a)) throw new O(403, { message: `Access denied to tenant ${c}` });
1929
2531
  return r();
1930
2532
  };
1931
2533
  }
1932
- function Wt(e) {
2534
+ function yn(e) {
1933
2535
  return async (t, n) => {
1934
2536
  if (!e.subdomainRouting) return n();
1935
2537
  let { baseDomain: r, reservedSubdomains: i = [], resolveSubdomain: a } = e.subdomainRouting, o = t.req.header("x-forwarded-host") || t.req.header("host") || "", s = null;
@@ -1941,18 +2543,18 @@ function Wt(e) {
1941
2543
  let c = null;
1942
2544
  if (a) c = await a(s);
1943
2545
  else if (e.subdomainRouting.useOrganizations !== !1 && e.accessControl) try {
1944
- let n = await q(t).organizations.get(e.accessControl.controlPlaneTenantId, s);
2546
+ let n = await J(t).organizations.get(e.accessControl.controlPlaneTenantId, s);
1945
2547
  n && (c = n.id);
1946
2548
  } catch {}
1947
- if (!c) throw new w(404, { message: `Tenant not found for subdomain: ${s}` });
2549
+ if (!c) throw new O(404, { message: `Tenant not found for subdomain: ${s}` });
1948
2550
  return t.set("tenant_id", c), n();
1949
2551
  };
1950
2552
  }
1951
- function Gt(e) {
2553
+ function bn(e) {
1952
2554
  return async (t, n) => {
1953
2555
  if (!e.databaseIsolation) return n();
1954
2556
  let r = t.var.tenant_id;
1955
- if (!r) throw new w(400, { message: "Tenant ID not found in request" });
2557
+ if (!r) throw new O(400, { message: "Tenant ID not found in request" });
1956
2558
  try {
1957
2559
  let n = await e.databaseIsolation.getAdapters(r);
1958
2560
  t.set("baseData", n), t.env = {
@@ -1960,39 +2562,39 @@ function Gt(e) {
1960
2562
  data: n
1961
2563
  };
1962
2564
  } catch (e) {
1963
- throw console.error(`Failed to resolve database for tenant ${r}:`, e), new w(500, { message: "Failed to resolve tenant database" });
2565
+ throw console.error(`Failed to resolve database for tenant ${r}:`, e), new O(500, { message: "Failed to resolve tenant database" });
1964
2566
  }
1965
2567
  return n();
1966
2568
  };
1967
2569
  }
1968
- function Kt(e) {
1969
- let t = Wt(e), n = Ut(e), r = Gt(e);
2570
+ function xn(e) {
2571
+ let t = yn(e), n = vn(e), r = bn(e);
1970
2572
  return async (e, i) => (await t(e, async () => {}), await n(e, async () => {}), await r(e, async () => {}), i());
1971
2573
  }
1972
2574
  //#endregion
1973
2575
  //#region src/rollouts/config.ts
1974
- var qt = [
2576
+ var Sn = [
1975
2577
  10,
1976
2578
  50,
1977
2579
  100
1978
- ], Y = {
2580
+ ], X = {
1979
2581
  canary: 1,
1980
- waves: qt,
2582
+ waves: Sn,
1981
2583
  failure_threshold: .1,
1982
2584
  max_concurrent: 25,
1983
2585
  debounce_ms: 6e4
1984
2586
  };
1985
- function X(e) {
2587
+ function Z(e) {
1986
2588
  let t = e.config ?? {};
1987
2589
  return {
1988
- ...Y,
2590
+ ...X,
1989
2591
  trigger: "manual",
1990
2592
  root_tenant_id: "",
1991
2593
  ...t,
1992
- waves: Array.isArray(t.waves) && t.waves.length > 0 ? t.waves : [...qt]
2594
+ waves: Array.isArray(t.waves) && t.waves.length > 0 ? t.waves : [...Sn]
1993
2595
  };
1994
2596
  }
1995
- function Jt(e, t, n) {
2597
+ function Cn(e, t, n) {
1996
2598
  let r = Array(e).fill(0);
1997
2599
  if (e === 0) return r;
1998
2600
  let i = Math.min(Math.max(t, 0), e), a = [], o = i;
@@ -2010,8 +2612,8 @@ function Jt(e, t, n) {
2010
2612
  }
2011
2613
  //#endregion
2012
2614
  //#region src/rollouts/enumerate.ts
2013
- async function Yt(e, t, n) {
2014
- let r = n.maxDepth ?? 8, i = await m((t) => e.tenants.list(t), "tenants", {
2615
+ async function wn(e, t, n) {
2616
+ let r = n.maxDepth ?? 8, i = await g((t) => e.tenants.list(t), "tenants", {
2015
2617
  cursorField: "id",
2016
2618
  pageSize: 100
2017
2619
  }), a = new Map(i.map((e) => [e.id, e])), o = async (e) => e.parent_tenant_id ?? (e.id === t ? void 0 : await n.resolveLegacyParent(e.id)), s = [];
@@ -2037,19 +2639,19 @@ async function Yt(e, t, n) {
2037
2639
  }
2038
2640
  //#endregion
2039
2641
  //#region src/rollouts/hashes.ts
2040
- async function Xt(e, t) {
2642
+ async function Q(e, t) {
2041
2643
  return e.resolveControlPlane ? (await e.resolveControlPlane({ tenant_id: t }))?.tenantId : e.controlPlaneTenantId;
2042
2644
  }
2043
- function Zt(e) {
2645
+ function Tn(e) {
2044
2646
  let t = /* @__PURE__ */ new Map();
2045
2647
  return async (n) => {
2046
- let r = await Xt(e, n), i = (await N({
2648
+ let r = await Q(e, n), i = (await R({
2047
2649
  tenantId: n,
2048
2650
  getTenant: (t) => e.adapters.tenants.get(t),
2049
2651
  legacyControlPlane: r,
2050
2652
  maxDepth: e.maxDepth
2051
2653
  })).join(">"), a = t.get(i);
2052
- return a || (a = et(e.adapters, n, {
2654
+ return a || (a = at(e.adapters, n, {
2053
2655
  legacyControlPlane: r,
2054
2656
  maxDepth: e.maxDepth
2055
2657
  }).then((e) => e.hash), t.set(i, a)), a;
@@ -2057,13 +2659,13 @@ function Zt(e) {
2057
2659
  }
2058
2660
  //#endregion
2059
2661
  //#region src/rollouts/plan.ts
2060
- var Qt = [
2662
+ var En = [
2061
2663
  "pending",
2062
2664
  "canary",
2063
2665
  "rolling",
2064
2666
  "paused"
2065
2667
  ];
2066
- function $t(e) {
2668
+ function Dn(e) {
2067
2669
  let { tenantOperations: t, tenantOperationEvents: n } = e.adapters;
2068
2670
  if (!t || !n) throw Error("Fleet rollouts need the tenant operations adapters");
2069
2671
  return {
@@ -2071,20 +2673,20 @@ function $t(e) {
2071
2673
  tenantOperationEvents: n
2072
2674
  };
2073
2675
  }
2074
- function Z(e) {
2676
+ function $(e) {
2075
2677
  if (!e.adapters.rollouts) throw Error("Fleet rollouts need the rollouts adapter");
2076
2678
  return e.adapters.rollouts;
2077
2679
  }
2078
- async function en(e, t, n = {}) {
2079
- let r = Z(e), i = $t(e), a = X(t), o = await Yt(e.adapters, a.root_tenant_id, {
2080
- resolveLegacyParent: (t) => Xt(e, t),
2680
+ async function On(e, t, n = {}) {
2681
+ let r = $(e), i = Dn(e), a = Z(t), o = await wn(e.adapters, a.root_tenant_id, {
2682
+ resolveLegacyParent: (t) => Q(e, t),
2081
2683
  maxDepth: e.maxDepth
2082
2684
  });
2083
2685
  if (n.tenantIds) {
2084
2686
  let e = new Set(n.tenantIds);
2085
2687
  o = o.filter((t) => e.has(t.tenantId));
2086
2688
  }
2087
- let s = Zt(e), c = [];
2689
+ let s = Tn(e), c = [];
2088
2690
  for (let e of o) (a.force || e.appliedHash !== await s(e.tenantId)) && c.push(e);
2089
2691
  let l = o.length - c.length;
2090
2692
  if (c.length === 0) return a.trigger === "write" ? await r.remove(t.id) : await r.update(t.id, {
@@ -2099,8 +2701,8 @@ async function en(e, t, n = {}) {
2099
2701
  planned: 0,
2100
2702
  upToDate: l
2101
2703
  };
2102
- let u = new Set((await Q(e, t.id)).map((e) => e.tenant_id)), d = Jt(c.length, a.canary, a.waves);
2103
- for (let [n, r] of c.entries()) u.has(r.tenantId) || await M(i, {
2704
+ let u = new Set((await kn(e, t.id)).map((e) => e.tenant_id)), d = Cn(c.length, a.canary, a.waves);
2705
+ for (let [n, r] of c.entries()) u.has(r.tenantId) || await se(i, {
2104
2706
  kind: "sync-defaults",
2105
2707
  tenant_id: r.tenantId,
2106
2708
  rollout_id: t.id,
@@ -2123,8 +2725,8 @@ async function en(e, t, n = {}) {
2123
2725
  upToDate: l
2124
2726
  };
2125
2727
  }
2126
- async function Q(e, t) {
2127
- let { tenantOperations: n } = $t(e), r = [];
2728
+ async function kn(e, t) {
2729
+ let { tenantOperations: n } = Dn(e), r = [];
2128
2730
  for (let e = 0;; e++) {
2129
2731
  let { operations: i } = await n.list({
2130
2732
  rollout_id: t,
@@ -2137,45 +2739,45 @@ async function Q(e, t) {
2137
2739
  }
2138
2740
  //#endregion
2139
2741
  //#region src/rollouts/advance.ts
2140
- var $ = (e) => {
2742
+ var An = (e) => {
2141
2743
  let t = e.input?.wave;
2142
2744
  return typeof t == "number" ? t : 0;
2143
- }, tn = (e) => e.status === "failed" || e.status === "cancelled";
2144
- function nn(e, t, n) {
2145
- let r = t.filter((e) => $(e) === n), i = r.filter(tn).length, a = n === 0 && e.canary > 0, o = a ? 0 : e.failure_threshold;
2745
+ }, jn = (e) => e.status === "failed" || e.status === "cancelled";
2746
+ function Mn(e, t, n) {
2747
+ let r = t.filter((e) => An(e) === n), i = r.filter(jn).length, a = n === 0 && e.canary > 0, o = a ? 0 : e.failure_threshold;
2146
2748
  return r.length === 0 || i === 0 || i / r.length <= o ? null : `${a ? "canary" : `wave ${n}`} failed for ${i} of ${r.length} tenant(s)`;
2147
2749
  }
2148
- async function rn(e, t) {
2149
- let n = Z(e), r = e.now?.() ?? Date.now(), i = typeof t == "string" ? await n.get(t) : t;
2750
+ async function Nn(e, t) {
2751
+ let n = $(e), r = e.now?.() ?? Date.now(), i = typeof t == "string" ? await n.get(t) : t;
2150
2752
  if (!i || i.kind !== "config-sync") return {
2151
2753
  rolloutId: String(i?.id ?? t),
2152
2754
  outcome: "skipped",
2153
2755
  started: 0
2154
2756
  };
2155
2757
  let a = i.id;
2156
- if (!Qt.includes(i.status) || i.status === "paused") return {
2758
+ if (!En.includes(i.status) || i.status === "paused") return {
2157
2759
  rolloutId: a,
2158
2760
  outcome: "skipped",
2159
2761
  started: 0
2160
2762
  };
2161
- let o = X(i);
2763
+ let o = Z(i);
2162
2764
  if (!o.planned) {
2163
2765
  if (r - Date.parse(i.updated_at) < o.debounce_ms) return {
2164
2766
  rolloutId: a,
2165
2767
  outcome: "waiting",
2166
2768
  started: 0
2167
2769
  };
2168
- let { planned: t } = await en(e, i);
2770
+ let { planned: t } = await On(e, i);
2169
2771
  if (t === 0) return {
2170
2772
  rolloutId: a,
2171
2773
  outcome: "planned-empty",
2172
2774
  started: 0
2173
2775
  };
2174
- i = await n.get(a) ?? i, o = X(i);
2776
+ i = await n.get(a) ?? i, o = Z(i);
2175
2777
  }
2176
- let s = await Q(e, a), c = s.filter((e) => !j(e.status));
2778
+ let s = await kn(e, a), c = s.filter((e) => !L(e.status));
2177
2779
  if (c.length === 0) {
2178
- let e = Math.max(0, ...s.map($)), t = s.length > 0 && e > (o.accepted_through ?? -1) ? nn(o, s, e) : null;
2780
+ let e = Math.max(0, ...s.map(An)), t = s.length > 0 && e > (o.accepted_through ?? -1) ? Mn(o, s, e) : null;
2179
2781
  return await n.update(a, {
2180
2782
  status: t ? "failed" : "done",
2181
2783
  ...t ? { paused_reason: t } : {},
@@ -2186,9 +2788,9 @@ async function rn(e, t) {
2186
2788
  started: 0
2187
2789
  };
2188
2790
  }
2189
- let l = Math.min(...c.map($)), u = l - 1;
2791
+ let l = Math.min(...c.map(An)), u = l - 1;
2190
2792
  if (u >= 0 && u > (o.accepted_through ?? -1)) {
2191
- let e = nn(o, s, u);
2793
+ let e = Mn(o, s, u);
2192
2794
  if (e) return await n.update(a, {
2193
2795
  status: "paused",
2194
2796
  paused_reason: e
@@ -2201,7 +2803,7 @@ async function rn(e, t) {
2201
2803
  }
2202
2804
  let d = l === 0 ? "canary" : "rolling";
2203
2805
  i.status !== d && await n.update(a, { status: d });
2204
- let f = c.filter((e) => $(e) === l), p = f.filter((e) => e.status === "running").length, m = Math.max(0, o.max_concurrent - p), { tenantOperations: h, tenantOperationEvents: g } = $t(e), _ = A({
2806
+ let f = c.filter((e) => An(e) === l), p = f.filter((e) => e.status === "running").length, m = Math.max(0, o.max_concurrent - p), { tenantOperations: h, tenantOperationEvents: g } = Dn(e), _ = I({
2205
2807
  tenantOperations: h,
2206
2808
  tenantOperationEvents: g
2207
2809
  }), v = 0;
@@ -2211,7 +2813,7 @@ async function rn(e, t) {
2211
2813
  } catch (e) {
2212
2814
  try {
2213
2815
  let n = await h.get(t.id);
2214
- n && !j(n.status) && await _.markFailed(t.id, e);
2816
+ n && !L(n.status) && await _.markFailed(t.id, e);
2215
2817
  } catch {}
2216
2818
  }
2217
2819
  v++;
@@ -2223,8 +2825,8 @@ async function rn(e, t) {
2223
2825
  wave: l
2224
2826
  };
2225
2827
  }
2226
- async function an(e, t = {}) {
2227
- let { rollouts: n } = await Z(e).list({
2828
+ async function Pn(e, t = {}) {
2829
+ let { rollouts: n } = await $(e).list({
2228
2830
  kind: "config-sync",
2229
2831
  status: [
2230
2832
  "pending",
@@ -2234,24 +2836,24 @@ async function an(e, t = {}) {
2234
2836
  per_page: t.limit ?? 20
2235
2837
  }), r = [];
2236
2838
  for (let i of n) try {
2237
- r.push(await rn(e, i));
2839
+ r.push(await Nn(e, i));
2238
2840
  } catch (e) {
2239
2841
  t.logger?.warn(`Advancing rollout ${i.id} failed:`, e);
2240
2842
  }
2241
2843
  return r;
2242
2844
  }
2243
- async function on(e, t, n = "paused by an operator") {
2244
- let r = Z(e), i = await r.get(t);
2845
+ async function Fn(e, t, n = "paused by an operator") {
2846
+ let r = $(e), i = await r.get(t);
2245
2847
  return !i || i.kind !== "config-sync" ? null : i.status === "done" || i.status === "failed" ? i : (await r.update(t, {
2246
2848
  status: "paused",
2247
2849
  paused_reason: n
2248
2850
  }), r.get(t));
2249
2851
  }
2250
- async function sn(e, t) {
2251
- let n = Z(e), r = await n.get(t);
2852
+ async function In(e, t) {
2853
+ let n = $(e), r = await n.get(t);
2252
2854
  if (!r || r.kind !== "config-sync") return null;
2253
2855
  if (r.status !== "paused") return r;
2254
- let i = X(r), a = (await Q(e, t)).filter((e) => !j(e.status)), o = a.length > 0 ? Math.min(...a.map($)) : 0;
2856
+ let i = Z(r), a = (await kn(e, t)).filter((e) => !L(e.status)), o = a.length > 0 ? Math.min(...a.map(An)) : 0;
2255
2857
  return await n.update(t, {
2256
2858
  status: o === 0 ? "canary" : "rolling",
2257
2859
  paused_reason: null,
@@ -2262,21 +2864,110 @@ async function sn(e, t) {
2262
2864
  }), n.get(t);
2263
2865
  }
2264
2866
  //#endregion
2867
+ //#region src/rollouts/verify.ts
2868
+ var Ln = {
2869
+ added: "missing",
2870
+ changed: "changed",
2871
+ delete: "stale"
2872
+ };
2873
+ function Rn(e) {
2874
+ return (e.rows ?? e.changes.flatMap((e) => {
2875
+ if (e.startsWith("skip ")) return [];
2876
+ let t = /^delete ([^:\s]+):(.*)$/.exec(e);
2877
+ if (t) return [{
2878
+ entity: t[1],
2879
+ key: t[2],
2880
+ action: "delete"
2881
+ }];
2882
+ let n = /^([^:\s]+):(.*)$/.exec(e);
2883
+ return n ? [{
2884
+ entity: n[1],
2885
+ key: n[2],
2886
+ action: "changed"
2887
+ }] : [];
2888
+ })).flatMap((e) => {
2889
+ let t = Ln[e.action];
2890
+ return t ? [{
2891
+ entity: e.entity,
2892
+ key: e.key,
2893
+ kind: t
2894
+ }] : [];
2895
+ });
2896
+ }
2897
+ async function zn(e, t) {
2898
+ let n = await e.adapters.tenants.get(t);
2899
+ if (!n) return null;
2900
+ let r = n.config_sync ?? "inherit-on-read", i = {
2901
+ tenant_id: t,
2902
+ config_sync: r,
2903
+ errors: []
2904
+ };
2905
+ if (r === "detached") return {
2906
+ ...i,
2907
+ method: "not-applicable",
2908
+ ok: !0,
2909
+ differences: []
2910
+ };
2911
+ if (r === "inherit-on-read") {
2912
+ let n = (await De({
2913
+ adapters: e.adapters,
2914
+ tenantId: t,
2915
+ legacyControlPlane: await Q(e, t),
2916
+ maxDepth: e.maxDepth
2917
+ })).filter((e) => !e.expected).map((e) => ({
2918
+ entity: e.entity,
2919
+ key: e.key,
2920
+ kind: e.kind,
2921
+ ...e.fields.length > 0 ? { fields: e.fields } : {}
2922
+ }));
2923
+ return {
2924
+ ...i,
2925
+ method: "read-time",
2926
+ ok: n.length === 0,
2927
+ differences: n
2928
+ };
2929
+ }
2930
+ let a = await e.syncConfig(t, {
2931
+ dryRun: !0,
2932
+ force: !1,
2933
+ prune: !1
2934
+ }), o = Rn(a), s = Object.entries(a.entities).filter(([, e]) => e.errors.length > 0).map(([e, t]) => `${e}: the sync dry run reported ${t.errors.length} error(s)`);
2935
+ return {
2936
+ ...i,
2937
+ method: "sync-dry-run",
2938
+ ok: o.length === 0 && s.length === 0,
2939
+ differences: o,
2940
+ errors: s.slice(0, 20)
2941
+ };
2942
+ }
2943
+ //#endregion
2265
2944
  //#region src/rollouts/status.ts
2266
- async function cn(e, t) {
2945
+ async function Bn(e, t) {
2267
2946
  let n = await e.adapters.tenants.get(t);
2268
2947
  if (!n) return null;
2269
- let r = n.config_sync === "synced", i = await N({
2948
+ if (n.config_sync === "detached") return {
2949
+ tenant_id: t,
2950
+ parent_tenant_id: null,
2951
+ config_sync: "detached",
2952
+ config_sync_hash: null,
2953
+ config_synced_at: null,
2954
+ expected_hash: null,
2955
+ drifted: !1,
2956
+ chain: [],
2957
+ inherited: {}
2958
+ };
2959
+ let r = n.config_sync === "synced", i = await R({
2270
2960
  tenantId: t,
2271
2961
  getTenant: (t) => e.adapters.tenants.get(t),
2272
- legacyControlPlane: await Xt(e, t),
2962
+ legacyControlPlane: await Q(e, t),
2273
2963
  maxDepth: e.maxDepth
2274
- }), a = r ? await Zt(e)(t) : null, o = n.config_sync_hash ?? null, s = {};
2964
+ }), a = r ? await Tn(e)(t) : null, o = n.config_sync_hash ?? null, s = {};
2275
2965
  for (let n of [...i].reverse()) {
2276
- let r = await I(e.adapters, n), i = (e, t) => V(e, t) === "shared", a = async (e, r, a) => {
2966
+ let r = await V(e.adapters, n), i = (e, t) => U(e, t) === "shared", a = async (e, r, a) => {
2277
2967
  for (let o of r) {
2278
- let r = o.id ?? o.hook_id;
2279
- r && y(r) || i(a, o) && (s[await W(e, t, G(e, o))] = n);
2968
+ if (!i(a, o)) continue;
2969
+ let r = await it(e, t, W(e, o)), c = o.id ?? o.hook_id;
2970
+ c && x(c) && s[r] || (s[r] = n);
2280
2971
  }
2281
2972
  };
2282
2973
  await a("connection", r.connections, "connection"), await a("resourceServer", r.resourceServers, "resourceServer"), await a("action", r.actions, "action"), await a("hook", r.hooks, "hook"), r.emailProvider && i("emailProvider", r.emailProvider) && (s.emailProvider = n), r.branding && i("branding", r.branding) && (s.branding = n), r.promptSettings && i("promptSettings", r.promptSettings) && (s.promptSettings = n);
@@ -2295,11 +2986,11 @@ async function cn(e, t) {
2295
2986
  }
2296
2987
  //#endregion
2297
2988
  //#region src/rollouts/reconcile.ts
2298
- async function ln(e, n = {}) {
2299
- let r = Z(e), i = n.rootTenantId ?? e.controlPlaneTenantId, a = n.limit ?? 500, o = await Yt(e.adapters, i, {
2300
- resolveLegacyParent: (t) => Xt(e, t),
2989
+ async function Vn(e, n = {}) {
2990
+ let r = $(e), i = n.rootTenantId ?? e.controlPlaneTenantId, a = n.limit ?? 500, o = await wn(e.adapters, i, {
2991
+ resolveLegacyParent: (t) => Q(e, t),
2301
2992
  maxDepth: e.maxDepth
2302
- }), s = Zt(e), c = [];
2993
+ }), s = Tn(e), c = [];
2303
2994
  for (let e of o) {
2304
2995
  if (c.length >= a) break;
2305
2996
  try {
@@ -2322,10 +3013,10 @@ async function ln(e, n = {}) {
2322
3013
  if (c.length === 0) return l;
2323
3014
  let u = /* @__PURE__ */ new Set(), { rollouts: d } = await r.list({
2324
3015
  kind: "config-sync",
2325
- status: [...Qt],
3016
+ status: [...En],
2326
3017
  per_page: 100
2327
3018
  });
2328
- for (let t of d) for (let n of await Q(e, t.id)) n.tenant_id && !j(n.status) && u.add(n.tenant_id);
3019
+ for (let t of d) for (let n of await kn(e, t.id)) n.tenant_id && !L(n.status) && u.add(n.tenant_id);
2329
3020
  for (let r of c) try {
2330
3021
  await e.adapters.logs.create(r.tenantId, {
2331
3022
  type: t.CONFIG_DRIFT,
@@ -2345,7 +3036,7 @@ async function ln(e, n = {}) {
2345
3036
  }
2346
3037
  let f = c.filter((e) => !u.has(e.tenantId));
2347
3038
  l.alreadyCovered = c.length - f.length;
2348
- let { tenantOperations: p } = $t(e), m = e.now?.() ?? Date.now(), h = n.retryAfterMs ?? 36e5, g = [];
3039
+ let { tenantOperations: p } = Dn(e), m = e.now?.() ?? Date.now(), h = n.retryAfterMs ?? 36e5, g = [];
2349
3040
  for (let e of f) {
2350
3041
  try {
2351
3042
  let { operations: t } = await p.list({
@@ -2367,33 +3058,33 @@ async function ln(e, n = {}) {
2367
3058
  kind: "config-sync",
2368
3059
  initiated_by: "reconcile",
2369
3060
  config: {
2370
- ...Y,
3061
+ ...X,
2371
3062
  trigger: "reconcile",
2372
3063
  root_tenant_id: i,
2373
3064
  planned: !1
2374
3065
  }
2375
3066
  });
2376
- return await en(e, _, { tenantIds: g.map((e) => e.tenantId) }), l.rolloutId = _.id, l;
3067
+ return await On(e, _, { tenantIds: g.map((e) => e.tenantId) }), l.rolloutId = _.id, l;
2377
3068
  }
2378
3069
  //#endregion
2379
3070
  //#region src/rollouts/trigger.ts
2380
- function un(e, t) {
2381
- return e === "hookCode" ? !0 : !t || typeof t != "object" ? !1 : V(e, t) !== "local";
3071
+ function Hn(e, t) {
3072
+ return e === "hookCode" ? !0 : !t || typeof t != "object" ? !1 : U(e, t) !== "local";
2382
3073
  }
2383
- async function dn(e, t, n) {
2384
- let r = Z(e), { rollouts: i } = await r.list({
3074
+ async function Un(e, t, n) {
3075
+ let r = $(e), { rollouts: i } = await r.list({
2385
3076
  kind: "config-sync",
2386
3077
  status: "pending",
2387
3078
  per_page: 100
2388
3079
  }), a = i.find((e) => {
2389
- let n = X(e);
3080
+ let n = Z(e);
2390
3081
  return n.trigger === "write" && n.planned !== !0 && n.origin_tenant_id === t;
2391
3082
  });
2392
3083
  return a ? (await r.update(a.id, {}), await r.get(a.id) ?? a) : r.create({
2393
3084
  kind: "config-sync",
2394
3085
  initiated_by: n ?? `write:${t}`,
2395
3086
  config: {
2396
- ...Y,
3087
+ ...X,
2397
3088
  trigger: "write",
2398
3089
  root_tenant_id: t,
2399
3090
  origin_tenant_id: t,
@@ -2401,7 +3092,7 @@ async function dn(e, t, n) {
2401
3092
  }
2402
3093
  });
2403
3094
  }
2404
- async function fn(e, t) {
3095
+ async function Wn(e, t) {
2405
3096
  if (t === e.controlPlaneTenantId) return !0;
2406
3097
  try {
2407
3098
  let { tenants: n } = await e.adapters.tenants.list({
@@ -2413,19 +3104,19 @@ async function fn(e, t) {
2413
3104
  return !0;
2414
3105
  }
2415
3106
  }
2416
- function pn(e, t = {}) {
3107
+ function Gn(e, t = {}) {
2417
3108
  let n = async (n) => {
2418
3109
  try {
2419
- await fn(e, n) && await dn(e, n);
3110
+ await Wn(e, n) && await Un(e, n);
2420
3111
  } catch (e) {
2421
3112
  t.logger?.warn(`Could not record a config change for ${n}:`, e);
2422
3113
  }
2423
3114
  }, r = (e) => ({
2424
3115
  afterCreate: async (t, r) => {
2425
- un(e, r) && await n(t.tenantId);
3116
+ Hn(e, r) && await n(t.tenantId);
2426
3117
  },
2427
3118
  afterUpdate: async (t, r, i) => {
2428
- un(e, i) && await n(t.tenantId);
3119
+ Hn(e, i) && await n(t.tenantId);
2429
3120
  },
2430
3121
  afterDelete: async (e) => n(e.tenantId)
2431
3122
  });
@@ -2439,79 +3130,89 @@ function pn(e, t = {}) {
2439
3130
  }
2440
3131
  //#endregion
2441
3132
  //#region src/rollouts/controller.ts
2442
- function mn(e) {
3133
+ function Kn(e) {
2443
3134
  return {
2444
3135
  async create(t) {
2445
3136
  let n = {
2446
- ...Y,
2447
- waves: t.waves ?? [...Y.waves],
2448
- canary: t.canary ?? Y.canary,
2449
- failure_threshold: t.failureThreshold ?? Y.failure_threshold,
2450
- max_concurrent: t.maxConcurrent ?? Y.max_concurrent,
3137
+ ...X,
3138
+ waves: t.waves ?? [...X.waves],
3139
+ canary: t.canary ?? X.canary,
3140
+ failure_threshold: t.failureThreshold ?? X.failure_threshold,
3141
+ max_concurrent: t.maxConcurrent ?? X.max_concurrent,
2451
3142
  trigger: "manual",
2452
3143
  root_tenant_id: t.rootTenantId ?? e.controlPlaneTenantId,
2453
3144
  dry_run: t.dryRun,
2454
3145
  force: t.force,
2455
3146
  planned: !1
2456
- }, r = Z(e), i = await r.create({
3147
+ }, r = $(e), i = await r.create({
2457
3148
  kind: "config-sync",
2458
3149
  initiated_by: t.initiatedBy,
2459
3150
  config: n
2460
3151
  });
2461
- return await en(e, i, { tenantIds: t.tenantIds }), await rn(e, i.id), await r.get(i.id) ?? i;
3152
+ return await On(e, i, { tenantIds: t.tenantIds }), await Nn(e, i.id), await r.get(i.id) ?? i;
2462
3153
  },
2463
- pause: (t, n) => on(e, t, n),
2464
- resume: (t) => sn(e, t)
3154
+ pause: (t, n) => Fn(e, t, n),
3155
+ resume: (t) => In(e, t)
2465
3156
  };
2466
3157
  }
2467
3158
  //#endregion
2468
3159
  //#region src/init.ts
2469
- function hn(e) {
2470
- let { dataAdapter: t, controlPlane: n, controlPlane: { tenantId: r = "control_plane", clientId: i } = {}, resolveControlPlane: a, inheritanceShadow: o, syncDefaults: s, rolloutExecutor: c, sync: l = {
3160
+ function qn(e) {
3161
+ let { dataAdapter: t, controlPlane: n, controlPlane: { tenantId: r = "control_plane", clientId: i } = {}, resolveControlPlane: a, inheritanceShadow: o, syncDefaults: s, detachTenant: c, tenantMemberRequests: l, rolloutExecutor: u, sync: d = {
2471
3162
  resourceServers: !0,
2472
3163
  roles: !0
2473
- }, defaultPermissions: u = ["tenant:admin"], requireOrganizationMatch: d = !1, managementApiExtensions: f = [], entityHooks: p, getChildTenantIds: h, getAdapters: g, ...v } = e;
3164
+ }, defaultPermissions: f = ["tenant:admin"], requireOrganizationMatch: p = !1, managementApiExtensions: m = [], entityHooks: h, getChildTenantIds: _, getAdapters: v, ...b } = e;
2474
3165
  if (a && !n) throw Error("initMultiTenant: `resolveControlPlane` requires `controlPlane` to be set. The static `controlPlane.tenantId` is used for access control, sync direction, and tenant management routing; the resolver only overrides per-tenant runtime inheritance lookups on top of it.");
2475
- let y = t, b = t, ee;
3166
+ let x = t, S = t, C;
2476
3167
  if (n) {
2477
- let e = Pe({
3168
+ let n = Me({
2478
3169
  base: Re({
2479
3170
  controlPlaneTenantId: r,
2480
3171
  controlPlaneClientId: i,
2481
3172
  resolveControlPlane: a
2482
3173
  }),
2483
3174
  getTenant: async (e) => await t.tenants.get(e) ?? null,
2484
- controlPlaneTenantId: r
3175
+ controlPlaneTenantId: r,
3176
+ ttlMs: e.configSyncCacheTtlMs
2485
3177
  });
2486
- ee = (t) => e.invalidate(t), y = Ue(t, {
3178
+ C = (e) => n.invalidate(e), x = We(t, {
2487
3179
  controlPlaneTenantId: r,
2488
3180
  controlPlaneClientId: i,
2489
3181
  resolveControlPlane: a,
2490
3182
  inheritanceShadow: o,
2491
- configSync: e
2492
- }), b = {
3183
+ configSync: n
3184
+ }), S = {
2493
3185
  ...Be(t, {
2494
3186
  controlPlaneTenantId: r,
2495
- resolveControlPlane: e.resolve
3187
+ resolveControlPlane: n.resolve
2496
3188
  }),
2497
3189
  multiTenancyConfig: {
2498
3190
  controlPlaneTenantId: r,
2499
3191
  controlPlaneClientId: i,
2500
- resolveControlPlane: e.resolve
3192
+ resolveControlPlane: n.resolve
2501
3193
  }
2502
3194
  };
2503
3195
  }
2504
- let te = v.tenantOperationExecutor, x;
3196
+ let w = b.tenantOperationExecutor, T, E;
2505
3197
  if (t.tenantOperations && t.tenantOperationEvents) {
2506
3198
  let e = {
2507
3199
  tenantOperations: t.tenantOperations,
2508
3200
  tenantOperationEvents: t.tenantOperationEvents
2509
- }, n = v.tenantUpgrade, i = A(e), o = s ?? ft(t, {
3201
+ }, n = b.tenantUpgrade, i = I(e), o = s ?? xt(t, {
2510
3202
  controlPlaneTenantId: r,
2511
3203
  resolveControlPlane: a
2512
- }), c = le({
3204
+ }), u = c ?? Mt(t), d = l ? l.store ?? Ft(t) : void 0, f = oe({
2513
3205
  stores: e,
2514
3206
  definitions: {
3207
+ detach: (e) => [{
3208
+ name: "detach",
3209
+ run: () => Dt({
3210
+ operation: e,
3211
+ detachTenant: u,
3212
+ recorder: i,
3213
+ onDetached: (e) => C?.(e)
3214
+ })
3215
+ }],
2515
3216
  ...n ? { upgrade: (e) => [{
2516
3217
  name: "upgrade",
2517
3218
  async run() {
@@ -2521,113 +3222,157 @@ function hn(e) {
2521
3222
  }] } : {},
2522
3223
  "sync-defaults": (e) => [{
2523
3224
  name: "sync-defaults",
2524
- run: () => dt({
3225
+ run: () => bt({
2525
3226
  operation: e,
2526
3227
  syncConfig: o,
2527
3228
  recorder: i
2528
3229
  })
2529
- }]
3230
+ }],
3231
+ ...d && l ? { "tenant-members-request": (e) => [{
3232
+ name: "tenant-members-request",
3233
+ run: () => Rt({
3234
+ operation: e,
3235
+ store: d,
3236
+ getBackend: l.getBackend,
3237
+ recorder: i,
3238
+ executeOptions: { isRequesterAllowed: l.isRequesterAllowed }
3239
+ })
3240
+ }] } : {}
2530
3241
  }
2531
3242
  });
2532
- x = c, te ??= {
2533
- engine: c.engine,
2534
- kinds: n ? ["upgrade", "sync-defaults"] : ["sync-defaults"],
2535
- enqueue: (t) => ue(e, c, {
3243
+ if (T = f, d) {
3244
+ let n = {
3245
+ stores: e,
3246
+ executor: f
3247
+ };
3248
+ E = {
3249
+ enqueue: (e, t) => Bt(n, e, t),
3250
+ reconcile: (e = {}) => Vt({
3251
+ ...n,
3252
+ store: d,
3253
+ tenantIds: e.tenantIds ?? (async () => (await g((e) => t.tenants.list(e), "tenants", {
3254
+ cursorField: "id",
3255
+ pageSize: 100
3256
+ })).map((e) => e.id).filter((e) => e !== r)),
3257
+ graceMs: e.graceMs,
3258
+ maxAttempts: e.maxAttempts
3259
+ })
3260
+ };
3261
+ }
3262
+ w ??= {
3263
+ engine: f.engine,
3264
+ kinds: n ? [
3265
+ "upgrade",
3266
+ "sync-defaults",
3267
+ "detach"
3268
+ ] : ["sync-defaults", "detach"],
3269
+ enqueue: (t) => ce(e, f, {
2536
3270
  ...t,
2537
3271
  tenant_id: t.tenant_id
2538
- }, { returnFailed: t.kind === "sync-defaults" })
3272
+ }, { returnFailed: t.kind === "sync-defaults" || t.kind === "detach" })
2539
3273
  };
2540
3274
  }
2541
- let S = c ?? x, C = S && t.rollouts && t.tenantOperations && t.tenantOperationEvents ? {
3275
+ if (l && !E) throw Error("initMultiTenant: `tenantMemberRequests` requires the `tenantOperations` and `tenantOperationEvents` adapters on the data adapter, which run the `tenant-members-request` operation.");
3276
+ let D = u ?? T, O = D && t.rollouts && t.tenantOperations && t.tenantOperationEvents ? {
2542
3277
  adapters: t,
2543
- executor: S,
3278
+ executor: D,
2544
3279
  controlPlaneTenantId: r,
2545
3280
  resolveControlPlane: a
2546
- } : void 0, w = C ? mn(C) : void 0, T = C ? pn(C, { logger: console }) : void 0, E = l !== !1, D = E ? {
2547
- resourceServers: l.resourceServers ?? !0,
2548
- roles: l.roles ?? !0
3281
+ } : void 0, k = O ? Kn(O) : void 0, A = O ? Gn(O, { logger: console }) : void 0, j = d !== !1, ee = j ? {
3282
+ resourceServers: d.resourceServers ?? !0,
3283
+ roles: d.roles ?? !0
2549
3284
  } : {
2550
3285
  resourceServers: !1,
2551
3286
  roles: !1
2552
- }, { entityHooks: ne, tenantHooks: O } = Tt({
3287
+ }, { entityHooks: M, tenantHooks: N } = Qt({
2553
3288
  controlPlaneTenantId: r,
2554
- getChildTenantIds: h ?? (async () => (await m((e) => y.tenants.list(e), "tenants", {
3289
+ getChildTenantIds: _ ?? (async () => (await g((e) => x.tenants.list(e), "tenants", {
2555
3290
  cursorField: "id",
2556
3291
  pageSize: 100
2557
3292
  })).filter((e) => e.id !== r).map((e) => e.id)),
2558
- getAdapters: g ?? (async () => y),
2559
- getControlPlaneAdapters: async () => y,
2560
- sync: D
2561
- }), re = {
3293
+ getAdapters: v ?? (async () => x),
3294
+ getControlPlaneAdapters: async () => x,
3295
+ sync: ee
3296
+ }), te = {
2562
3297
  resourceServers: [
2563
- ne.resourceServers,
2564
- T?.resourceServers,
2565
- ...p?.resourceServers ?? []
3298
+ M.resourceServers,
3299
+ A?.resourceServers,
3300
+ ...h?.resourceServers ?? []
2566
3301
  ],
2567
- roles: [ne.roles, ...p?.roles ?? []],
2568
- connections: [T?.connections, ...p?.connections ?? []],
2569
- tenants: p?.tenants ?? [],
2570
- rolePermissions: p?.rolePermissions ?? [],
2571
- actions: [T?.actions, ...p?.actions ?? []],
2572
- hooks: [T?.hooks, ...p?.hooks ?? []],
2573
- hookCode: [T?.hookCode, ...p?.hookCode ?? []]
2574
- }, k = gt({ accessControl: {
3302
+ roles: [M.roles, ...h?.roles ?? []],
3303
+ connections: [A?.connections, ...h?.connections ?? []],
3304
+ tenants: h?.tenants ?? [],
3305
+ rolePermissions: h?.rolePermissions ?? [],
3306
+ actions: [A?.actions, ...h?.actions ?? []],
3307
+ hooks: [A?.hooks, ...h?.hooks ?? []],
3308
+ hookCode: [A?.hookCode, ...h?.hookCode ?? []]
3309
+ }, P = Ut({ accessControl: {
2575
3310
  controlPlaneTenantId: r,
2576
- requireOrganizationMatch: d,
2577
- defaultPermissions: u
2578
- } }), ie = At({
3311
+ requireOrganizationMatch: p,
3312
+ defaultPermissions: f
3313
+ } }), ne = an({
2579
3314
  accessControl: {
2580
3315
  controlPlaneTenantId: r,
2581
- requireOrganizationMatch: d,
2582
- defaultPermissions: u
3316
+ requireOrganizationMatch: p,
3317
+ defaultPermissions: f
2583
3318
  },
2584
- onConfigSyncChange: (e) => ee?.(e),
2585
- configSyncStatus: (e) => cn({
3319
+ onConfigSyncChange: (e) => C?.(e),
3320
+ configSyncStatus: (e) => Bn({
2586
3321
  adapters: t,
2587
3322
  controlPlaneTenantId: r,
2588
3323
  resolveControlPlane: a
3324
+ }, e),
3325
+ verifyConfigSync: (e) => zn({
3326
+ adapters: t,
3327
+ controlPlaneTenantId: r,
3328
+ resolveControlPlane: a,
3329
+ syncConfig: s ?? xt(t, {
3330
+ controlPlaneTenantId: r,
3331
+ resolveControlPlane: a
3332
+ })
2589
3333
  }, e)
2590
3334
  }, { tenants: {
2591
3335
  async beforeCreate(e, t) {
2592
- return k.beforeCreate && (t = await k.beforeCreate(e, t)), O.beforeCreate && (t = await O.beforeCreate(e, t)), t;
3336
+ return P.beforeCreate && (t = await P.beforeCreate(e, t)), N.beforeCreate && (t = await N.beforeCreate(e, t)), t;
2593
3337
  },
2594
3338
  async afterCreate(e, t) {
2595
- await k.afterCreate?.(e, t), await O.afterCreate?.(e, t);
3339
+ await P.afterCreate?.(e, t), await N.afterCreate?.(e, t);
2596
3340
  },
2597
3341
  async beforeDelete(e, t) {
2598
- await k.beforeDelete?.(e, t), await O.beforeDelete?.(e, t);
2599
- }
2600
- } }), { app: ae } = _({
2601
- dataAdapter: y,
2602
- managementDataAdapter: b,
2603
- ...v,
2604
- tenantOperationExecutor: te,
2605
- ...w ? { rolloutController: w } : {},
2606
- entityHooks: re,
2607
- managementApiExtensions: [...f, {
3342
+ await P.beforeDelete?.(e, t), await N.beforeDelete?.(e, t);
3343
+ }
3344
+ } }), { app: re } = y({
3345
+ dataAdapter: x,
3346
+ managementDataAdapter: S,
3347
+ ...b,
3348
+ tenantOperationExecutor: w,
3349
+ ...k ? { rolloutController: k } : {},
3350
+ entityHooks: te,
3351
+ managementApiExtensions: [...m, {
2608
3352
  path: "/tenants",
2609
- router: ie
3353
+ router: ne
2610
3354
  }],
2611
- managementApiMiddleware: [...v.managementApiMiddleware ?? [], ...E ? [Vt()] : []]
3355
+ managementApiMiddleware: [...b.managementApiMiddleware ?? [], ...j ? [gn()] : []]
2612
3356
  });
2613
3357
  return {
2614
- app: ae,
3358
+ app: re,
2615
3359
  controlPlaneTenantId: r,
2616
- rollouts: C
3360
+ rollouts: O,
3361
+ memberRequests: E
2617
3362
  };
2618
3363
  }
2619
3364
  //#endregion
2620
3365
  //#region src/rollout/payload.ts
2621
- function gn(e) {
3366
+ function Jn(e) {
2622
3367
  let { pkcs7: t, tenant_id: n, ...r } = e;
2623
3368
  return r;
2624
3369
  }
2625
- async function _n(e, t, n = {}, r) {
2626
- let i = he(n), a = n.signingKeys ?? !0, o = n.tenants ?? !0, s = await ve(e, t, i), c = a ? (await b(e.keys)).map(gn) : [], l = o ? await vn(e, t, r) : [];
3370
+ async function Yn(e, t, n = {}, r) {
3371
+ let i = pe(n), a = n.signingKeys ?? !0, o = n.tenants ?? !0, s = await ge(e, t, i), c = a ? (await S(e.keys)).map(Jn) : [], l = o ? await Xn(e, t, r) : [];
2627
3372
  return {
2628
3373
  connections: s.connections,
2629
3374
  resourceServers: s.resourceServers.filter((e) => e.is_system),
2630
- hooks: s.hooks.filter(_e),
3375
+ hooks: s.hooks.filter(he),
2631
3376
  emailProvider: s.emailProvider,
2632
3377
  branding: s.branding,
2633
3378
  promptSettings: s.promptSettings,
@@ -2635,7 +3380,7 @@ async function _n(e, t, n = {}, r) {
2635
3380
  tenants: l
2636
3381
  };
2637
3382
  }
2638
- async function vn(e, t, n) {
3383
+ async function Xn(e, t, n) {
2639
3384
  let r = n && n !== t ? [t, n] : [t], i = [];
2640
3385
  for (let t of r) {
2641
3386
  let n = await e.tenants.get(t);
@@ -2646,19 +3391,19 @@ async function vn(e, t, n) {
2646
3391
  }
2647
3392
  return i;
2648
3393
  }
2649
- async function yn(e, t, n) {
2650
- let r = P();
3394
+ async function Zn(e, t, n) {
3395
+ let r = z();
2651
3396
  if (e.length === 0) return r;
2652
- let i = await b(t.keys), a = new Set(i.map((e) => e.kid));
2653
- for (let i of e) await F(r, `signing_key ${i.kid}`, n, async () => {
2654
- let e = gn(i);
3397
+ let i = await S(t.keys), a = new Set(i.map((e) => e.kid));
3398
+ for (let i of e) await B(r, `signing_key ${i.kid}`, n, async () => {
3399
+ let e = Jn(i);
2655
3400
  a.has(e.kid) || (await t.keys.create(e), a.add(e.kid), r.upserted += 1);
2656
3401
  });
2657
3402
  return r;
2658
3403
  }
2659
- async function bn(e, t, n) {
2660
- let r = P();
2661
- for (let i of e) await F(r, `tenant ${i.id}`, n, async () => {
3404
+ async function Qn(e, t, n) {
3405
+ let r = z();
3406
+ for (let i of e) await B(r, `tenant ${i.id}`, n, async () => {
2662
3407
  await t.tenants.get(i.id) || (await t.tenants.create({
2663
3408
  id: i.id,
2664
3409
  friendly_name: i.friendly_name
@@ -2666,50 +3411,50 @@ async function bn(e, t, n) {
2666
3411
  });
2667
3412
  return r;
2668
3413
  }
2669
- async function xn(e, t, n, r = {}) {
2670
- let i = r.continueOnError ?? !1, a = he(r.entities), s = r.entities?.signingKeys ?? !0, c = r.entities?.tenants ?? !0, l = {
3414
+ async function $n(e, t, n, r = {}) {
3415
+ let i = r.continueOnError ?? !1, a = pe(r.entities), o = r.entities?.signingKeys ?? !0, c = r.entities?.tenants ?? !0, l = {
2671
3416
  connections: e.connections,
2672
3417
  resourceServers: e.resourceServers,
2673
3418
  hooks: e.hooks,
2674
- emailProvider: e.emailProvider ? f.parse(e.emailProvider) : null,
2675
- branding: e.branding ? o.parse(e.branding) : null,
2676
- promptSettings: e.promptSettings ? ee.parse(e.promptSettings) : null
2677
- }, u = c ? await bn(e.tenants ?? [], t, i) : P(), d = ge(n);
2678
- await ye(l, t, n, a, i, d);
2679
- let p = s ? await yn(e.signingKeys, t, i) : P(), m = e.resolved && r.resolved ? await at(e.resolved, t, r.resolved.tenantId, {
3419
+ emailProvider: e.emailProvider ? p.parse(e.emailProvider) : null,
3420
+ branding: e.branding ? s.parse(e.branding) : null,
3421
+ promptSettings: e.promptSettings ? C.parse(e.promptSettings) : null
3422
+ }, u = c ? await Qn(e.tenants ?? [], t, i) : z(), d = me(n);
3423
+ await _e(l, t, n, a, i, d);
3424
+ let f = o ? await Zn(e.signingKeys, t, i) : z(), m = e.resolved && r.resolved ? await ut(e.resolved, t, r.resolved.tenantId, {
2680
3425
  continueOnError: i,
2681
3426
  ...r.resolved
2682
3427
  }) : void 0;
2683
3428
  return {
2684
3429
  ...d,
2685
- signingKeys: p,
3430
+ signingKeys: f,
2686
3431
  tenants: u,
2687
3432
  ...m ? { resolved: m } : {}
2688
3433
  };
2689
3434
  }
2690
3435
  //#endregion
2691
3436
  //#region src/rollout/index.ts
2692
- function Sn(e) {
3437
+ function er(e) {
2693
3438
  return {
2694
- syncDefaults: (t) => be(e, t),
3439
+ syncDefaults: (t) => ve(e, t),
2695
3440
  syncDefaultsToTenants: async (t) => {
2696
3441
  let n = [];
2697
- for (let r of t) n.push(await be(e, r));
3442
+ for (let r of t) n.push(await ve(e, r));
2698
3443
  return n;
2699
3444
  }
2700
3445
  };
2701
3446
  }
2702
3447
  //#endregion
2703
3448
  //#region src/plugin.ts
2704
- function Cn(e) {
2705
- let t = wn(e);
3449
+ function tr(e) {
3450
+ let t = nr(e);
2706
3451
  return {
2707
3452
  name: "multi-tenancy",
2708
- middleware: Kt(e),
3453
+ middleware: xn(e),
2709
3454
  hooks: t,
2710
3455
  routes: [{
2711
3456
  path: "/management",
2712
- handler: At(e, t)
3457
+ handler: an(e, t)
2713
3458
  }],
2714
3459
  onRegister: async () => {
2715
3460
  console.log("Multi-tenancy plugin registered"), e.accessControl && console.log(` - Access control enabled (control plane: ${e.accessControl.controlPlaneTenantId})`), e.subdomainRouting && console.log(` - Subdomain routing enabled (base domain: ${e.subdomainRouting.baseDomain})`), e.databaseIsolation && console.log(" - Database isolation enabled");
@@ -2718,29 +3463,29 @@ function Cn(e) {
2718
3463
  }
2719
3464
  //#endregion
2720
3465
  //#region src/index.ts
2721
- function wn(e) {
2722
- let t = e.accessControl ? ne(e.accessControl) : {}, n = e.databaseIsolation ? re(e.databaseIsolation) : {}, r = gt(e);
3466
+ function nr(e) {
3467
+ let t = e.accessControl ? M(e.accessControl) : {}, n = e.databaseIsolation ? te(e.databaseIsolation) : {}, r = Ut(e);
2723
3468
  return {
2724
3469
  ...t,
2725
3470
  ...n,
2726
3471
  tenants: r
2727
3472
  };
2728
3473
  }
2729
- function Tn(t) {
2730
- let n = new e(), r = wn(t);
2731
- return n.route("/tenants", At(t, r)), n;
3474
+ function rr(t) {
3475
+ let n = new e(), r = nr(t);
3476
+ return n.route("/tenants", an(t, r)), n;
2732
3477
  }
2733
- function En(e) {
3478
+ function ir(e) {
2734
3479
  return {
2735
- hooks: wn(e),
2736
- middleware: Kt(e),
2737
- app: Tn(e),
3480
+ hooks: nr(e),
3481
+ middleware: xn(e),
3482
+ app: rr(e),
2738
3483
  config: e,
2739
- wrapAdapters: (t, n) => Ue(t, {
3484
+ wrapAdapters: (t, n) => We(t, {
2740
3485
  controlPlaneTenantId: e.accessControl?.controlPlaneTenantId,
2741
3486
  controlPlaneClientId: n?.controlPlaneClientId
2742
3487
  })
2743
3488
  };
2744
3489
  }
2745
3490
  //#endregion
2746
- export { Y as DEFAULT_ROLLOUT_SETTINGS, qt as DEFAULT_ROLLOUT_WAVES, rn as advanceRollout, an as advanceRollouts, xn as applyControlPlaneDefaultsPayload, at as applyResolvedConfigBlock, Jt as assignWaves, _n as buildControlPlaneDefaultsPayload, ae as buildEngineInstanceId, et as buildResolvedConfigBlock, ke as compareShadow, me as computeLegacyConfig, ne as createAccessControlHooks, Ut as createAccessControlMiddleware, Pe as createConfigSyncResolver, Ht as createControlPlaneTenantMiddleware, re as createDatabaseHooks, Gt as createDatabaseMiddleware, Sn as createDirectRolloutAdapter, Zt as createExpectedHash, ft as createInProcessSyncConfig, le as createInlineExecutor, Tn as createMultiTenancy, wn as createMultiTenancyHooks, Kt as createMultiTenancyMiddleware, Cn as createMultiTenancyPlugin, A as createOperationRecorder, M as createOperationRow, Vt as createProtectSyncedMiddleware, gt as createProvisioningHooks, mn as createRolloutController, pn as createRolloutWriteHooks, Ve as createRuntimeFallbackAdapter, Me as createShadowReporter, Wt as createSubdomainMiddleware, Tt as createSyncHooks, At as createTenantsOpenAPIRouter, Oe as diffConfig, H as effectiveOverride, V as effectiveScope, ue as enqueueTenantOperation, se as errorToMessage, rt as findUndecryptableKeyIds, cn as getConfigSyncStatus, hn as initMultiTenant, ce as inlineStepRunner, un as isPublishedRow, j as isTerminalStatus, Q as listRolloutOperations, Yt as listSyncedDescendants, Le as mergeClientWithFallback, Ze as mergeConfig, on as pauseRollout, en as planRollout, be as projectControlPlaneDefaults, I as readConfigRows, X as readRolloutConfig, ln as reconcileConfigDrift, dn as requestRollout, N as resolveTenantChain, sn as resumeRollout, mt as runRecordedTenantOperation, dt as runSyncDefaultsStep, En as setupMultiTenancy, ut as summarizeSyncResult, lt as syncErrors, ct as syncOptionsOf, W as syncedRowId, O as validateTenantAccess, Ue as withRuntimeFallback, Be as withSystemResourceServerInheritance };
3491
+ export { X as DEFAULT_ROLLOUT_SETTINGS, Sn as DEFAULT_ROLLOUT_WAVES, zt as MAX_MEMBER_REQUEST_ATTEMPTS, Nn as advanceRollout, Pn as advanceRollouts, $n as applyControlPlaneDefaultsPayload, ut as applyResolvedConfigBlock, kt as assertDetachEligible, Cn as assignWaves, Yn as buildControlPlaneDefaultsPayload, re as buildEngineInstanceId, at as buildResolvedConfigBlock, De as compareShadow, fe as computeLegacyConfig, M as createAccessControlHooks, vn as createAccessControlMiddleware, Me as createConfigSyncResolver, _n as createControlPlaneTenantMiddleware, te as createDatabaseHooks, bn as createDatabaseMiddleware, er as createDirectRolloutAdapter, Tn as createExpectedHash, Mt as createInProcessDetach, Ft as createInProcessMemberRequestStore, xt as createInProcessSyncConfig, oe as createInlineExecutor, rr as createMultiTenancy, nr as createMultiTenancyHooks, xn as createMultiTenancyMiddleware, tr as createMultiTenancyPlugin, I as createOperationRecorder, se as createOperationRow, gn as createProtectSyncedMiddleware, Ut as createProvisioningHooks, Kn as createRolloutController, Gn as createRolloutWriteHooks, Ve as createRuntimeFallbackAdapter, Ae as createShadowReporter, yn as createSubdomainMiddleware, Qt as createSyncHooks, an as createTenantsOpenAPIRouter, Tt as detachErrors, St as detachOptionsOf, jt as detachTenantRows, Ee as diffConfig, Ke as effectiveOverride, U as effectiveScope, Ot as emptyDetachResult, Bt as enqueueTenantMemberRequest, ce as enqueueTenantOperation, F as errorToMessage, ct as findUndecryptableKeyIds, Bn as getConfigSyncStatus, qn as initMultiTenant, ae as inlineStepRunner, Hn as isPublishedRow, L as isTerminalStatus, kn as listRolloutOperations, wn as listSyncedDescendants, At as markTenantDetached, It as memberRequestIdOf, Le as mergeClientWithFallback, $e as mergeConfig, Fn as pauseRollout, On as planRollout, ve as projectControlPlaneDefaults, V as readConfigRows, Z as readRolloutConfig, Vn as reconcileConfigDrift, Vt as reconcileTenantMemberRequests, Un as requestRollout, R as resolveTenantChain, In as resumeRollout, Dt as runDetachStep, Pt as runRecordedTenantOperation, bt as runSyncDefaultsStep, Rt as runTenantMembersRequestStep, ir as setupMultiTenancy, Et as summarizeDetachResult, yt as summarizeSyncResult, gt as syncErrors, ht as syncOptionsOf, it as syncedRowId, N as validateTenantAccess, zn as verifyTenantConfig, We as withRuntimeFallback, Be as withSystemResourceServerInheritance };