@authhero/multi-tenancy 15.1.2 → 15.3.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 (76) hide show
  1. package/dist/multi-tenancy.cjs +1 -1
  2. package/dist/multi-tenancy.mjs +2145 -703
  3. package/dist/types/index.d.ts +6 -2
  4. package/dist/types/index.d.ts.map +1 -1
  5. package/dist/types/inheritance/chain.d.ts +18 -0
  6. package/dist/types/inheritance/chain.d.ts.map +1 -0
  7. package/dist/types/inheritance/index.d.ts +10 -0
  8. package/dist/types/inheritance/index.d.ts.map +1 -0
  9. package/dist/types/inheritance/legacy.d.ts +7 -0
  10. package/dist/types/inheritance/legacy.d.ts.map +1 -0
  11. package/dist/types/inheritance/merge.d.ts +40 -0
  12. package/dist/types/inheritance/merge.d.ts.map +1 -0
  13. package/dist/types/inheritance/read.d.ts +5 -0
  14. package/dist/types/inheritance/read.d.ts.map +1 -0
  15. package/dist/types/inheritance/report.d.ts +20 -0
  16. package/dist/types/inheritance/report.d.ts.map +1 -0
  17. package/dist/types/inheritance/shadow.d.ts +30 -0
  18. package/dist/types/inheritance/shadow.d.ts.map +1 -0
  19. package/dist/types/inheritance/types.d.ts +24 -0
  20. package/dist/types/inheritance/types.d.ts.map +1 -0
  21. package/dist/types/init.d.ts +38 -0
  22. package/dist/types/init.d.ts.map +1 -1
  23. package/dist/types/middleware/config-sync-mode.d.ts +36 -0
  24. package/dist/types/middleware/config-sync-mode.d.ts.map +1 -0
  25. package/dist/types/middleware/index.d.ts +3 -1
  26. package/dist/types/middleware/index.d.ts.map +1 -1
  27. package/dist/types/middleware/protect-synced.d.ts +1 -1
  28. package/dist/types/middleware/protect-synced.d.ts.map +1 -1
  29. package/dist/types/middleware/settings-inheritance.d.ts +51 -3
  30. package/dist/types/middleware/settings-inheritance.d.ts.map +1 -1
  31. package/dist/types/operations/enqueue.d.ts +8 -1
  32. package/dist/types/operations/enqueue.d.ts.map +1 -1
  33. package/dist/types/operations/index.d.ts +3 -1
  34. package/dist/types/operations/index.d.ts.map +1 -1
  35. package/dist/types/operations/recorder.d.ts +2 -0
  36. package/dist/types/operations/recorder.d.ts.map +1 -1
  37. package/dist/types/operations/sync-defaults.d.ts +55 -0
  38. package/dist/types/operations/sync-defaults.d.ts.map +1 -0
  39. package/dist/types/operations/types.d.ts +2 -0
  40. package/dist/types/operations/types.d.ts.map +1 -1
  41. package/dist/types/rollout/index.d.ts +2 -0
  42. package/dist/types/rollout/index.d.ts.map +1 -1
  43. package/dist/types/rollout/payload.d.ts +15 -0
  44. package/dist/types/rollout/payload.d.ts.map +1 -1
  45. package/dist/types/rollout/resolved-sync.d.ts +91 -0
  46. package/dist/types/rollout/resolved-sync.d.ts.map +1 -0
  47. package/dist/types/rollouts/advance.d.ts +44 -0
  48. package/dist/types/rollouts/advance.d.ts.map +1 -0
  49. package/dist/types/rollouts/config.d.ts +54 -0
  50. package/dist/types/rollouts/config.d.ts.map +1 -0
  51. package/dist/types/rollouts/controller.d.ts +29 -0
  52. package/dist/types/rollouts/controller.d.ts.map +1 -0
  53. package/dist/types/rollouts/enumerate.d.ts +25 -0
  54. package/dist/types/rollouts/enumerate.d.ts.map +1 -0
  55. package/dist/types/rollouts/hashes.d.ts +10 -0
  56. package/dist/types/rollouts/hashes.d.ts.map +1 -0
  57. package/dist/types/rollouts/index.d.ts +19 -0
  58. package/dist/types/rollouts/index.d.ts.map +1 -0
  59. package/dist/types/rollouts/plan.d.ts +29 -0
  60. package/dist/types/rollouts/plan.d.ts.map +1 -0
  61. package/dist/types/rollouts/reconcile.d.ts +38 -0
  62. package/dist/types/rollouts/reconcile.d.ts.map +1 -0
  63. package/dist/types/rollouts/status.d.ts +28 -0
  64. package/dist/types/rollouts/status.d.ts.map +1 -0
  65. package/dist/types/rollouts/trigger.d.ts +52 -0
  66. package/dist/types/rollouts/trigger.d.ts.map +1 -0
  67. package/dist/types/rollouts/types.d.ts +25 -0
  68. package/dist/types/rollouts/types.d.ts.map +1 -0
  69. package/dist/types/routes/tenants.d.ts.map +1 -1
  70. package/dist/types/types.d.ts +12 -0
  71. package/dist/types/types.d.ts.map +1 -1
  72. package/dist/types/utils/index.d.ts +1 -0
  73. package/dist/types/utils/index.d.ts.map +1 -1
  74. package/dist/types/utils/tenant-tree.d.ts +33 -0
  75. package/dist/types/utils/tenant-tree.d.ts.map +1 -0
  76. package/package.json +5 -5
@@ -1,9 +1,9 @@
1
1
  import { Hono as e } from "hono";
2
- import { MANAGEMENT_API_AUDIENCE as t, MANAGEMENT_API_SCOPES as n, auth0QuerySchema as r, brandingSchema as i, connectionInsertSchema as a, connectionOptionsSchema as o, connectionSchema as s, deepMergePatch as c, emailProviderSchema as l, escapeLuceneValue as u, fetchAll as d, hookInsertSchema as f, init as p, isInteractiveClient as m, listControlPlaneKeys as h, promptSettingSchema as g, provisionDefaultClients as _, resourceServerInsertSchema as v, tenantInsertSchema as y, tenantSchema as b } from "authhero";
3
- import { OpenAPIHono as x, createRoute as S, z as C } from "@hono/zod-openapi";
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";
4
3
  import { HTTPException as w } from "hono/http-exception";
4
+ import { OpenAPIHono as T, createRoute as E, z as D } from "@hono/zod-openapi";
5
5
  //#region src/hooks/access-control.ts
6
- function T(e) {
6
+ function ne(e) {
7
7
  let { controlPlaneTenantId: t, requireOrganizationMatch: n = !0 } = e;
8
8
  return { async onTenantAccessValidation(e, r) {
9
9
  if (r === t) return !0;
@@ -14,14 +14,14 @@ function T(e) {
14
14
  return !0;
15
15
  } };
16
16
  }
17
- function E(e, t, n, r) {
17
+ function O(e, t, n, r) {
18
18
  if (t === n) return !0;
19
19
  let i = r || e;
20
20
  return i ? i.toLowerCase() === t.toLowerCase() : !1;
21
21
  }
22
22
  //#endregion
23
23
  //#region src/hooks/database.ts
24
- function D(e) {
24
+ function re(e) {
25
25
  return { async resolveDataAdapters(t) {
26
26
  try {
27
27
  return await e.getAdapters(t);
@@ -33,18 +33,18 @@ function D(e) {
33
33
  }
34
34
  //#endregion
35
35
  //#region src/operations/instance-id.ts
36
- var O = 64;
37
- function k(e) {
36
+ var k = 64;
37
+ function ie(e) {
38
38
  return e.replace(/[^a-zA-Z0-9_-]/g, "-");
39
39
  }
40
- function A(e) {
41
- let t = k(e.id), n = Math.max(0, O - (5 + t.length)), r = k(e.kind).slice(0, n), i = 3 + r.length + 2 + t.length, a = Math.max(0, O - i);
42
- return `op-${r}-${k(e.tenant_id ?? "fleet").slice(0, a)}-${t}`.slice(0, O);
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);
43
43
  }
44
44
  //#endregion
45
45
  //#region src/operations/recorder.ts
46
- var ee = 2048;
47
- function j(e) {
46
+ var oe = 2048;
47
+ function se(e) {
48
48
  let t;
49
49
  if (e instanceof Error) t = e.message;
50
50
  else try {
@@ -52,9 +52,9 @@ function j(e) {
52
52
  } catch {
53
53
  t = Object.prototype.toString.call(e);
54
54
  }
55
- return t.slice(0, ee);
55
+ return t.slice(0, oe);
56
56
  }
57
- function M(e) {
57
+ function A(e) {
58
58
  let { tenantOperations: t, tenantOperationEvents: n } = e;
59
59
  return {
60
60
  async markRunning(e, n) {
@@ -75,6 +75,9 @@ function M(e) {
75
75
  attempt: t.attempt ?? 1
76
76
  });
77
77
  },
78
+ async setResult(e, n) {
79
+ await t.update(e, { result: n });
80
+ },
78
81
  async markSucceeded(e) {
79
82
  await t.update(e, {
80
83
  status: "succeeded",
@@ -85,24 +88,24 @@ function M(e) {
85
88
  async markFailed(e, n) {
86
89
  await t.update(e, {
87
90
  status: "failed",
88
- error: j(n),
91
+ error: se(n),
89
92
  finished_at: (/* @__PURE__ */ new Date()).toISOString()
90
93
  });
91
94
  }
92
95
  };
93
96
  }
94
- function N(e) {
97
+ function j(e) {
95
98
  return e === "succeeded" || e === "failed" || e === "cancelled";
96
99
  }
97
100
  //#endregion
98
101
  //#region src/operations/inline-executor.ts
99
- var te = { async do(e, t, n) {
102
+ var ce = { async do(e, t, n) {
100
103
  let r = typeof t == "function" ? t : n;
101
104
  if (!r) throw Error("StepRunner.do called without a function");
102
105
  return r();
103
106
  } };
104
- function ne(e) {
105
- let t = M(e.stores);
107
+ function le(e) {
108
+ let t = A(e.stores);
106
109
  return {
107
110
  engine: "inline",
108
111
  async start(n) {
@@ -121,7 +124,7 @@ function ne(e) {
121
124
  try {
122
125
  let r = await e.run({
123
126
  operation: n,
124
- step: te
127
+ step: ce
125
128
  });
126
129
  await t.appendEvent(n.id, {
127
130
  step: e.name,
@@ -132,7 +135,7 @@ function ne(e) {
132
135
  throw await t.appendEvent(n.id, {
133
136
  step: e.name,
134
137
  outcome: "failed",
135
- detail: { message: j(r) }
138
+ detail: { message: se(r) }
136
139
  }), await t.markFailed(n.id, r), r;
137
140
  }
138
141
  }
@@ -142,7 +145,7 @@ function ne(e) {
142
145
  }
143
146
  //#endregion
144
147
  //#region src/operations/enqueue.ts
145
- async function re(e, t, n) {
148
+ async function M(e, t, n) {
146
149
  let r = await e.tenantOperations.create({
147
150
  tenant_id: t.tenant_id,
148
151
  rollout_id: t.rollout_id,
@@ -150,13 +153,14 @@ async function re(e, t, n) {
150
153
  engine: n,
151
154
  initiated_by: t.initiated_by,
152
155
  target_worker_version: t.target_worker_version,
153
- target_database_version: t.target_database_version
154
- }), i = A(r);
156
+ target_database_version: t.target_database_version,
157
+ input: t.input
158
+ }), i = ae(r);
155
159
  try {
156
160
  await e.tenantOperations.update(r.id, { engine_instance_id: i });
157
161
  } catch (t) {
158
162
  try {
159
- await M(e).markFailed(r.id, t);
163
+ await A(e).markFailed(r.id, t);
160
164
  } catch {}
161
165
  throw t;
162
166
  }
@@ -165,236 +169,1230 @@ async function re(e, t, n) {
165
169
  engine_instance_id: i
166
170
  };
167
171
  }
168
- async function ie(e, t, n) {
169
- let r = M(e), i = await re(e, n, t.engine);
172
+ async function ue(e, t, n, r = {}) {
173
+ let i = A(e), a = await M(e, n, t.engine);
170
174
  try {
171
- await t.start(i);
175
+ await t.start(a);
172
176
  } catch (t) {
177
+ let n = null;
173
178
  try {
174
- let n = await e.tenantOperations.get(i.id);
175
- n && !N(n.status) && await r.markFailed(i.id, t);
179
+ 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);
176
181
  } catch (e) {
177
182
  console.warn("Failed to record tenant operation failure:", e);
178
183
  }
184
+ if (r.returnFailed && n) return n;
179
185
  throw t;
180
186
  }
181
187
  try {
182
- return await e.tenantOperations.get(i.id) ?? i;
188
+ return await e.tenantOperations.get(a.id) ?? a;
183
189
  } catch (e) {
184
- return console.warn("Failed to re-fetch tenant operation after start:", e), i;
190
+ return console.warn("Failed to re-fetch tenant operation after start:", e), a;
185
191
  }
186
192
  }
187
- //#endregion
188
- //#region src/operations/record-provision.ts
189
- function ae(e) {
190
- if (e.tenantOperations && e.tenantOperationEvents) return {
191
- tenantOperations: e.tenantOperations,
192
- tenantOperationEvents: e.tenantOperationEvents
193
- };
194
- }
195
- async function oe(e, t, n) {
196
- let r = ae(e);
197
- if (!r) {
198
- await n(void 0);
199
- return;
193
+ async function de(e) {
194
+ let { tenantId: t, parentTenantId: n, getTenant: r, getChildren: i } = e, a = e.maxDepth ?? 2;
195
+ if (!n) return;
196
+ if (t && n === t) throw new w(400, { message: "A tenant cannot be its own parent" });
197
+ let o = new Set(t ? [t] : []), s = 0, c = n;
198
+ for (; c;) {
199
+ if (o.has(c)) throw new w(400, { message: `Setting parent_tenant_id to '${n}' would create a cycle` });
200
+ o.add(c);
201
+ 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` });
204
+ c = e.parent_tenant_id;
200
205
  }
201
- let i = M(r), a = async (e) => {
202
- try {
203
- await e();
204
- } catch (e) {
205
- console.warn("Failed to record tenant operation progress:", e);
206
+ if (t && i) {
207
+ let e = new Set([t]), r = 0, o = [t];
208
+ for (; o.length > 0;) {
209
+ let t = [];
210
+ 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
+ o = t;
206
213
  }
207
- }, o;
208
- if (await a(async () => {
209
- let e = await re(r, t, "inline");
210
- o = e.id, await i.markRunning(e.id);
211
- }), !o) {
212
- await n(void 0);
213
- return;
214
214
  }
215
- let s = o, c = !1, l = async (e, t, n) => {
216
- c = !0, await a(async () => {
217
- t === "started" && await i.setCurrentStep(s, e), await i.appendEvent(s, {
218
- step: e,
219
- outcome: t,
220
- detail: n
221
- });
222
- });
215
+ }
216
+ //#endregion
217
+ //#region src/inheritance/chain.ts
218
+ async function N(e) {
219
+ let { tenantId: t, getTenant: n, legacyControlPlane: r } = e, i = e.maxDepth ?? 2, a = await n(t);
220
+ if (!a?.parent_tenant_id) return r && r !== t ? [r] : [];
221
+ let o = [], s = new Set([t]), c = a.parent_tenant_id;
222
+ 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}` });
225
+ let e = await n(c);
226
+ if (!e) break;
227
+ o.push(c), c = e.parent_tenant_id;
228
+ }
229
+ return o;
230
+ }
231
+ //#endregion
232
+ //#region src/inheritance/legacy.ts
233
+ function fe(e) {
234
+ let t = {};
235
+ for (let n of e ?? []) n.value !== void 0 && (t[n.name] = n.value);
236
+ return t;
237
+ }
238
+ function pe(e, t) {
239
+ if (!e.inherit) return e;
240
+ let n = t.find((t) => t.name === e.name && t.is_system);
241
+ if (!n) return e;
242
+ let r = {
243
+ ...fe(n.secrets),
244
+ ...fe(e.secrets)
245
+ };
246
+ return {
247
+ ...e,
248
+ code: n.code,
249
+ secrets: Object.entries(r).map(([e, t]) => ({
250
+ name: e,
251
+ value: t
252
+ }))
253
+ };
254
+ }
255
+ function me(e, t) {
256
+ 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
+ return {
259
+ connections: e.connections.map((e) => R(e, t.connections)),
260
+ resourceServers: e.resourceServers.map((e) => e.is_system ? Ie(e, t.resourceServers.find((t) => t.id === e.id) ?? null) : e),
261
+ hooks: [...e.hooks, ...r],
262
+ hookCode: e.hookCode,
263
+ actions: e.actions.map((e) => pe(e, t.actions)),
264
+ emailProvider: e.emailProvider ?? t.emailProvider,
265
+ branding: e.branding,
266
+ promptSettings: e.promptSettings
267
+ };
268
+ }
269
+ //#endregion
270
+ //#region src/rollout/defaults-projection.ts
271
+ function he(e = {}) {
272
+ return {
273
+ connections: e.connections ?? !0,
274
+ resourceServers: e.resourceServers ?? !0,
275
+ hooks: e.hooks ?? !0,
276
+ emailProvider: e.emailProvider ?? !0,
277
+ branding: e.branding ?? !0,
278
+ promptSettings: e.promptSettings ?? !0
279
+ };
280
+ }
281
+ function P() {
282
+ return {
283
+ upserted: 0,
284
+ errors: []
285
+ };
286
+ }
287
+ function ge(e) {
288
+ return {
289
+ tenantId: e,
290
+ connections: P(),
291
+ resourceServers: P(),
292
+ hooks: P(),
293
+ emailProvider: P(),
294
+ branding: P(),
295
+ promptSettings: P()
223
296
  };
297
+ }
298
+ function _e(e) {
299
+ let t = e.metadata;
300
+ return !!(t && t.inheritable === !0);
301
+ }
302
+ async function F(e, t, n, r) {
224
303
  try {
225
- await n(l);
226
- } catch (e) {
227
- throw await a(async () => {
228
- c || await i.appendEvent(s, {
229
- step: t.kind,
230
- outcome: "failed",
231
- detail: { message: j(e) }
232
- }), await i.markFailed(s, e);
233
- }), e;
304
+ await r();
305
+ } catch (r) {
306
+ let i = `${t}: ${r instanceof Error ? r.message : String(r)}`;
307
+ if (!n) throw Error(i, { cause: r });
308
+ e.errors.push(i);
234
309
  }
235
- await a(async () => {
236
- c || await i.appendEvent(s, {
237
- step: t.kind,
238
- outcome: "succeeded"
239
- }), await i.markSucceeded(s);
310
+ }
311
+ async function ve(e, t, n) {
312
+ return {
313
+ connections: n.connections ? await m((n) => e.connections.list(t, n), "connections", {
314
+ cursorField: "id",
315
+ pageSize: 100
316
+ }) : [],
317
+ resourceServers: n.resourceServers ? await m((n) => e.resourceServers.list(t, n), "resource_servers", {
318
+ cursorField: "id",
319
+ pageSize: 100
320
+ }) : [],
321
+ hooks: n.hooks ? await m((n) => e.hooks.list(t, n), "hooks", {
322
+ cursorField: "hook_id",
323
+ pageSize: 100
324
+ }) : [],
325
+ emailProvider: n.emailProvider ? await e.emailProviders.get(t) ?? null : null,
326
+ branding: n.branding ? await e.branding.get(t) ?? null : null,
327
+ promptSettings: n.promptSettings ? await e.promptSettings.get(t) ?? null : null
328
+ };
329
+ }
330
+ async function ye(e, t, n, r, i, a) {
331
+ if (r.connections) for (let r of e.connections) {
332
+ let e = r.id;
333
+ e && await F(a.connections, `connection ${e}`, i, async () => {
334
+ let i = c.parse(r);
335
+ 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
+ }
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);
340
+ 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
+ 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);
344
+ 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
+ r.emailProvider && e.emailProvider && await F(a.emailProvider, "email_provider", i, async () => {
347
+ let r = e.emailProvider;
348
+ 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
+ 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
+ await t.promptSettings.set(n, e.promptSettings), a.promptSettings.upserted += 1;
240
353
  });
241
354
  }
242
- //#endregion
243
- //#region src/hooks/provisioning.ts
244
- function se(e) {
245
- return `urn:authhero:tenant:${e.toLowerCase()}`;
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;
246
358
  }
247
- function P(e) {
359
+ //#endregion
360
+ //#region src/inheritance/read.ts
361
+ async function I(e, t) {
362
+ let n = await ve(e, t, {
363
+ connections: !0,
364
+ resourceServers: !0,
365
+ hooks: !0,
366
+ emailProvider: !0,
367
+ branding: !0,
368
+ promptSettings: !0
369
+ }), r = await m((n) => e.actions.list(t, n), "actions", {
370
+ cursorField: "id",
371
+ pageSize: 100
372
+ }), i = new Set(r.map((e) => e.id)), a = /* @__PURE__ */ new Set();
373
+ for (let e of n.hooks) {
374
+ let t = e.code_id;
375
+ t && !i.has(t) && a.add(t);
376
+ }
377
+ let o = [];
378
+ for (let n of a) {
379
+ let r = await e.hookCode.get(t, n);
380
+ r && o.push(r);
381
+ }
248
382
  return {
249
- async beforeCreate(e, t) {
250
- return !t.audience && t.id ? {
251
- ...t,
252
- audience: se(t.id)
253
- } : t;
254
- },
255
- async afterCreate(r, i) {
256
- let { accessControl: a, databaseIsolation: o } = e;
257
- if (a && r.ctx && await ce(r, i, a), o?.onProvision) {
258
- let e = o.onProvision;
259
- o.recordProvisionOperations === !1 ? await e(i.id) : await oe(r.adapters, {
260
- kind: "provision",
261
- tenant_id: i.id,
262
- initiated_by: r.ctx?.var.user?.sub
263
- }, (t) => e(i.id, t));
264
- } else try {
265
- await _(r.adapters, i.id, {
266
- managementApiIdentifier: t,
267
- managementApiScopes: n
383
+ ...n,
384
+ actions: r,
385
+ hookCode: o
386
+ };
387
+ }
388
+ //#endregion
389
+ //#region src/inheritance/shadow.ts
390
+ var xe = /secret|password|private_key|api_key|token/i, Se = new Set([
391
+ "id",
392
+ "tenant_id",
393
+ "created_at",
394
+ "updated_at",
395
+ "scope",
396
+ "override",
397
+ "enforce",
398
+ "enabled_clients"
399
+ ]);
400
+ async function L(e) {
401
+ let t = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(e));
402
+ return [...new Uint8Array(t)].map((e) => e.toString(16).padStart(2, "0")).join("").slice(0, 16);
403
+ }
404
+ async function Ce(e, t = "") {
405
+ if (Array.isArray(e)) {
406
+ if (t === "secrets") {
407
+ let t = {};
408
+ for (let n of e) t[n.name] = n.value === void 0 ? null : `sha256:${await L(n.value)}`;
409
+ return t;
410
+ }
411
+ return Promise.all(e.map((e) => Ce(e, t)));
412
+ }
413
+ if (e && typeof e == "object") {
414
+ let t = {};
415
+ for (let n of Object.keys(e).sort()) {
416
+ let r = e[n];
417
+ r != null && (t[n] = typeof r == "string" && xe.test(n) ? `sha256:${await L(r)}` : await Ce(r, n));
418
+ }
419
+ return t;
420
+ }
421
+ return e;
422
+ }
423
+ async function we(e) {
424
+ let t = {};
425
+ for (let [n, r] of Object.entries(e)) Se.has(n) || (t[n] = r);
426
+ return await Ce(t);
427
+ }
428
+ var Te = {
429
+ connection: (e) => `${e.strategy}:${e.name}`,
430
+ resourceServer: (e) => e.identifier,
431
+ hook: (e) => e.hook_id,
432
+ action: (e) => e.name
433
+ }, Ee = new Set([
434
+ "connection",
435
+ "resourceServer",
436
+ "action",
437
+ "emailProvider",
438
+ "branding",
439
+ "promptSettings"
440
+ ]);
441
+ async function De(e) {
442
+ let t = /* @__PURE__ */ new Map(), n = async (e, n, r) => {
443
+ let i = t.get(e) ?? /* @__PURE__ */ new Map();
444
+ i.set(n, await we(r)), t.set(e, i);
445
+ };
446
+ for (let [t, r] of Object.entries(Te)) {
447
+ let i = e[{
448
+ connection: "connections",
449
+ resourceServer: "resourceServers",
450
+ hook: "hooks",
451
+ action: "actions"
452
+ }[t]];
453
+ for (let e of i) await n(t, r(e), e);
454
+ }
455
+ for (let t of [
456
+ "emailProvider",
457
+ "branding",
458
+ "promptSettings"
459
+ ]) e[t] && await n(t, "singleton", e[t]);
460
+ return t;
461
+ }
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()]);
464
+ for (let e of a) {
465
+ let t = n.get(e) ?? /* @__PURE__ */ new Map(), a = r.get(e) ?? /* @__PURE__ */ new Map();
466
+ for (let n of new Set([...t.keys(), ...a.keys()])) {
467
+ let r = t.get(n), o = a.get(n);
468
+ if (r && !o) i.push({
469
+ entity: e,
470
+ key: n,
471
+ kind: "missing",
472
+ fields: [],
473
+ expected: !1
474
+ });
475
+ else if (!r && o) i.push({
476
+ entity: e,
477
+ key: n,
478
+ kind: "extra",
479
+ fields: [],
480
+ expected: Ee.has(e)
481
+ });
482
+ else if (r && o) {
483
+ let t = JSON.stringify(r), a = JSON.stringify(o);
484
+ if (t === a) continue;
485
+ let s = [...new Set([...Object.keys(r), ...Object.keys(o)])].filter((e) => JSON.stringify(r[e]) !== JSON.stringify(o[e])).sort();
486
+ i.push({
487
+ entity: e,
488
+ key: n,
489
+ kind: "changed",
490
+ fields: s,
491
+ expected: !1,
492
+ legacy_hash: await L(t),
493
+ new_hash: await L(a)
268
494
  });
269
- } catch (e) {
270
- throw console.warn(`Failed to provision default clients for tenant ${i.id}:`, e), e;
271
- }
272
- },
273
- async beforeDelete(t, n) {
274
- let { accessControl: r, databaseIsolation: i } = e;
275
- if (r) try {
276
- let e = (await t.adapters.organizations.list(r.controlPlaneTenantId)).organizations.find((e) => e.name === n);
277
- e && await t.adapters.organizations.remove(r.controlPlaneTenantId, e.id);
278
- } catch (e) {
279
- console.warn(`Failed to remove organization for tenant ${n}:`, e);
280
- }
281
- if (i?.onDeprovision) try {
282
- await i.onDeprovision(n);
283
- } catch (e) {
284
- console.warn(`Failed to deprovision database for tenant ${n}:`, e);
285
495
  }
286
496
  }
287
- };
497
+ }
498
+ return i;
288
499
  }
289
- async function ce(e, t, n) {
290
- 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, {
291
- name: t.id,
292
- display_name: t.friendly_name || t.id
293
- }), d;
294
- if (o && (d = await ue(e, r, s, c)), l && e.ctx) {
295
- let t = e.ctx.var.user;
296
- if (t?.sub && !await le(e, r, t.sub)) try {
297
- await e.adapters.userOrganizations.create(r, {
298
- user_id: t.sub,
299
- organization_id: u.id
300
- }), d && await e.adapters.userRoles.create(r, t.sub, d, u.id);
301
- } catch (e) {
302
- console.warn(`Failed to add creator ${t.sub} to organization ${u.id}:`, e);
500
+ async function ke(e) {
501
+ let { adapters: t, tenantId: n, legacyControlPlane: r } = e, i = await N({
502
+ tenantId: n,
503
+ getTenant: (e) => t.tenants.get(e),
504
+ legacyControlPlane: r,
505
+ 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}`));
508
+ }
509
+ //#endregion
510
+ //#region src/inheritance/report.ts
511
+ var Ae = 3600 * 1e3, je = 1e4;
512
+ function Me(e, t) {
513
+ let n = t.sample ?? 1, r = t.intervalMs ?? 6e4, i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = /* @__PURE__ */ new Map();
514
+ async function s(n, r) {
515
+ let i = await ke({
516
+ adapters: e,
517
+ tenantId: n,
518
+ legacyControlPlane: r
519
+ }), a = Date.now();
520
+ o.size > je && o.clear();
521
+ for (let s of i) {
522
+ if (s.expected && !t.includeExpected) continue;
523
+ let i = await L([
524
+ n,
525
+ s.entity,
526
+ s.key,
527
+ s.kind,
528
+ s.fields.join(",")
529
+ ].join("|")), c = o.get(i);
530
+ c !== void 0 && a - c < Ae || (o.set(i, a), await Ne(e, n, s, r));
303
531
  }
304
532
  }
305
- 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}`);
306
- }
307
- async function le(e, n, r) {
308
- let i = await e.adapters.userRoles.list(n, r, void 0, "");
309
- for (let r of i) if ((await e.adapters.rolePermissions.list(n, r.id, { per_page: 1e3 })).some((e) => e.permission_name === "admin:organizations" && e.resource_server_identifier === t)) return !0;
310
- return !1;
533
+ return { schedule(e, t) {
534
+ if (a.has(e) || n < 1 && Math.random() >= n) return;
535
+ 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
+ } };
311
538
  }
312
- async function ue(e, r, i, a) {
313
- let o = (await e.adapters.roles.list(r, {})).roles.find((e) => e.name === i);
314
- if (o) return o.id;
315
- let s = await e.adapters.roles.create(r, {
316
- name: i,
317
- description: a
318
- }), c = t, l = n.map((e) => ({
319
- role_id: s.id,
320
- resource_server_identifier: c,
321
- permission_name: e.value
322
- }));
323
- return await e.adapters.rolePermissions.assign(r, s.id, l), s.id;
539
+ async function Ne(e, n, r, i) {
540
+ await e.logs.create(n, {
541
+ type: t.CONFIG_INHERITANCE_DIFF,
542
+ date: (/* @__PURE__ */ new Date()).toISOString(),
543
+ isMobile: !1,
544
+ description: `${r.kind} ${r.entity} ${r.key}`,
545
+ details: {
546
+ shadow: "config-inheritance",
547
+ legacy_control_plane: i,
548
+ ...r
549
+ }
550
+ });
324
551
  }
325
552
  //#endregion
326
- //#region src/hooks/sync.ts
327
- function F(e, t, n = () => !0) {
328
- let { controlPlaneTenantId: r, getChildTenantIds: i, getAdapters: a } = e, o = /* @__PURE__ */ new Map();
329
- async function s(e, n, r) {
330
- return (await t(e).list(n, {
331
- q: `name:${u(r)}`,
332
- per_page: 1
333
- }))[0] ?? null;
334
- }
335
- async function c(e) {
336
- let n = await i(), o = t(await a(r));
337
- await Promise.all(n.map(async (n) => {
338
- try {
339
- let r = await a(n), i = t(r), c = {
340
- ...o.transform(e),
341
- is_system: !0
342
- }, l = await s(r, n, e.name), u = l ? i.getId(l) : void 0;
343
- if (l && u) {
344
- let e = i.preserveOnUpdate ? i.preserveOnUpdate(l, c) : c;
345
- await i.update(n, u, e);
346
- } else await i.create(n, c);
347
- } catch (t) {
348
- console.error(`Failed to sync ${o.listKey} "${e.name}" to tenant "${n}":`, t);
349
- }
350
- }));
351
- }
352
- async function l(e) {
353
- let n = await i();
354
- await Promise.all(n.map(async (n) => {
355
- try {
356
- let r = await a(n), i = t(r), o = await s(r, n, e), c = o ? i.getId(o) : void 0;
357
- o && c && await i.remove(n, c);
358
- } catch (t) {
359
- console.error(`Failed to delete entity "${e}" from tenant "${n}":`, t);
360
- }
361
- }));
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();
556
+ async function s(e) {
557
+ if (e === r) return !1;
558
+ let t = o.get(e), s = Date.now();
559
+ if (t && t.expires > s) return t.synced;
560
+ try {
561
+ let t = (await n(e))?.config_sync === "synced";
562
+ return o.size >= a && o.clear(), o.set(e, {
563
+ synced: t,
564
+ expires: s + i
565
+ }), t;
566
+ } catch {
567
+ return !1;
568
+ }
362
569
  }
363
570
  return {
364
- afterCreate: async (e, t) => {
365
- e.tenantId === r && n(t) && await c(t);
366
- },
367
- afterUpdate: async (e, t, i) => {
368
- e.tenantId === r && n(i) && await c(i);
369
- },
370
- beforeDelete: async (e, i) => {
371
- if (e.tenantId !== r) return;
372
- let a = await t(e.adapters).get(e.tenantId, i);
373
- a && n(a) && o.set(i, a);
571
+ isSynced: s,
572
+ invalidate(e) {
573
+ e ? o.delete(e) : o.clear();
374
574
  },
375
- afterDelete: async (e, t) => {
376
- if (e.tenantId !== r) return;
377
- let n = o.get(t);
378
- n && (o.delete(t), await l(n.name));
575
+ async resolve({ tenant_id: e }) {
576
+ let n = await t(e);
577
+ return !n || n.tenantId === e ? n : await s(e) ? void 0 : n;
379
578
  }
380
579
  };
381
580
  }
382
- function I(e, t, n = () => !0) {
383
- let { controlPlaneTenantId: r, getControlPlaneAdapters: i, getAdapters: a } = e;
384
- return { async afterCreate(e, o) {
385
- if (o.id !== r) try {
386
- let e = await i(), s = await a(o.id), c = t(e), l = t(s), u = await d((e) => c.listPaginated(r, e), c.listKey, {
387
- cursorField: "id",
388
- pageSize: 100
389
- });
390
- await Promise.all(u.filter((e) => n(e)).map(async (e) => {
391
- try {
392
- let t = c.transform(e);
393
- await l.create(o.id, {
394
- ...t,
395
- is_system: !0
396
- });
397
- } catch (e) {
581
+ //#endregion
582
+ //#region src/middleware/settings-inheritance.ts
583
+ function R(e, t) {
584
+ let n = t.find((t) => t.strategy === e.strategy);
585
+ if (!n?.options) return e;
586
+ let r = u.passthrough().parse({
587
+ ...n,
588
+ ...e
589
+ });
590
+ return r.options = l.passthrough().parse({
591
+ ...n.options || {},
592
+ ...e.options
593
+ }), r;
594
+ }
595
+ function z(e, t) {
596
+ let n = [...t || [], ...e || []];
597
+ return [...new Set(n)];
598
+ }
599
+ function Fe(e, t) {
600
+ if (!t?.length) return e || [];
601
+ if (!e?.length) return t;
602
+ let n = /* @__PURE__ */ new Map();
603
+ for (let e of t) n.set(e.value, e);
604
+ for (let t of e) n.set(t.value, t);
605
+ return Array.from(n.values());
606
+ }
607
+ function Ie(e, t) {
608
+ return t ? {
609
+ ...e,
610
+ scopes: Fe(e.scopes, t.scopes)
611
+ } : e;
612
+ }
613
+ function Le(e, t) {
614
+ return t ? {
615
+ ...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)
620
+ } : e;
621
+ }
622
+ function Re(e) {
623
+ let { controlPlaneTenantId: t, controlPlaneClientId: n, resolveControlPlane: r } = e;
624
+ if (r) return async (e) => r({ tenant_id: e });
625
+ if (!t) return async () => void 0;
626
+ let i = {
627
+ tenantId: t,
628
+ clientId: n
629
+ };
630
+ return async () => i;
631
+ }
632
+ function ze(e, t) {
633
+ return {
634
+ ...e.resourceServers,
635
+ get: async (n, r) => {
636
+ let i = await e.resourceServers.get(n, r);
637
+ if (!i) return i;
638
+ let a = await t(n);
639
+ return !a || n === a.tenantId || !i.is_system ? i : Ie(i, await e.resourceServers.get(a.tenantId, r));
640
+ },
641
+ list: async (n, r) => {
642
+ let i = await e.resourceServers.list(n, r), a = await t(n);
643
+ if (!a || n === a.tenantId) return i;
644
+ let o = a.tenantId, s = i.resource_servers.filter((e) => !!(e.is_system && e.id)).map((e) => e.id);
645
+ if (s.length === 0) return i;
646
+ let c = /* @__PURE__ */ new Map();
647
+ await Promise.all(s.map(async (t) => {
648
+ let n = await e.resourceServers.get(o, t);
649
+ n && c.set(t, n);
650
+ }));
651
+ let l = i.resource_servers.map((e) => e.is_system && e.id ? Ie(e, c.get(e.id) ?? null) : e);
652
+ return {
653
+ ...i,
654
+ resource_servers: l
655
+ };
656
+ }
657
+ };
658
+ }
659
+ function Be(e, t) {
660
+ let n = Re({
661
+ controlPlaneTenantId: t.controlPlaneTenantId,
662
+ resolveControlPlane: t.resolveControlPlane
663
+ });
664
+ return {
665
+ ...e,
666
+ resourceServers: ze(e, n)
667
+ };
668
+ }
669
+ function Ve(e, t) {
670
+ let { controlPlaneTenantId: n, controlPlaneClientId: r, resolveControlPlane: i, inheritanceShadow: a } = t, o = t.configSync ?? Pe({
671
+ base: Re({
672
+ controlPlaneTenantId: n,
673
+ controlPlaneClientId: r,
674
+ resolveControlPlane: i
675
+ }),
676
+ getTenant: async (t) => await e.tenants.get(t) ?? null,
677
+ controlPlaneTenantId: n
678
+ }), s = (e) => o.resolve({ tenant_id: e }), c = a ? Me(e, a === !0 ? {} : a) : void 0, l = c ? async (e) => {
679
+ let t = await s(e);
680
+ return await o.isSynced(e) || c.schedule(e, t?.tenantId), t;
681
+ } : s;
682
+ return {
683
+ ...e,
684
+ multiTenancyConfig: {
685
+ controlPlaneTenantId: n,
686
+ controlPlaneClientId: r,
687
+ resolveControlPlane: o.resolve
688
+ },
689
+ connections: {
690
+ ...e.connections,
691
+ get: async (t, n) => {
692
+ let r = await e.connections.get(t, n);
693
+ if (!r) return r;
694
+ let i = await l(t);
695
+ return !i || t === i.tenantId ? r : R(r, (await e.connections.list(i.tenantId)).connections || []);
696
+ },
697
+ list: async (t, n) => {
698
+ let r = await e.connections.list(t, n), i = await l(t);
699
+ 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 || []));
701
+ return {
702
+ ...r,
703
+ connections: o
704
+ };
705
+ }
706
+ },
707
+ clientConnections: {
708
+ ...e.clientConnections,
709
+ listByClient: async (t, n) => {
710
+ let r = await e.clientConnections.listByClient(t, n);
711
+ r.length === 0 && (r = (await e.connections.list(t)).connections || []);
712
+ let i = await l(t);
713
+ if (!i || t === i.tenantId) return r;
714
+ let a = await e.connections.list(i.tenantId);
715
+ return r.map((e) => R(e, a.connections || []));
716
+ }
717
+ },
718
+ emailProviders: {
719
+ ...e.emailProviders,
720
+ get: async (t) => {
721
+ let n = await e.emailProviders.get(t);
722
+ if (n) return n;
723
+ let r = await l(t);
724
+ return !r || t === r.tenantId ? null : e.emailProviders.get(r.tenantId);
725
+ }
726
+ },
727
+ resourceServers: ze(e, l),
728
+ hooks: He(e, l)
729
+ };
730
+ }
731
+ function B(e) {
732
+ if (!e || typeof e != "object") return !1;
733
+ let t = e.metadata;
734
+ return !t || typeof t != "object" ? !1 : t.inheritable === !0;
735
+ }
736
+ function He(e, t) {
737
+ return {
738
+ ...e.hooks,
739
+ list: async (n, r) => {
740
+ let i = await e.hooks.list(n, r), a = await t(n);
741
+ if (!a || n === a.tenantId) return i;
742
+ let o = ((await e.hooks.list(a.tenantId, r)).hooks || []).filter(B);
743
+ if (o.length === 0) return i;
744
+ 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);
746
+ return {
747
+ ...i,
748
+ hooks: [...i.hooks || [], ...c],
749
+ length: typeof i.length == "number" ? i.length + c.length : i.length
750
+ };
751
+ },
752
+ get: async (n, r) => {
753
+ let i = await e.hooks.get(n, r);
754
+ if (i) return i;
755
+ let a = await t(n);
756
+ if (!a || n === a.tenantId) return i;
757
+ let o = await e.hooks.get(a.tenantId, r);
758
+ return o && B(o) ? o : null;
759
+ }
760
+ };
761
+ }
762
+ function Ue(e, t) {
763
+ return Ve(e, t);
764
+ }
765
+ //#endregion
766
+ //#region src/inheritance/types.ts
767
+ var We = () => ({
768
+ connections: [],
769
+ resourceServers: [],
770
+ hooks: [],
771
+ hookCode: [],
772
+ actions: [],
773
+ emailProvider: null,
774
+ branding: null,
775
+ promptSettings: null
776
+ });
777
+ //#endregion
778
+ //#region src/inheritance/merge.ts
779
+ function V(e, t) {
780
+ if (t.scope) return t.scope;
781
+ switch (e) {
782
+ case "connection":
783
+ case "emailProvider": return "shared";
784
+ case "resourceServer":
785
+ case "action": return t.is_system ? "shared" : "local";
786
+ case "hook": return B(t) ? "shared" : "local";
787
+ default: return "local";
788
+ }
789
+ }
790
+ function H(e) {
791
+ return e.override ?? "fields";
792
+ }
793
+ var Ge = /secret|password|private_key|api_key|token/i;
794
+ function Ke(e, t) {
795
+ let n = { ...e ?? {} };
796
+ for (let [e, r] of Object.entries(t ?? {})) Ge.test(e) && (n[e] = r);
797
+ return n;
798
+ }
799
+ function qe(e, t) {
800
+ switch (H(e)) {
801
+ case "none": return {
802
+ ...e,
803
+ id: t.id
804
+ };
805
+ case "secrets": return {
806
+ ...e,
807
+ id: t.id,
808
+ options: Ke(e.options, t.options)
809
+ };
810
+ default: return {
811
+ ...e,
812
+ ...t,
813
+ options: {
814
+ ...e.options ?? {},
815
+ ...t.options ?? {}
816
+ }
817
+ };
818
+ }
819
+ }
820
+ function Je(e, t) {
821
+ switch (H(e)) {
822
+ case "none": return {
823
+ ...e,
824
+ id: t.id
825
+ };
826
+ case "secrets": return {
827
+ ...e,
828
+ id: t.id,
829
+ signing_secret: t.signing_secret ?? e.signing_secret
830
+ };
831
+ default: return {
832
+ ...t,
833
+ scopes: Fe(t.scopes, e.scopes)
834
+ };
835
+ }
836
+ }
837
+ function Ye(e) {
838
+ return new Map((e ?? []).map((e) => [e.name, e]));
839
+ }
840
+ function Xe(e, t) {
841
+ let n = H(e);
842
+ if (n === "none") return {
843
+ ...e,
844
+ id: t.id
845
+ };
846
+ let r = Ye(e.secrets);
847
+ if (n === "secrets" || n === "fields") for (let [e, n] of Ye(t.secrets)) r.set(e, n);
848
+ return {
849
+ ...n === "fields" && !t.inherit ? t : e,
850
+ id: t.id,
851
+ secrets: [...r.values()]
852
+ };
853
+ }
854
+ function Ze(e, t) {
855
+ 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);
857
+ 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();
859
+ r.forEach((e, t) => {
860
+ let h = t === r.length - 1;
861
+ for (let t of i("connection", e.connections, h, o)) {
862
+ let e = u.get(t.strategy);
863
+ h ? d.push(e ? qe(e, t) : t) : u.set(t.strategy, e ? qe(e, t) : t);
864
+ }
865
+ for (let t of i("resourceServer", e.resourceServers, h, s)) {
866
+ let e = f.get(s(t));
867
+ f.set(s(t), e ? Je(e, t) : t);
868
+ }
869
+ for (let t of i("hook", e.hooks, h, c)) p.set(c(t), t);
870
+ for (let t of i("action", e.actions, h, l)) {
871
+ let e = m.get(l(t));
872
+ m.set(l(t), e ? Xe(e, t) : t);
873
+ }
874
+ for (let t of [
875
+ "emailProvider",
876
+ "branding",
877
+ "promptSettings"
878
+ ]) {
879
+ let r = e[t];
880
+ r && (h || V(t, r) !== "local") && (!h && V(t, r) === "platform" && n.add(`${t}:singleton`), a[t] = r);
881
+ }
882
+ });
883
+ let h = new Set(r[r.length - 1].connections.map((e) => e.strategy));
884
+ a.connections = [...d, ...[...u.values()].filter((e) => !h.has(e.strategy))], a.resourceServers = [...f.values()], a.hooks = [...p.values()];
885
+ let g = new Set(a.hooks.map((e) => e.code_id).filter((e) => !!e)), _ = /* @__PURE__ */ new Map();
886
+ for (let e of [...r].reverse()) for (let t of e.hookCode) g.has(t.id) && !_.has(t.id) && _.set(t.id, t);
887
+ return a.hookCode = [..._.values()], a.actions = [...m.values()], {
888
+ ...a,
889
+ hidden: [...n]
890
+ };
891
+ }
892
+ //#endregion
893
+ //#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";
896
+ }
897
+ async function Qe(e) {
898
+ let t = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(e));
899
+ return [...new Uint8Array(t)].map((e) => e.toString(16).padStart(2, "0")).join("");
900
+ }
901
+ var $e = {
902
+ connection: "con_",
903
+ resourceServer: "api_",
904
+ hook: "h_",
905
+ hookCode: "hc_",
906
+ action: "act_"
907
+ };
908
+ async function W(e, t, n) {
909
+ let r = await Qe(`${t}|${e}|${n}`);
910
+ return `${$e[e]}sy${r.slice(0, 15)}`;
911
+ }
912
+ function G(e, t) {
913
+ let n = t;
914
+ switch (e) {
915
+ case "connection": return `${n.strategy}:${n.name}`;
916
+ case "resourceServer": return n.identifier;
917
+ case "action": return n.name;
918
+ case "hookCode": return n.id;
919
+ case "hook": return n.hook_id;
920
+ }
921
+ }
922
+ async function et(e, t, n = {}) {
923
+ let r = await N({
924
+ tenantId: t,
925
+ getTenant: (t) => e.tenants.get(t),
926
+ legacyControlPlane: n.legacyControlPlane,
927
+ maxDepth: n.maxDepth
928
+ }), i = Ze(await Promise.all(r.map((t) => I(e, t))), We()), a = {
929
+ version: 1,
930
+ chain: r,
931
+ connections: i.connections,
932
+ resourceServers: i.resourceServers,
933
+ hookCode: i.hookCode,
934
+ actions: i.actions,
935
+ hooks: i.hooks,
936
+ emailProvider: i.emailProvider,
937
+ branding: i.branding,
938
+ promptSettings: i.promptSettings,
939
+ hidden: i.hidden,
940
+ deletes: n.deletes ?? []
941
+ };
942
+ return {
943
+ ...a,
944
+ hash: await Qe(U(a))
945
+ };
946
+ }
947
+ function tt(e, t) {
948
+ 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);
951
+ }
952
+ function nt(e) {
953
+ let t = e.slice(7), n = t.indexOf(":");
954
+ return n === -1 ? "default" : t.slice(0, n);
955
+ }
956
+ async function rt(e, t) {
957
+ let n = /* @__PURE__ */ new Set();
958
+ tt(e, n);
959
+ let r = /* @__PURE__ */ new Set();
960
+ for (let e of n) await s(e, t) || r.add(nt(e));
961
+ return [...r].sort();
962
+ }
963
+ var K = () => ({
964
+ added: 0,
965
+ changed: 0,
966
+ unchanged: 0,
967
+ deleted: 0,
968
+ 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",
973
+ hash: e.hash,
974
+ 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
+ },
984
+ changes: []
985
+ }, 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,
988
+ status: "up-to-date"
989
+ };
990
+ if (r.keyRing) {
991
+ let t = await rt(e, r.keyRing);
992
+ 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
+ }
994
+ let p = async (e, t, n) => {
995
+ let r = l.entities[e];
996
+ try {
997
+ let i = await n();
998
+ r[i] += 1, i !== "unchanged" && l.changes.push(`${e}:${t}`);
999
+ } catch (n) {
1000
+ let i = `${e} ${t}: ${n instanceof Error ? n.message : String(n)}`;
1001
+ if (!s) throw Error(i, { cause: n });
1002
+ r.errors.push(i);
1003
+ }
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)));
1007
+ 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,
1012
+ 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),
1019
+ view: (e) => e
1020
+ });
1021
+ });
1022
+ }
1023
+ 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({
1027
+ ...r,
1028
+ 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),
1035
+ view: (e) => e
1036
+ });
1037
+ });
1038
+ }
1039
+ 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,
1045
+ desired: e,
1046
+ create: () => t.hookCode.create(n, e, { importMetadata: { id: i } }),
1047
+ update: () => t.hookCode.update(n, i, e),
1048
+ view: (e) => e
1049
+ });
1050
+ });
1051
+ }
1052
+ 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),
1061
+ view: (e) => e
1062
+ });
1063
+ });
1064
+ }
1065
+ 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({
1069
+ ...r,
1070
+ hook_id: i,
1071
+ ...e ? { code_id: v.get(e) ?? e } : {}
1072
+ }), o = await t.hooks.get(n, i);
1073
+ return m({
1074
+ existing: o ? g.parse(o) : null,
1075
+ desired: a,
1076
+ create: () => t.hooks.create(n, a),
1077
+ update: () => t.hooks.update(n, i, a),
1078
+ view: (e) => e
1079
+ });
1080
+ });
1081
+ }
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");
1088
+ });
1089
+ for (let i of e.deletes) {
1090
+ let e = await _(i.entity, i.key), o = `${i.entity}:${i.key}`;
1091
+ 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);
1094
+ } catch (e) {
1095
+ l.entities[i.entity].errors.push(`delete ${o}: ${e instanceof Error ? e.message : e}`);
1096
+ }
1097
+ }
1098
+ let y = Object.values(l.entities).some((e) => e.errors.length > 0);
1099
+ return !a && !y && u && await t.tenants.update(n, {
1100
+ config_sync_hash: e.hash,
1101
+ config_synced_at: (/* @__PURE__ */ new Date()).toISOString()
1102
+ }), l;
1103
+ }
1104
+ async function ot(e, t, n, r) {
1105
+ switch (n) {
1106
+ case "connection": return !!await e.connections.get(t, r);
1107
+ case "resourceServer": return !!await e.resourceServers.get(t, r);
1108
+ case "hookCode": return !!await e.hookCode.get(t, r);
1109
+ case "action": return !!await e.actions.get(t, r);
1110
+ case "hook": return !!await e.hooks.get(t, r);
1111
+ }
1112
+ }
1113
+ async function st(e, t, n, r) {
1114
+ switch (n) {
1115
+ case "connection":
1116
+ await e.connections.remove(t, r);
1117
+ return;
1118
+ case "resourceServer":
1119
+ await e.resourceServers.remove(t, r);
1120
+ return;
1121
+ case "hookCode":
1122
+ await e.hookCode.remove(t, r);
1123
+ return;
1124
+ case "action":
1125
+ await e.actions.remove(t, r);
1126
+ return;
1127
+ case "hook":
1128
+ await e.hooks.remove(t, r);
1129
+ return;
1130
+ }
1131
+ }
1132
+ //#endregion
1133
+ //#region src/operations/sync-defaults.ts
1134
+ function ct(e) {
1135
+ let t = e.input ?? {};
1136
+ return {
1137
+ dryRun: t.dry_run === !0,
1138
+ force: t.force === !0
1139
+ };
1140
+ }
1141
+ function lt(e) {
1142
+ return Object.values(e.entities).flatMap((e) => e.errors);
1143
+ }
1144
+ function ut(e, t) {
1145
+ return {
1146
+ dry_run: t.dryRun,
1147
+ status: e.status,
1148
+ hash: e.hash,
1149
+ changes: e.changes,
1150
+ entities: Object.fromEntries(Object.entries(e.entities).map(([e, t]) => [e, {
1151
+ added: t.added,
1152
+ changed: t.changed,
1153
+ unchanged: t.unchanged,
1154
+ deleted: t.deleted,
1155
+ errors: t.errors.length
1156
+ }]))
1157
+ };
1158
+ }
1159
+ async function dt(e) {
1160
+ let { operation: t, syncConfig: n, recorder: r } = e;
1161
+ 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);
1163
+ await r.setResult(t.id, o);
1164
+ let s = lt(a);
1165
+ if (s.length > 0) {
1166
+ let e = s.slice(0, 3).join("; ");
1167
+ throw Error(`sync-defaults reported ${s.length} error(s): ${e}${s.length > 3 ? "; ..." : ""}`);
1168
+ }
1169
+ return o;
1170
+ }
1171
+ function ft(e, t) {
1172
+ return async (n, r) => {
1173
+ let i = await e.tenants.get(n);
1174
+ if (!i) throw Error(`Tenant "${n}" not found`);
1175
+ 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, {
1177
+ legacyControlPlane: (t.resolveControlPlane ? await t.resolveControlPlane({ tenant_id: n }) : { tenantId: t.controlPlaneTenantId })?.tenantId,
1178
+ maxDepth: t.maxDepth
1179
+ }), e, n, {
1180
+ dryRun: r.dryRun,
1181
+ force: r.force
1182
+ });
1183
+ };
1184
+ }
1185
+ //#endregion
1186
+ //#region src/operations/record-provision.ts
1187
+ function pt(e) {
1188
+ if (e.tenantOperations && e.tenantOperationEvents) return {
1189
+ tenantOperations: e.tenantOperations,
1190
+ tenantOperationEvents: e.tenantOperationEvents
1191
+ };
1192
+ }
1193
+ async function mt(e, t, n) {
1194
+ let r = pt(e);
1195
+ if (!r) {
1196
+ await n(void 0);
1197
+ return;
1198
+ }
1199
+ let i = A(r), a = async (e) => {
1200
+ try {
1201
+ await e();
1202
+ } catch (e) {
1203
+ console.warn("Failed to record tenant operation progress:", e);
1204
+ }
1205
+ }, o;
1206
+ if (await a(async () => {
1207
+ let e = await M(r, t, "inline");
1208
+ o = e.id, await i.markRunning(e.id);
1209
+ }), !o) {
1210
+ await n(void 0);
1211
+ return;
1212
+ }
1213
+ let s = o, c = !1, l = async (e, t, n) => {
1214
+ c = !0, await a(async () => {
1215
+ t === "started" && await i.setCurrentStep(s, e), await i.appendEvent(s, {
1216
+ step: e,
1217
+ outcome: t,
1218
+ detail: n
1219
+ });
1220
+ });
1221
+ };
1222
+ try {
1223
+ await n(l);
1224
+ } catch (e) {
1225
+ throw await a(async () => {
1226
+ c || await i.appendEvent(s, {
1227
+ step: t.kind,
1228
+ outcome: "failed",
1229
+ detail: { message: se(e) }
1230
+ }), await i.markFailed(s, e);
1231
+ }), e;
1232
+ }
1233
+ await a(async () => {
1234
+ c || await i.appendEvent(s, {
1235
+ step: t.kind,
1236
+ outcome: "succeeded"
1237
+ }), await i.markSucceeded(s);
1238
+ });
1239
+ }
1240
+ //#endregion
1241
+ //#region src/hooks/provisioning.ts
1242
+ function ht(e) {
1243
+ return `urn:authhero:tenant:${e.toLowerCase()}`;
1244
+ }
1245
+ function gt(e) {
1246
+ return {
1247
+ async beforeCreate(e, t) {
1248
+ return !t.audience && t.id ? {
1249
+ ...t,
1250
+ audience: ht(t.id)
1251
+ } : t;
1252
+ },
1253
+ async afterCreate(t, i) {
1254
+ let { accessControl: a, databaseIsolation: o } = e;
1255
+ if (a && t.ctx && await _t(t, i, a), o?.onProvision) {
1256
+ let e = o.onProvision;
1257
+ o.recordProvisionOperations === !1 ? await e(i.id) : await mt(t.adapters, {
1258
+ kind: "provision",
1259
+ tenant_id: i.id,
1260
+ initiated_by: t.ctx?.var.user?.sub
1261
+ }, (t) => e(i.id, t));
1262
+ } else try {
1263
+ await te(t.adapters, i.id, {
1264
+ managementApiIdentifier: n,
1265
+ managementApiScopes: r
1266
+ });
1267
+ } catch (e) {
1268
+ throw console.warn(`Failed to provision default clients for tenant ${i.id}:`, e), e;
1269
+ }
1270
+ },
1271
+ async beforeDelete(t, n) {
1272
+ let { accessControl: r, databaseIsolation: i } = e;
1273
+ if (r) try {
1274
+ let e = (await t.adapters.organizations.list(r.controlPlaneTenantId)).organizations.find((e) => e.name === n);
1275
+ e && await t.adapters.organizations.remove(r.controlPlaneTenantId, e.id);
1276
+ } catch (e) {
1277
+ console.warn(`Failed to remove organization for tenant ${n}:`, e);
1278
+ }
1279
+ if (i?.onDeprovision) try {
1280
+ await i.onDeprovision(n);
1281
+ } catch (e) {
1282
+ console.warn(`Failed to deprovision database for tenant ${n}:`, e);
1283
+ }
1284
+ }
1285
+ };
1286
+ }
1287
+ async function _t(e, t, n) {
1288
+ 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
+ name: t.id,
1290
+ display_name: t.friendly_name || t.id
1291
+ }), d;
1292
+ if (o && (d = await yt(e, r, s, c)), l && e.ctx) {
1293
+ let t = e.ctx.var.user;
1294
+ if (t?.sub && !await vt(e, r, t.sub)) try {
1295
+ await e.adapters.userOrganizations.create(r, {
1296
+ user_id: t.sub,
1297
+ organization_id: u.id
1298
+ }), d && await e.adapters.userRoles.create(r, t.sub, d, u.id);
1299
+ } catch (e) {
1300
+ console.warn(`Failed to add creator ${t.sub} to organization ${u.id}:`, e);
1301
+ }
1302
+ }
1303
+ 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
+ }
1305
+ async function vt(e, t, r) {
1306
+ let i = await e.adapters.userRoles.list(t, r, void 0, "");
1307
+ 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
+ return !1;
1309
+ }
1310
+ async function yt(e, t, i, a) {
1311
+ let o = (await e.adapters.roles.list(t, {})).roles.find((e) => e.name === i);
1312
+ if (o) return o.id;
1313
+ let s = await e.adapters.roles.create(t, {
1314
+ name: i,
1315
+ description: a
1316
+ }), c = n, l = r.map((e) => ({
1317
+ role_id: s.id,
1318
+ resource_server_identifier: c,
1319
+ permission_name: e.value
1320
+ }));
1321
+ return await e.adapters.rolePermissions.assign(t, s.id, l), s.id;
1322
+ }
1323
+ //#endregion
1324
+ //#region src/hooks/sync.ts
1325
+ function bt(e, t, n = () => !0) {
1326
+ let { controlPlaneTenantId: r, getChildTenantIds: i, getAdapters: a } = e, o = /* @__PURE__ */ new Map();
1327
+ async function s(e, n, r) {
1328
+ return (await t(e).list(n, {
1329
+ q: `name:${p(r)}`,
1330
+ per_page: 1
1331
+ }))[0] ?? null;
1332
+ }
1333
+ async function c(e) {
1334
+ let n = await i(), o = t(await a(r));
1335
+ await Promise.all(n.map(async (n) => {
1336
+ try {
1337
+ let r = await a(n), i = t(r), c = {
1338
+ ...o.transform(e),
1339
+ is_system: !0
1340
+ }, l = await s(r, n, e.name), u = l ? i.getId(l) : void 0;
1341
+ if (l && u) {
1342
+ let e = i.preserveOnUpdate ? i.preserveOnUpdate(l, c) : c;
1343
+ await i.update(n, u, e);
1344
+ } else await i.create(n, c);
1345
+ } catch (t) {
1346
+ console.error(`Failed to sync ${o.listKey} "${e.name}" to tenant "${n}":`, t);
1347
+ }
1348
+ }));
1349
+ }
1350
+ async function l(e) {
1351
+ let n = await i();
1352
+ await Promise.all(n.map(async (n) => {
1353
+ try {
1354
+ let r = await a(n), i = t(r), o = await s(r, n, e), c = o ? i.getId(o) : void 0;
1355
+ o && c && await i.remove(n, c);
1356
+ } catch (t) {
1357
+ console.error(`Failed to delete entity "${e}" from tenant "${n}":`, t);
1358
+ }
1359
+ }));
1360
+ }
1361
+ return {
1362
+ afterCreate: async (e, t) => {
1363
+ e.tenantId === r && n(t) && await c(t);
1364
+ },
1365
+ afterUpdate: async (e, t, i) => {
1366
+ e.tenantId === r && n(i) && await c(i);
1367
+ },
1368
+ beforeDelete: async (e, i) => {
1369
+ if (e.tenantId !== r) return;
1370
+ let a = await t(e.adapters).get(e.tenantId, i);
1371
+ a && n(a) && o.set(i, a);
1372
+ },
1373
+ afterDelete: async (e, t) => {
1374
+ if (e.tenantId !== r) return;
1375
+ let n = o.get(t);
1376
+ n && (o.delete(t), await l(n.name));
1377
+ }
1378
+ };
1379
+ }
1380
+ function xt(e, t, n = () => !0) {
1381
+ let { controlPlaneTenantId: r, getControlPlaneAdapters: i, getAdapters: a } = e;
1382
+ return { async afterCreate(e, o) {
1383
+ 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, {
1385
+ cursorField: "id",
1386
+ pageSize: 100
1387
+ });
1388
+ await Promise.all(u.filter((e) => n(e)).map(async (e) => {
1389
+ try {
1390
+ let t = c.transform(e);
1391
+ await l.create(o.id, {
1392
+ ...t,
1393
+ is_system: !0
1394
+ });
1395
+ } catch (e) {
398
1396
  console.error(`Failed to sync entity to new tenant "${o.id}":`, e);
399
1397
  }
400
1398
  }));
@@ -403,7 +1401,7 @@ function I(e, t, n = () => !0) {
403
1401
  }
404
1402
  } };
405
1403
  }
406
- var L = (e) => ({
1404
+ var St = (e) => ({
407
1405
  list: async (t, n) => (await e.resourceServers.list(t, n)).resource_servers,
408
1406
  listPaginated: (t, n) => e.resourceServers.list(t, n),
409
1407
  get: (t, n) => e.resourceServers.get(t, n),
@@ -421,7 +1419,7 @@ var L = (e) => ({
421
1419
  token_lifetime: e.token_lifetime,
422
1420
  token_lifetime_for_web: e.token_lifetime_for_web
423
1421
  })
424
- }), R = (e) => ({
1422
+ }), Ct = (e) => ({
425
1423
  list: async (t, n) => (await e.roles.list(t, n)).roles,
426
1424
  listPaginated: (t, n) => e.roles.list(t, n),
427
1425
  get: (t, n) => e.roles.get(t, n),
@@ -436,20 +1434,20 @@ var L = (e) => ({
436
1434
  description: e.description
437
1435
  })
438
1436
  });
439
- function z(e) {
1437
+ function wt(e) {
440
1438
  return e.metadata?.sync !== !1;
441
1439
  }
442
- function B(e) {
443
- let { sync: t = {}, filters: n = {} } = e, r = t.resourceServers ?? !0, i = t.roles ?? !0, a = (e) => z(e) ? n.resourceServers ? n.resourceServers(e) : !0 : !1, o = (e) => z(e) ? n.roles ? n.roles(e) : !0 : !1, s = r ? F(e, L, a) : void 0, c = i ? F(e, R, o) : void 0, l = r ? I(e, L, a) : void 0, f = i ? I(e, R, o) : void 0, p = i ? { async afterCreate(t, r) {
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) {
444
1442
  if (r.id !== e.controlPlaneTenantId) {
445
- await f?.afterCreate?.(t, r);
1443
+ await u?.afterCreate?.(t, r);
446
1444
  try {
447
- let t = await e.getControlPlaneAdapters(), i = await e.getAdapters(r.id), a = await d((n) => t.roles.list(e.controlPlaneTenantId, n), "roles", {
1445
+ let t = await e.getControlPlaneAdapters(), i = await e.getAdapters(r.id), a = await m((n) => t.roles.list(e.controlPlaneTenantId, n), "roles", {
448
1446
  cursorField: "id",
449
1447
  pageSize: 100
450
1448
  }), o = /* @__PURE__ */ new Map();
451
1449
  for (let e of a.filter((e) => n.roles?.(e) ?? !0)) {
452
- let t = await m(i, r.id, e.name);
1450
+ let t = await f(i, r.id, e.name);
453
1451
  t && o.set(e.name, t.id);
454
1452
  }
455
1453
  for (let s of a.filter((e) => n.roles?.(e) ?? !0)) {
@@ -470,9 +1468,9 @@ function B(e) {
470
1468
  }
471
1469
  }
472
1470
  } } : void 0;
473
- async function m(e, t, n) {
1471
+ async function f(e, t, n) {
474
1472
  return (await e.roles.list(t, {
475
- q: `name:${u(n)}`,
1473
+ q: `name:${p(n)}`,
476
1474
  per_page: 1
477
1475
  })).roles[0] ?? null;
478
1476
  }
@@ -482,7 +1480,7 @@ function B(e) {
482
1480
  roles: c
483
1481
  },
484
1482
  tenantHooks: { async afterCreate(e, t) {
485
- let n = [l?.afterCreate, p?.afterCreate ?? f?.afterCreate], r = [];
1483
+ let n = [l?.afterCreate, d?.afterCreate ?? u?.afterCreate], r = [];
486
1484
  for (let i of n) if (i) try {
487
1485
  await i(e, t);
488
1486
  } catch (e) {
@@ -495,48 +1493,54 @@ function B(e) {
495
1493
  }
496
1494
  //#endregion
497
1495
  //#region src/middleware/request-data.ts
498
- function V(e) {
1496
+ function q(e) {
499
1497
  return e.var.data ?? e.env.data;
500
1498
  }
501
1499
  //#endregion
502
1500
  //#region src/routes/tenants.ts
503
- var de = C.object({
504
- sub: C.string(),
505
- tenant_id: C.string().optional(),
506
- org_id: C.string().optional(),
507
- scope: C.string().optional(),
508
- permissions: C.array(C.string()).optional()
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()
509
1507
  }).passthrough();
510
- function fe(e) {
511
- let t = de.safeParse(e);
1508
+ function Dt(e) {
1509
+ let t = Et.safeParse(e);
512
1510
  return t.success ? t.data : void 0;
513
1511
  }
514
- function pe(e) {
1512
+ function Ot(e, t, n) {
1513
+ return t ? !e || n ? !1 : e.tenant_id === t : !0;
1514
+ }
1515
+ function kt(e) {
515
1516
  let t = e.permissions ?? [], n = e.scope ? e.scope.split(" ").filter(Boolean) : [], r = new Set([...t, ...n]);
516
1517
  return r.has("delete:tenants") || r.has("admin:organizations");
517
1518
  }
518
- function H(e, t) {
519
- let n = new x();
520
- return n.openapi(S({
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({
521
1525
  tags: ["tenants"],
522
1526
  method: "get",
523
1527
  path: "/",
524
- request: { query: r },
1528
+ request: { query: a },
525
1529
  security: [{ Bearer: [] }],
526
1530
  responses: { 200: {
527
- content: { "application/json": { schema: C.object({
528
- tenants: C.array(b),
529
- start: C.number().optional(),
530
- limit: C.number().optional(),
531
- length: C.number().optional(),
532
- total: C.number().optional()
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()
533
1537
  }) } },
534
1538
  description: "List of tenants"
535
1539
  } }
536
1540
  }), async (t) => {
537
1541
  let { page: n, per_page: r, include_totals: i, q: a } = t.req.valid("query"), o = t.var.user, s = o?.permissions || [];
538
1542
  if (!(o?.org_id ?? t.var.organization_id) && s.includes("admin:organizations")) {
539
- let e = await V(t).tenants.list({
1543
+ let e = await q(t).tenants.list({
540
1544
  page: n,
541
1545
  per_page: r,
542
1546
  include_totals: i,
@@ -550,10 +1554,10 @@ function H(e, t) {
550
1554
  total: e.totals?.length
551
1555
  }) : t.json({ tenants: e.tenants });
552
1556
  }
553
- let c = e.accessControl?.controlPlaneTenantId ?? V(t).multiTenancyConfig?.controlPlaneTenantId;
1557
+ let c = e.accessControl?.controlPlaneTenantId ?? q(t).multiTenancyConfig?.controlPlaneTenantId;
554
1558
  if (c && !o?.sub) throw new w(403, { message: "Access denied: token has no subject" });
555
1559
  if (c && o?.sub) {
556
- let e = (await d((e) => V(t).userOrganizations.listUserOrganizations(c, o.sub, e), "organizations")).map((e) => e.name);
1560
+ let e = (await m((e) => q(t).userOrganizations.listUserOrganizations(c, o.sub, e), "organizations")).map((e) => e.name);
557
1561
  if (e.length === 0) return i ? t.json({
558
1562
  tenants: [],
559
1563
  start: 0,
@@ -561,28 +1565,28 @@ function H(e, t) {
561
1565
  length: 0,
562
1566
  total: 0
563
1567
  }) : t.json({ tenants: [] });
564
- let s = e.length, l = n ?? 0, u = r ?? 50, f = l * u, p = e.slice(f, f + u);
565
- if (p.length === 0) return i ? t.json({
1568
+ let s = e.length, l = n ?? 0, u = r ?? 50, d = l * u, f = e.slice(d, d + u);
1569
+ if (f.length === 0) return i ? t.json({
566
1570
  tenants: [],
567
- start: f,
1571
+ start: d,
568
1572
  limit: u,
569
1573
  length: 0,
570
1574
  total: s
571
1575
  }) : t.json({ tenants: [] });
572
- let m = p.map((e) => `id:${e}`).join(" OR "), h = a ? `(${m}) AND (${a})` : m, g = await V(t).tenants.list({
1576
+ let p = f.map((e) => `id:${e}`).join(" OR "), h = a ? `(${p}) AND (${a})` : p, g = await q(t).tenants.list({
573
1577
  q: h,
574
1578
  per_page: u,
575
1579
  include_totals: !1
576
1580
  });
577
1581
  return i ? t.json({
578
1582
  tenants: g.tenants,
579
- start: f,
1583
+ start: d,
580
1584
  limit: u,
581
1585
  length: g.tenants.length,
582
1586
  total: s
583
1587
  }) : t.json({ tenants: g.tenants });
584
1588
  }
585
- let l = await V(t).tenants.list({
1589
+ let l = await q(t).tenants.list({
586
1590
  page: n,
587
1591
  per_page: r,
588
1592
  include_totals: i,
@@ -595,34 +1599,44 @@ function H(e, t) {
595
1599
  length: l.tenants.length,
596
1600
  total: l.totals?.length
597
1601
  }) : t.json({ tenants: l.tenants });
598
- }), n.openapi(S({
1602
+ }), n.openapi(E({
599
1603
  tags: ["tenants"],
600
1604
  method: "post",
601
1605
  path: "/",
602
- request: { body: { content: { "application/json": { schema: y } } } },
1606
+ request: { body: { content: { "application/json": { schema: S } } } },
603
1607
  security: [{ Bearer: [] }],
604
1608
  responses: {
605
1609
  201: {
606
- content: { "application/json": { schema: b } },
1610
+ content: { "application/json": { schema: C } },
607
1611
  description: "Tenant created"
608
1612
  },
609
1613
  400: { description: "Validation error" },
610
1614
  409: { description: "Tenant with this ID already exists" }
611
1615
  }
612
- }), async (e) => {
613
- if (!e.var.user?.sub) throw new w(401, { message: "Authentication required to create tenants" });
614
- let n = e.req.valid("json"), r = {
615
- adapters: V(e),
616
- ctx: e
1616
+ }), async (n) => {
1617
+ if (!n.var.user?.sub) throw new w(401, { message: "Authentication required to create tenants" });
1618
+ 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" });
1620
+ o !== void 0 && r(n) && (c = {
1621
+ ...c,
1622
+ config_sync: o
1623
+ });
1624
+ let l = {
1625
+ adapters: q(n),
1626
+ ctx: n
617
1627
  };
618
- t.tenants?.beforeCreate && (n = await t.tenants.beforeCreate(r, n));
619
- let i = await V(e).tenants.create(n);
620
- return t.tenants?.afterCreate && await t.tenants.afterCreate(r, i), e.json(i, 201);
621
- }), n.openapi(S({
1628
+ t.tenants?.beforeCreate && (c = await t.tenants.beforeCreate(l, c)), await de({
1629
+ tenantId: c.id,
1630
+ parentTenantId: c.parent_tenant_id,
1631
+ getTenant: (e) => q(n).tenants.get(e)
1632
+ });
1633
+ let u = await q(n).tenants.create(c);
1634
+ return t.tenants?.afterCreate && await t.tenants.afterCreate(l, u), e.onConfigSyncChange?.(u.id), n.json(u, 201);
1635
+ }), n.openapi(E({
622
1636
  tags: ["tenants"],
623
1637
  method: "delete",
624
1638
  path: "/{id}",
625
- request: { params: C.object({ id: C.string() }) },
1639
+ request: { params: D.object({ id: D.string() }) },
626
1640
  security: [{ Bearer: ["delete:tenants"] }],
627
1641
  responses: {
628
1642
  204: { description: "Tenant deleted" },
@@ -630,72 +1644,116 @@ function H(e, t) {
630
1644
  404: { description: "Tenant not found" }
631
1645
  }
632
1646
  }), async (n) => {
633
- let { id: r } = n.req.valid("param"), i = e.accessControl?.controlPlaneTenantId ?? V(n).multiTenancyConfig?.controlPlaneTenantId;
1647
+ let { id: r } = n.req.valid("param"), i = e.accessControl?.controlPlaneTenantId ?? q(n).multiTenancyConfig?.controlPlaneTenantId;
634
1648
  if (i) {
635
- let e = fe(n.var.user);
1649
+ let e = Dt(n.var.user);
636
1650
  if (!e?.sub) throw new w(401, { message: "Authentication required" });
637
1651
  if (r === i) throw new w(403, { message: "Cannot delete the control plane" });
638
1652
  let t = n.var.org_name, a = r.toLowerCase(), o = !!t && t.toLowerCase() === a;
639
1653
  if (!o) {
640
1654
  let r = !!(e.org_id ?? n.var.organization_id ?? t), a = !e.tenant_id || e.tenant_id === i;
641
- !r && a && pe(e) && (o = !0);
1655
+ !r && a && kt(e) && (o = !0);
642
1656
  }
643
- if (o ||= (await d((t) => V(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" });
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" });
644
1658
  }
645
- if (!await V(n).tenants.get(r)) throw new w(404, { message: "Tenant not found" });
1659
+ if (!await q(n).tenants.get(r)) throw new w(404, { message: "Tenant not found" });
646
1660
  let a = {
647
- adapters: V(n),
1661
+ adapters: q(n),
648
1662
  ctx: n
649
1663
  };
650
- return t.tenants?.beforeDelete && await t.tenants.beforeDelete(a, r), await V(n).tenants.remove(r), t.tenants?.afterDelete && await t.tenants.afterDelete(a, r), n.body(null, 204);
651
- }), n.openapi(S({
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) {
1666
+ let t = e.configSyncStatus;
1667
+ n.openapi(E({
1668
+ tags: ["tenants"],
1669
+ method: "get",
1670
+ path: "/{id}/config-sync",
1671
+ request: { params: D.object({ id: D.string() }) },
1672
+ security: [{ Bearer: ["read:tenants"] }],
1673
+ responses: {
1674
+ 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())
1685
+ }) } },
1686
+ description: "Config sync status of the tenant"
1687
+ },
1688
+ 403: { description: "Not allowed to read this tenant" },
1689
+ 404: { description: "Tenant not found" }
1690
+ }
1691
+ }), async (e) => {
1692
+ 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" });
1694
+ let i = await t(n);
1695
+ if (!i) throw new w(404, { message: "Tenant not found" });
1696
+ return e.json(i);
1697
+ });
1698
+ }
1699
+ return n.openapi(E({
652
1700
  tags: ["tenants", "settings"],
653
1701
  method: "get",
654
1702
  path: "/settings",
655
- request: { headers: C.object({ "tenant-id": C.string().optional() }) },
1703
+ request: { headers: D.object({ "tenant-id": D.string().optional() }) },
656
1704
  security: [{ Bearer: ["read:tenants"] }],
657
1705
  responses: { 200: {
658
- content: { "application/json": { schema: b } },
1706
+ content: { "application/json": { schema: C } },
659
1707
  description: "Current tenant settings"
660
1708
  } }
661
1709
  }), async (e) => {
662
- let t = await V(e).tenants.get(e.var.tenant_id);
1710
+ let t = await q(e).tenants.get(e.var.tenant_id);
663
1711
  if (!t) throw new w(404, { message: "Tenant not found" });
664
1712
  return e.json(t);
665
- }), n.openapi(S({
1713
+ }), n.openapi(E({
666
1714
  tags: ["tenants", "settings"],
667
1715
  method: "patch",
668
1716
  path: "/settings",
669
1717
  request: {
670
- headers: C.object({ "tenant-id": C.string().optional() }),
671
- body: { content: { "application/json": { schema: C.object(y.shape).partial() } } }
1718
+ headers: D.object({ "tenant-id": D.string().optional() }),
1719
+ body: { content: { "application/json": { schema: D.object(S.shape).partial() } } }
672
1720
  },
673
1721
  security: [{ Bearer: ["update:tenants"] }],
674
1722
  responses: { 200: {
675
- content: { "application/json": { schema: b } },
1723
+ content: { "application/json": { schema: C } },
676
1724
  description: "Updated tenant settings"
677
1725
  } }
678
- }), async (e) => {
679
- let { id: t, ...n } = e.req.valid("json"), r = await V(e).tenants.get(e.var.tenant_id);
680
- if (!r) throw new w(404, { message: "Tenant not found" });
681
- if ("default_client_id" in n) {
682
- let t = n.default_client_id;
683
- if (typeof t == "string" && t.length > 0) {
684
- let n = await V(e).clients.get(e.var.tenant_id, t);
685
- if (!n) throw new w(400, { message: `Client with id '${t}' not found` });
686
- if (!m(n)) throw new w(400, { message: `Client '${t}' is not an interactive client and cannot be used as the default client` });
1726
+ }), 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;
1732
+ 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` });
687
1736
  }
688
1737
  }
689
- let i = c(r, n);
690
- await V(e).tenants.update(e.var.tenant_id, i);
691
- let a = await V(e).tenants.get(e.var.tenant_id);
692
- if (!a) throw new w(500, { message: "Failed to retrieve updated tenant" });
693
- return e.json(a);
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({
1741
+ 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)
1745
+ });
1746
+ }
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);
694
1752
  }), n;
695
1753
  }
696
1754
  //#endregion
697
1755
  //#region src/middleware/protect-synced.ts
698
- function me(e) {
1756
+ function jt(e) {
699
1757
  for (let { pattern: t, type: n } of [
700
1758
  {
701
1759
  pattern: /\/api\/v2\/resource-servers\/([^/]+)$/,
@@ -718,7 +1776,7 @@ function me(e) {
718
1776
  }
719
1777
  return null;
720
1778
  }
721
- async function he(e, t, n) {
1779
+ async function Mt(e, t, n) {
722
1780
  try {
723
1781
  switch (n.type) {
724
1782
  case "resource_server": return (await e.resourceServers.get(t, n.id))?.is_system === !0;
@@ -730,222 +1788,148 @@ async function he(e, t, n) {
730
1788
  return !1;
731
1789
  }
732
1790
  }
733
- function ge(e) {
734
- return {
735
- resource_server: "resource server",
736
- role: "role",
737
- connection: "connection"
738
- }[e];
739
- }
740
- function U() {
741
- return async (e, t) => {
742
- if (![
743
- "PATCH",
744
- "PUT",
745
- "DELETE"
746
- ].includes(e.req.method)) return t();
747
- let n = me(e.req.path);
748
- if (!n) return t();
749
- let r = e.var.tenant_id || e.req.header("x-tenant-id") || e.req.header("tenant-id");
750
- if (!r) return t();
751
- if (await he(V(e), r, n)) throw new w(403, { message: `This ${ge(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.` });
752
- return t();
753
- };
754
- }
755
- //#endregion
756
- //#region src/middleware/settings-inheritance.ts
757
- function W(e, t) {
758
- let n = t.find((t) => t.strategy === e.strategy);
759
- if (!n?.options) return e;
760
- let r = s.passthrough().parse({
761
- ...n,
762
- ...e
763
- });
764
- return r.options = o.passthrough().parse({
765
- ...n.options || {},
766
- ...e.options
767
- }), r;
768
- }
769
- function G(e, t) {
770
- let n = [...t || [], ...e || []];
771
- return [...new Set(n)];
772
- }
773
- function _e(e, t) {
774
- if (!t?.length) return e || [];
775
- if (!e?.length) return t;
776
- let n = /* @__PURE__ */ new Map();
777
- for (let e of t) n.set(e.value, e);
778
- for (let t of e) n.set(t.value, t);
779
- return Array.from(n.values());
780
- }
781
- function ve(e, t) {
782
- return t ? {
783
- ...e,
784
- scopes: _e(e.scopes, t.scopes)
785
- } : e;
786
- }
787
- function ye(e, t) {
788
- return t ? {
789
- ...e,
790
- callbacks: G(e.callbacks, t.callbacks),
791
- web_origins: G(e.web_origins, t.web_origins),
792
- allowed_logout_urls: G(e.allowed_logout_urls, t.allowed_logout_urls),
793
- allowed_origins: G(e.allowed_origins, t.allowed_origins)
794
- } : e;
795
- }
796
- function be(e) {
797
- let { controlPlaneTenantId: t, controlPlaneClientId: n, resolveControlPlane: r } = e;
798
- if (r) return async (e) => r({ tenant_id: e });
799
- if (!t) return async () => void 0;
800
- let i = {
801
- tenantId: t,
802
- clientId: n
803
- };
804
- return async () => i;
805
- }
806
- function xe(e, t) {
807
- return {
808
- ...e.resourceServers,
809
- get: async (n, r) => {
810
- let i = await e.resourceServers.get(n, r);
811
- if (!i) return i;
812
- let a = await t(n);
813
- return !a || n === a.tenantId || !i.is_system ? i : ve(i, await e.resourceServers.get(a.tenantId, r));
814
- },
815
- list: async (n, r) => {
816
- let i = await e.resourceServers.list(n, r), a = await t(n);
817
- if (!a || n === a.tenantId) return i;
818
- let o = a.tenantId, s = i.resource_servers.filter((e) => !!(e.is_system && e.id)).map((e) => e.id);
819
- if (s.length === 0) return i;
820
- let c = /* @__PURE__ */ new Map();
821
- await Promise.all(s.map(async (t) => {
822
- let n = await e.resourceServers.get(o, t);
823
- n && c.set(t, n);
824
- }));
825
- let l = i.resource_servers.map((e) => e.is_system && e.id ? ve(e, c.get(e.id) ?? null) : e);
826
- return {
827
- ...i,
828
- resource_servers: l
829
- };
830
- }
831
- };
832
- }
833
- function Se(e, t) {
834
- let n = be({
835
- controlPlaneTenantId: t.controlPlaneTenantId,
836
- resolveControlPlane: t.resolveControlPlane
837
- });
838
- return {
839
- ...e,
840
- resourceServers: xe(e, n)
841
- };
842
- }
843
- function Ce(e, t) {
844
- let { controlPlaneTenantId: n, controlPlaneClientId: r, resolveControlPlane: i } = t, a = be({
845
- controlPlaneTenantId: n,
846
- controlPlaneClientId: r,
847
- resolveControlPlane: i
848
- });
849
- return {
850
- ...e,
851
- multiTenancyConfig: {
852
- controlPlaneTenantId: n,
853
- controlPlaneClientId: r,
854
- resolveControlPlane: i
855
- },
856
- connections: {
857
- ...e.connections,
858
- get: async (t, n) => {
859
- let r = await e.connections.get(t, n);
860
- if (!r) return r;
861
- let i = await a(t);
862
- return !i || t === i.tenantId ? r : W(r, (await e.connections.list(i.tenantId)).connections || []);
863
- },
864
- list: async (t, n) => {
865
- let r = await e.connections.list(t, n), i = await a(t);
866
- if (!i || t === i.tenantId) return r;
867
- let o = await e.connections.list(i.tenantId), s = r.connections.map((e) => W(e, o.connections || []));
868
- return {
869
- ...r,
870
- connections: s
871
- };
872
- }
873
- },
874
- clientConnections: {
875
- ...e.clientConnections,
876
- listByClient: async (t, n) => {
877
- let r = await e.clientConnections.listByClient(t, n);
878
- r.length === 0 && (r = (await e.connections.list(t)).connections || []);
879
- let i = await a(t);
880
- if (!i || t === i.tenantId) return r;
881
- let o = await e.connections.list(i.tenantId);
882
- return r.map((e) => W(e, o.connections || []));
883
- }
884
- },
885
- emailProviders: {
886
- ...e.emailProviders,
887
- get: async (t) => {
888
- let n = await e.emailProviders.get(t);
889
- if (n) return n;
890
- let r = await a(t);
891
- return !r || t === r.tenantId ? null : e.emailProviders.get(r.tenantId);
892
- }
893
- },
894
- resourceServers: xe(e, a),
895
- hooks: Te(e, a)
896
- };
897
- }
898
- function we(e) {
899
- if (!e || typeof e != "object") return !1;
900
- let t = e.metadata;
901
- return !t || typeof t != "object" ? !1 : t.inheritable === !0;
902
- }
903
- function Te(e, t) {
1791
+ function Nt(e) {
904
1792
  return {
905
- ...e.hooks,
906
- list: async (n, r) => {
907
- let i = await e.hooks.list(n, r), a = await t(n);
908
- if (!a || n === a.tenantId) return i;
909
- let o = ((await e.hooks.list(a.tenantId, r)).hooks || []).filter(we);
910
- if (o.length === 0) return i;
911
- let s = new Set((i.hooks || []).map((e) => e.hook_id)), c = o.filter((e) => !s.has(e.hook_id));
912
- return {
913
- ...i,
914
- hooks: [...i.hooks || [], ...c],
915
- length: typeof i.length == "number" ? i.length + c.length : i.length
916
- };
1793
+ resource_server: "resource server",
1794
+ role: "role",
1795
+ connection: "connection"
1796
+ }[e];
1797
+ }
1798
+ function Pt(e) {
1799
+ for (let { pattern: t, type: n } of [
1800
+ {
1801
+ pattern: /\/api\/v2\/connections\/([^/]+)$/,
1802
+ type: "connection"
917
1803
  },
918
- get: async (n, r) => {
919
- let i = await e.hooks.get(n, r);
920
- if (i) return i;
921
- let a = await t(n);
922
- if (!a || n === a.tenantId) return i;
923
- let o = await e.hooks.get(a.tenantId, r);
924
- return o && we(o) ? o : null;
1804
+ {
1805
+ pattern: /\/api\/v2\/resource-servers\/([^/]+)$/,
1806
+ type: "resource_server"
1807
+ },
1808
+ {
1809
+ pattern: /\/api\/v2\/actions\/actions\/([^/]+)$/,
1810
+ type: "action"
1811
+ },
1812
+ {
1813
+ pattern: /\/api\/v2\/hooks\/([^/]+)$/,
1814
+ type: "hook"
1815
+ },
1816
+ {
1817
+ pattern: /\/api\/v2\/hook-code\/([^/]+)$/,
1818
+ type: "hook_code"
1819
+ }
1820
+ ]) {
1821
+ let r = e.match(t);
1822
+ if (r?.[1]) return {
1823
+ type: n,
1824
+ id: r[1]
1825
+ };
1826
+ }
1827
+ return null;
1828
+ }
1829
+ async function Ft(e, t, n) {
1830
+ try {
1831
+ switch (n.type) {
1832
+ case "connection": return await e.connections.get(t, n.id);
1833
+ case "resource_server": return await e.resourceServers.get(t, n.id);
1834
+ case "action": return await e.actions.get(t, n.id);
1835
+ case "hook": return await e.hooks.get(t, n.id);
1836
+ case "hook_code": return await e.hookCode.get(t, n.id);
925
1837
  }
1838
+ } catch {
1839
+ return null;
1840
+ }
1841
+ }
1842
+ var It = {
1843
+ connection: ["options"],
1844
+ resource_server: ["signing_secret"],
1845
+ action: ["secrets"],
1846
+ hook: [],
1847
+ hook_code: []
1848
+ }, Lt = new Set([
1849
+ "client_secret",
1850
+ "app_secret",
1851
+ "twilio_token"
1852
+ ]);
1853
+ function Rt(e, t) {
1854
+ let n = (e) => {
1855
+ let { client_secret: t, ...n } = e ?? {};
1856
+ return n;
926
1857
  };
1858
+ return zt(n(e), n(t));
1859
+ }
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.` });
1863
+ }
1864
+ async function Bt(e, t, n) {
1865
+ let r = await Ft(q(e), t, n);
1866
+ if (!r) return;
1867
+ if (n.type === "hook_code") throw J(n, "cannot be modified");
1868
+ if (e.req.method === "DELETE") {
1869
+ if (r.enforce === !0) throw J(n, "cannot be deleted");
1870
+ return;
1871
+ }
1872
+ let i = r.override ?? "fields";
1873
+ if (i === "none") throw J(n, "cannot be edited");
1874
+ let a = {};
1875
+ try {
1876
+ let t = await e.req.raw.clone().json();
1877
+ t && typeof t == "object" && (a = t);
1878
+ } catch {}
1879
+ for (let e of [
1880
+ "scope",
1881
+ "override",
1882
+ "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");
1885
+ if (i === "secrets") {
1886
+ let e = It[n.type];
1887
+ for (let [t, i] of Object.entries(a)) if (![
1888
+ "scope",
1889
+ "override",
1890
+ "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})`);
1893
+ if (t === "options" && i && typeof i == "object") {
1894
+ 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})`);
1896
+ }
1897
+ }
1898
+ }
927
1899
  }
928
- function K(e, t) {
929
- return Ce(e, t);
1900
+ function Vt() {
1901
+ return async (e, t) => {
1902
+ if (![
1903
+ "PATCH",
1904
+ "PUT",
1905
+ "DELETE"
1906
+ ].includes(e.req.method)) return t();
1907
+ let n = jt(e.req.path), r = Pt(e.req.path);
1908
+ if (!n && !r) return t();
1909
+ let i = e.var.tenant_id || e.req.header("x-tenant-id") || e.req.header("tenant-id");
1910
+ 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();
1913
+ };
930
1914
  }
931
1915
  //#endregion
932
1916
  //#region src/middleware/index.ts
933
- function Ee(e) {
1917
+ function Ht(e) {
934
1918
  return async (t, n) => {
935
1919
  let r = t.var.user;
936
1920
  return r?.tenant_id === e && r.org_name && t.set("tenant_id", r.org_name), n();
937
1921
  };
938
1922
  }
939
- function De(e) {
940
- return async (n, r) => {
1923
+ function Ut(e) {
1924
+ return async (t, r) => {
941
1925
  if (!e.accessControl) return r();
942
- let { controlPlaneTenantId: i } = e.accessControl, a = n.var.org_name, o = n.var.organization_id, s = a || o, c = n.var.tenant_id, l = n.var.user, u = (l?.aud ? Array.isArray(l.aud) ? l.aud : [l.aud] : []).includes(t);
943
- if (!c && s && u && (n.set("tenant_id", s), c = s), !c) throw new w(400, { message: "Tenant ID not found in request" });
944
- if (!E(o, c, i, a)) throw new w(403, { message: `Access denied to tenant ${c}` });
1926
+ 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}` });
945
1929
  return r();
946
1930
  };
947
1931
  }
948
- function Oe(e) {
1932
+ function Wt(e) {
949
1933
  return async (t, n) => {
950
1934
  if (!e.subdomainRouting) return n();
951
1935
  let { baseDomain: r, reservedSubdomains: i = [], resolveSubdomain: a } = e.subdomainRouting, o = t.req.header("x-forwarded-host") || t.req.header("host") || "", s = null;
@@ -957,14 +1941,14 @@ function Oe(e) {
957
1941
  let c = null;
958
1942
  if (a) c = await a(s);
959
1943
  else if (e.subdomainRouting.useOrganizations !== !1 && e.accessControl) try {
960
- let n = await V(t).organizations.get(e.accessControl.controlPlaneTenantId, s);
1944
+ let n = await q(t).organizations.get(e.accessControl.controlPlaneTenantId, s);
961
1945
  n && (c = n.id);
962
1946
  } catch {}
963
1947
  if (!c) throw new w(404, { message: `Tenant not found for subdomain: ${s}` });
964
1948
  return t.set("tenant_id", c), n();
965
1949
  };
966
1950
  }
967
- function ke(e) {
1951
+ function Gt(e) {
968
1952
  return async (t, n) => {
969
1953
  if (!e.databaseIsolation) return n();
970
1954
  let r = t.var.tenant_id;
@@ -981,215 +1965,669 @@ function ke(e) {
981
1965
  return n();
982
1966
  };
983
1967
  }
984
- function q(e) {
985
- let t = Oe(e), n = De(e), r = ke(e);
1968
+ function Kt(e) {
1969
+ let t = Wt(e), n = Ut(e), r = Gt(e);
986
1970
  return async (e, i) => (await t(e, async () => {}), await n(e, async () => {}), await r(e, async () => {}), i());
987
1971
  }
988
1972
  //#endregion
1973
+ //#region src/rollouts/config.ts
1974
+ var qt = [
1975
+ 10,
1976
+ 50,
1977
+ 100
1978
+ ], Y = {
1979
+ canary: 1,
1980
+ waves: qt,
1981
+ failure_threshold: .1,
1982
+ max_concurrent: 25,
1983
+ debounce_ms: 6e4
1984
+ };
1985
+ function X(e) {
1986
+ let t = e.config ?? {};
1987
+ return {
1988
+ ...Y,
1989
+ trigger: "manual",
1990
+ root_tenant_id: "",
1991
+ ...t,
1992
+ waves: Array.isArray(t.waves) && t.waves.length > 0 ? t.waves : [...qt]
1993
+ };
1994
+ }
1995
+ function Jt(e, t, n) {
1996
+ let r = Array(e).fill(0);
1997
+ if (e === 0) return r;
1998
+ let i = Math.min(Math.max(t, 0), e), a = [], o = i;
1999
+ for (let t of n) {
2000
+ let n = Math.min(e, Math.max(o, Math.ceil(e * t / 100)));
2001
+ n > o && (a.push(n), o = n);
2002
+ }
2003
+ o < e && a.push(e);
2004
+ let s = +(i > 0), c = i;
2005
+ for (let e of a) {
2006
+ for (; c < e; c++) r[c] = s;
2007
+ s++;
2008
+ }
2009
+ return r;
2010
+ }
2011
+ //#endregion
2012
+ //#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", {
2015
+ cursorField: "id",
2016
+ pageSize: 100
2017
+ }), 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 = [];
2018
+ for (let e of i) {
2019
+ if (e.id === t || e.config_sync !== "synced") continue;
2020
+ let n = 0, i = e, c = !1;
2021
+ for (; i && n <= r;) {
2022
+ let e = await o(i);
2023
+ if (!e) break;
2024
+ if (n++, e === t) {
2025
+ c = !0;
2026
+ break;
2027
+ }
2028
+ i = a.get(e);
2029
+ }
2030
+ c && s.push({
2031
+ tenantId: e.id,
2032
+ depth: n,
2033
+ appliedHash: e.config_sync_hash ?? null
2034
+ });
2035
+ }
2036
+ return s.sort((e, t) => e.depth - t.depth || (e.tenantId < t.tenantId ? -1 : 1));
2037
+ }
2038
+ //#endregion
2039
+ //#region src/rollouts/hashes.ts
2040
+ async function Xt(e, t) {
2041
+ return e.resolveControlPlane ? (await e.resolveControlPlane({ tenant_id: t }))?.tenantId : e.controlPlaneTenantId;
2042
+ }
2043
+ function Zt(e) {
2044
+ let t = /* @__PURE__ */ new Map();
2045
+ return async (n) => {
2046
+ let r = await Xt(e, n), i = (await N({
2047
+ tenantId: n,
2048
+ getTenant: (t) => e.adapters.tenants.get(t),
2049
+ legacyControlPlane: r,
2050
+ maxDepth: e.maxDepth
2051
+ })).join(">"), a = t.get(i);
2052
+ return a || (a = et(e.adapters, n, {
2053
+ legacyControlPlane: r,
2054
+ maxDepth: e.maxDepth
2055
+ }).then((e) => e.hash), t.set(i, a)), a;
2056
+ };
2057
+ }
2058
+ //#endregion
2059
+ //#region src/rollouts/plan.ts
2060
+ var Qt = [
2061
+ "pending",
2062
+ "canary",
2063
+ "rolling",
2064
+ "paused"
2065
+ ];
2066
+ function $t(e) {
2067
+ let { tenantOperations: t, tenantOperationEvents: n } = e.adapters;
2068
+ if (!t || !n) throw Error("Fleet rollouts need the tenant operations adapters");
2069
+ return {
2070
+ tenantOperations: t,
2071
+ tenantOperationEvents: n
2072
+ };
2073
+ }
2074
+ function Z(e) {
2075
+ if (!e.adapters.rollouts) throw Error("Fleet rollouts need the rollouts adapter");
2076
+ return e.adapters.rollouts;
2077
+ }
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),
2081
+ maxDepth: e.maxDepth
2082
+ });
2083
+ if (n.tenantIds) {
2084
+ let e = new Set(n.tenantIds);
2085
+ o = o.filter((t) => e.has(t.tenantId));
2086
+ }
2087
+ let s = Zt(e), c = [];
2088
+ for (let e of o) (a.force || e.appliedHash !== await s(e.tenantId)) && c.push(e);
2089
+ let l = o.length - c.length;
2090
+ if (c.length === 0) return a.trigger === "write" ? await r.remove(t.id) : await r.update(t.id, {
2091
+ status: "done",
2092
+ finished_at: new Date(e.now?.() ?? Date.now()).toISOString(),
2093
+ config: {
2094
+ ...a,
2095
+ planned: !0,
2096
+ tenant_count: 0
2097
+ }
2098
+ }), {
2099
+ planned: 0,
2100
+ upToDate: l
2101
+ };
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, {
2104
+ kind: "sync-defaults",
2105
+ tenant_id: r.tenantId,
2106
+ rollout_id: t.id,
2107
+ initiated_by: `rollout:${t.id}`,
2108
+ input: {
2109
+ wave: d[n],
2110
+ ...a.dry_run ? { dry_run: !0 } : {},
2111
+ ...a.force ? { force: !0 } : {}
2112
+ }
2113
+ }, e.executor.engine);
2114
+ return await r.update(t.id, {
2115
+ status: "canary",
2116
+ config: {
2117
+ ...a,
2118
+ planned: !0,
2119
+ tenant_count: c.length
2120
+ }
2121
+ }), {
2122
+ planned: c.length,
2123
+ upToDate: l
2124
+ };
2125
+ }
2126
+ async function Q(e, t) {
2127
+ let { tenantOperations: n } = $t(e), r = [];
2128
+ for (let e = 0;; e++) {
2129
+ let { operations: i } = await n.list({
2130
+ rollout_id: t,
2131
+ page: e,
2132
+ per_page: 200
2133
+ });
2134
+ if (r.push(...i), i.length < 200) break;
2135
+ }
2136
+ return r.sort((e, t) => e.created_at === t.created_at ? e.id < t.id ? -1 : 1 : e.created_at < t.created_at ? -1 : 1);
2137
+ }
2138
+ //#endregion
2139
+ //#region src/rollouts/advance.ts
2140
+ var $ = (e) => {
2141
+ let t = e.input?.wave;
2142
+ 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;
2146
+ return r.length === 0 || i === 0 || i / r.length <= o ? null : `${a ? "canary" : `wave ${n}`} failed for ${i} of ${r.length} tenant(s)`;
2147
+ }
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;
2150
+ if (!i || i.kind !== "config-sync") return {
2151
+ rolloutId: String(i?.id ?? t),
2152
+ outcome: "skipped",
2153
+ started: 0
2154
+ };
2155
+ let a = i.id;
2156
+ if (!Qt.includes(i.status) || i.status === "paused") return {
2157
+ rolloutId: a,
2158
+ outcome: "skipped",
2159
+ started: 0
2160
+ };
2161
+ let o = X(i);
2162
+ if (!o.planned) {
2163
+ if (r - Date.parse(i.updated_at) < o.debounce_ms) return {
2164
+ rolloutId: a,
2165
+ outcome: "waiting",
2166
+ started: 0
2167
+ };
2168
+ let { planned: t } = await en(e, i);
2169
+ if (t === 0) return {
2170
+ rolloutId: a,
2171
+ outcome: "planned-empty",
2172
+ started: 0
2173
+ };
2174
+ i = await n.get(a) ?? i, o = X(i);
2175
+ }
2176
+ let s = await Q(e, a), c = s.filter((e) => !j(e.status));
2177
+ 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;
2179
+ return await n.update(a, {
2180
+ status: t ? "failed" : "done",
2181
+ ...t ? { paused_reason: t } : {},
2182
+ finished_at: new Date(r).toISOString()
2183
+ }), {
2184
+ rolloutId: a,
2185
+ outcome: "done",
2186
+ started: 0
2187
+ };
2188
+ }
2189
+ let l = Math.min(...c.map($)), u = l - 1;
2190
+ if (u >= 0 && u > (o.accepted_through ?? -1)) {
2191
+ let e = nn(o, s, u);
2192
+ if (e) return await n.update(a, {
2193
+ status: "paused",
2194
+ paused_reason: e
2195
+ }), {
2196
+ rolloutId: a,
2197
+ outcome: "paused",
2198
+ started: 0,
2199
+ wave: l
2200
+ };
2201
+ }
2202
+ let d = l === 0 ? "canary" : "rolling";
2203
+ 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({
2205
+ tenantOperations: h,
2206
+ tenantOperationEvents: g
2207
+ }), v = 0;
2208
+ for (let t of f.filter((e) => e.status === "pending").slice(0, m)) {
2209
+ try {
2210
+ await _.markRunning(t.id), await e.executor.start(t);
2211
+ } catch (e) {
2212
+ try {
2213
+ let n = await h.get(t.id);
2214
+ n && !j(n.status) && await _.markFailed(t.id, e);
2215
+ } catch {}
2216
+ }
2217
+ v++;
2218
+ }
2219
+ return {
2220
+ rolloutId: a,
2221
+ outcome: v > 0 ? "started" : "running",
2222
+ started: v,
2223
+ wave: l
2224
+ };
2225
+ }
2226
+ async function an(e, t = {}) {
2227
+ let { rollouts: n } = await Z(e).list({
2228
+ kind: "config-sync",
2229
+ status: [
2230
+ "pending",
2231
+ "canary",
2232
+ "rolling"
2233
+ ],
2234
+ per_page: t.limit ?? 20
2235
+ }), r = [];
2236
+ for (let i of n) try {
2237
+ r.push(await rn(e, i));
2238
+ } catch (e) {
2239
+ t.logger?.warn(`Advancing rollout ${i.id} failed:`, e);
2240
+ }
2241
+ return r;
2242
+ }
2243
+ async function on(e, t, n = "paused by an operator") {
2244
+ let r = Z(e), i = await r.get(t);
2245
+ return !i || i.kind !== "config-sync" ? null : i.status === "done" || i.status === "failed" ? i : (await r.update(t, {
2246
+ status: "paused",
2247
+ paused_reason: n
2248
+ }), r.get(t));
2249
+ }
2250
+ async function sn(e, t) {
2251
+ let n = Z(e), r = await n.get(t);
2252
+ if (!r || r.kind !== "config-sync") return null;
2253
+ 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;
2255
+ return await n.update(t, {
2256
+ status: o === 0 ? "canary" : "rolling",
2257
+ paused_reason: null,
2258
+ config: {
2259
+ ...i,
2260
+ accepted_through: Math.max(i.accepted_through ?? -1, o - 1)
2261
+ }
2262
+ }), n.get(t);
2263
+ }
2264
+ //#endregion
2265
+ //#region src/rollouts/status.ts
2266
+ async function cn(e, t) {
2267
+ let n = await e.adapters.tenants.get(t);
2268
+ if (!n) return null;
2269
+ let r = n.config_sync === "synced", i = await N({
2270
+ tenantId: t,
2271
+ getTenant: (t) => e.adapters.tenants.get(t),
2272
+ legacyControlPlane: await Xt(e, t),
2273
+ maxDepth: e.maxDepth
2274
+ }), a = r ? await Zt(e)(t) : null, o = n.config_sync_hash ?? null, s = {};
2275
+ 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) => {
2277
+ 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);
2280
+ }
2281
+ };
2282
+ 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);
2283
+ }
2284
+ return {
2285
+ tenant_id: t,
2286
+ parent_tenant_id: n.parent_tenant_id ?? null,
2287
+ config_sync: r ? "synced" : "inherit-on-read",
2288
+ config_sync_hash: o,
2289
+ config_synced_at: n.config_synced_at ?? null,
2290
+ expected_hash: a,
2291
+ drifted: r && a !== o,
2292
+ chain: i,
2293
+ inherited: s
2294
+ };
2295
+ }
2296
+ //#endregion
2297
+ //#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),
2301
+ maxDepth: e.maxDepth
2302
+ }), s = Zt(e), c = [];
2303
+ for (let e of o) {
2304
+ if (c.length >= a) break;
2305
+ try {
2306
+ let t = await s(e.tenantId);
2307
+ e.appliedHash !== t && c.push({
2308
+ tenantId: e.tenantId,
2309
+ expected: t,
2310
+ applied: e.appliedHash
2311
+ });
2312
+ } catch (t) {
2313
+ n.logger?.warn(`Could not compute the expected hash of ${e.tenantId}:`, t);
2314
+ }
2315
+ }
2316
+ let l = {
2317
+ checked: o.length,
2318
+ drifted: c.length,
2319
+ alreadyCovered: 0,
2320
+ recentlyFailed: 0
2321
+ };
2322
+ if (c.length === 0) return l;
2323
+ let u = /* @__PURE__ */ new Set(), { rollouts: d } = await r.list({
2324
+ kind: "config-sync",
2325
+ status: [...Qt],
2326
+ per_page: 100
2327
+ });
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);
2329
+ for (let r of c) try {
2330
+ await e.adapters.logs.create(r.tenantId, {
2331
+ type: t.CONFIG_DRIFT,
2332
+ date: new Date(e.now?.() ?? Date.now()).toISOString(),
2333
+ isMobile: !1,
2334
+ description: r.applied ? "hash-mismatch: applied config differs from what the parent chain publishes" : "never-synced: no config has been applied to this synced tenant",
2335
+ details: {
2336
+ reason: r.applied ? "hash-mismatch" : "never-synced",
2337
+ applied_hash: r.applied,
2338
+ expected_hash: r.expected,
2339
+ covered_by_open_rollout: u.has(r.tenantId),
2340
+ trigger: "reconcile"
2341
+ }
2342
+ });
2343
+ } catch (e) {
2344
+ n.logger?.warn(`Could not record drift for ${r.tenantId}:`, e);
2345
+ }
2346
+ let f = c.filter((e) => !u.has(e.tenantId));
2347
+ l.alreadyCovered = c.length - f.length;
2348
+ let { tenantOperations: p } = $t(e), m = e.now?.() ?? Date.now(), h = n.retryAfterMs ?? 36e5, g = [];
2349
+ for (let e of f) {
2350
+ try {
2351
+ let { operations: t } = await p.list({
2352
+ tenant_id: e.tenantId,
2353
+ kind: "sync-defaults",
2354
+ per_page: 5
2355
+ }), n = t.sort((e, t) => e.created_at === t.created_at ? e.id < t.id ? 1 : -1 : e.created_at < t.created_at ? 1 : -1)[0];
2356
+ if (n?.status === "failed" && m - Date.parse(n.updated_at) < h) {
2357
+ l.recentlyFailed++;
2358
+ continue;
2359
+ }
2360
+ } catch (t) {
2361
+ n.logger?.warn(`Could not read the latest sync of ${e.tenantId}:`, t);
2362
+ }
2363
+ g.push(e);
2364
+ }
2365
+ if (g.length === 0) return l;
2366
+ let _ = await r.create({
2367
+ kind: "config-sync",
2368
+ initiated_by: "reconcile",
2369
+ config: {
2370
+ ...Y,
2371
+ trigger: "reconcile",
2372
+ root_tenant_id: i,
2373
+ planned: !1
2374
+ }
2375
+ });
2376
+ return await en(e, _, { tenantIds: g.map((e) => e.tenantId) }), l.rolloutId = _.id, l;
2377
+ }
2378
+ //#endregion
2379
+ //#region src/rollouts/trigger.ts
2380
+ function un(e, t) {
2381
+ return e === "hookCode" ? !0 : !t || typeof t != "object" ? !1 : V(e, t) !== "local";
2382
+ }
2383
+ async function dn(e, t, n) {
2384
+ let r = Z(e), { rollouts: i } = await r.list({
2385
+ kind: "config-sync",
2386
+ status: "pending",
2387
+ per_page: 100
2388
+ }), a = i.find((e) => {
2389
+ let n = X(e);
2390
+ return n.trigger === "write" && n.planned !== !0 && n.origin_tenant_id === t;
2391
+ });
2392
+ return a ? (await r.update(a.id, {}), await r.get(a.id) ?? a) : r.create({
2393
+ kind: "config-sync",
2394
+ initiated_by: n ?? `write:${t}`,
2395
+ config: {
2396
+ ...Y,
2397
+ trigger: "write",
2398
+ root_tenant_id: t,
2399
+ origin_tenant_id: t,
2400
+ planned: !1
2401
+ }
2402
+ });
2403
+ }
2404
+ async function fn(e, t) {
2405
+ if (t === e.controlPlaneTenantId) return !0;
2406
+ try {
2407
+ let { tenants: n } = await e.adapters.tenants.list({
2408
+ q: `parent_tenant_id:${t}`,
2409
+ per_page: 1
2410
+ });
2411
+ return n.some((e) => e.parent_tenant_id === t);
2412
+ } catch {
2413
+ return !0;
2414
+ }
2415
+ }
2416
+ function pn(e, t = {}) {
2417
+ let n = async (n) => {
2418
+ try {
2419
+ await fn(e, n) && await dn(e, n);
2420
+ } catch (e) {
2421
+ t.logger?.warn(`Could not record a config change for ${n}:`, e);
2422
+ }
2423
+ }, r = (e) => ({
2424
+ afterCreate: async (t, r) => {
2425
+ un(e, r) && await n(t.tenantId);
2426
+ },
2427
+ afterUpdate: async (t, r, i) => {
2428
+ un(e, i) && await n(t.tenantId);
2429
+ },
2430
+ afterDelete: async (e) => n(e.tenantId)
2431
+ });
2432
+ return {
2433
+ actions: r("action"),
2434
+ hooks: r("hook"),
2435
+ hookCode: r("hookCode"),
2436
+ connections: r("connection"),
2437
+ resourceServers: r("resourceServer")
2438
+ };
2439
+ }
2440
+ //#endregion
2441
+ //#region src/rollouts/controller.ts
2442
+ function mn(e) {
2443
+ return {
2444
+ async create(t) {
2445
+ 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,
2451
+ trigger: "manual",
2452
+ root_tenant_id: t.rootTenantId ?? e.controlPlaneTenantId,
2453
+ dry_run: t.dryRun,
2454
+ force: t.force,
2455
+ planned: !1
2456
+ }, r = Z(e), i = await r.create({
2457
+ kind: "config-sync",
2458
+ initiated_by: t.initiatedBy,
2459
+ config: n
2460
+ });
2461
+ return await en(e, i, { tenantIds: t.tenantIds }), await rn(e, i.id), await r.get(i.id) ?? i;
2462
+ },
2463
+ pause: (t, n) => on(e, t, n),
2464
+ resume: (t) => sn(e, t)
2465
+ };
2466
+ }
2467
+ //#endregion
989
2468
  //#region src/init.ts
990
- function Ae(e) {
991
- let { dataAdapter: t, controlPlane: n, controlPlane: { tenantId: r = "control_plane", clientId: i } = {}, resolveControlPlane: a, sync: o = {
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 = {
992
2471
  resourceServers: !0,
993
2472
  roles: !0
994
- }, defaultPermissions: s = ["tenant:admin"], requireOrganizationMatch: c = !1, managementApiExtensions: l = [], entityHooks: u, getChildTenantIds: f, getAdapters: m, ...h } = e;
2473
+ }, defaultPermissions: u = ["tenant:admin"], requireOrganizationMatch: d = !1, managementApiExtensions: f = [], entityHooks: p, getChildTenantIds: h, getAdapters: g, ...v } = e;
995
2474
  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.");
996
- let g = t, _ = t;
997
- n && (g = K(t, {
998
- controlPlaneTenantId: r,
999
- controlPlaneClientId: i,
1000
- resolveControlPlane: a
1001
- }), _ = {
1002
- ...Se(t, {
1003
- controlPlaneTenantId: r,
1004
- resolveControlPlane: a
1005
- }),
1006
- multiTenancyConfig: {
2475
+ let y = t, b = t, ee;
2476
+ if (n) {
2477
+ let e = Pe({
2478
+ base: Re({
2479
+ controlPlaneTenantId: r,
2480
+ controlPlaneClientId: i,
2481
+ resolveControlPlane: a
2482
+ }),
2483
+ getTenant: async (e) => await t.tenants.get(e) ?? null,
2484
+ controlPlaneTenantId: r
2485
+ });
2486
+ ee = (t) => e.invalidate(t), y = Ue(t, {
1007
2487
  controlPlaneTenantId: r,
1008
2488
  controlPlaneClientId: i,
1009
- resolveControlPlane: a
1010
- }
1011
- });
1012
- let v = h.tenantOperationExecutor;
1013
- if (!v && t.tenantOperations && t.tenantOperationEvents && h.tenantUpgrade) {
2489
+ resolveControlPlane: a,
2490
+ inheritanceShadow: o,
2491
+ configSync: e
2492
+ }), b = {
2493
+ ...Be(t, {
2494
+ controlPlaneTenantId: r,
2495
+ resolveControlPlane: e.resolve
2496
+ }),
2497
+ multiTenancyConfig: {
2498
+ controlPlaneTenantId: r,
2499
+ controlPlaneClientId: i,
2500
+ resolveControlPlane: e.resolve
2501
+ }
2502
+ };
2503
+ }
2504
+ let te = v.tenantOperationExecutor, x;
2505
+ if (t.tenantOperations && t.tenantOperationEvents) {
1014
2506
  let e = {
1015
2507
  tenantOperations: t.tenantOperations,
1016
2508
  tenantOperationEvents: t.tenantOperationEvents
1017
- }, n = h.tenantUpgrade, r = ne({
2509
+ }, n = v.tenantUpgrade, i = A(e), o = s ?? ft(t, {
2510
+ controlPlaneTenantId: r,
2511
+ resolveControlPlane: a
2512
+ }), c = le({
1018
2513
  stores: e,
1019
- definitions: { upgrade: (e) => [{
1020
- name: "upgrade",
1021
- async run() {
1022
- if (!e.tenant_id) throw Error("upgrade operations require a tenant_id");
1023
- await n(e.tenant_id);
1024
- }
1025
- }] }
2514
+ definitions: {
2515
+ ...n ? { upgrade: (e) => [{
2516
+ name: "upgrade",
2517
+ async run() {
2518
+ if (!e.tenant_id) throw Error("upgrade operations require a tenant_id");
2519
+ await n(e.tenant_id);
2520
+ }
2521
+ }] } : {},
2522
+ "sync-defaults": (e) => [{
2523
+ name: "sync-defaults",
2524
+ run: () => dt({
2525
+ operation: e,
2526
+ syncConfig: o,
2527
+ recorder: i
2528
+ })
2529
+ }]
2530
+ }
1026
2531
  });
1027
- v = {
1028
- engine: r.engine,
1029
- enqueue: (t) => ie(e, r, {
2532
+ x = c, te ??= {
2533
+ engine: c.engine,
2534
+ kinds: n ? ["upgrade", "sync-defaults"] : ["sync-defaults"],
2535
+ enqueue: (t) => ue(e, c, {
1030
2536
  ...t,
1031
2537
  tenant_id: t.tenant_id
1032
- })
2538
+ }, { returnFailed: t.kind === "sync-defaults" })
1033
2539
  };
1034
2540
  }
1035
- let y = o !== !1, b = y ? {
1036
- resourceServers: o.resourceServers ?? !0,
1037
- roles: o.roles ?? !0
2541
+ let S = c ?? x, C = S && t.rollouts && t.tenantOperations && t.tenantOperationEvents ? {
2542
+ adapters: t,
2543
+ executor: S,
2544
+ controlPlaneTenantId: r,
2545
+ 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
1038
2549
  } : {
1039
2550
  resourceServers: !1,
1040
2551
  roles: !1
1041
- }, { entityHooks: x, tenantHooks: S } = B({
2552
+ }, { entityHooks: ne, tenantHooks: O } = Tt({
1042
2553
  controlPlaneTenantId: r,
1043
- getChildTenantIds: f ?? (async () => (await d((e) => g.tenants.list(e), "tenants", {
2554
+ getChildTenantIds: h ?? (async () => (await m((e) => y.tenants.list(e), "tenants", {
1044
2555
  cursorField: "id",
1045
2556
  pageSize: 100
1046
2557
  })).filter((e) => e.id !== r).map((e) => e.id)),
1047
- getAdapters: m ?? (async () => g),
1048
- getControlPlaneAdapters: async () => g,
1049
- sync: b
1050
- }), C = {
1051
- resourceServers: [x.resourceServers, ...u?.resourceServers ?? []],
1052
- roles: [x.roles, ...u?.roles ?? []],
1053
- connections: u?.connections ?? [],
1054
- tenants: u?.tenants ?? [],
1055
- rolePermissions: u?.rolePermissions ?? []
1056
- }, w = P({ accessControl: {
2558
+ getAdapters: g ?? (async () => y),
2559
+ getControlPlaneAdapters: async () => y,
2560
+ sync: D
2561
+ }), re = {
2562
+ resourceServers: [
2563
+ ne.resourceServers,
2564
+ T?.resourceServers,
2565
+ ...p?.resourceServers ?? []
2566
+ ],
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: {
1057
2575
  controlPlaneTenantId: r,
1058
- requireOrganizationMatch: c,
1059
- defaultPermissions: s
1060
- } }), T = H({ accessControl: {
1061
- controlPlaneTenantId: r,
1062
- requireOrganizationMatch: c,
1063
- defaultPermissions: s
1064
- } }, { tenants: {
2576
+ requireOrganizationMatch: d,
2577
+ defaultPermissions: u
2578
+ } }), ie = At({
2579
+ accessControl: {
2580
+ controlPlaneTenantId: r,
2581
+ requireOrganizationMatch: d,
2582
+ defaultPermissions: u
2583
+ },
2584
+ onConfigSyncChange: (e) => ee?.(e),
2585
+ configSyncStatus: (e) => cn({
2586
+ adapters: t,
2587
+ controlPlaneTenantId: r,
2588
+ resolveControlPlane: a
2589
+ }, e)
2590
+ }, { tenants: {
1065
2591
  async beforeCreate(e, t) {
1066
- return w.beforeCreate && (t = await w.beforeCreate(e, t)), S.beforeCreate && (t = await S.beforeCreate(e, t)), t;
2592
+ return k.beforeCreate && (t = await k.beforeCreate(e, t)), O.beforeCreate && (t = await O.beforeCreate(e, t)), t;
1067
2593
  },
1068
2594
  async afterCreate(e, t) {
1069
- await w.afterCreate?.(e, t), await S.afterCreate?.(e, t);
2595
+ await k.afterCreate?.(e, t), await O.afterCreate?.(e, t);
1070
2596
  },
1071
2597
  async beforeDelete(e, t) {
1072
- await w.beforeDelete?.(e, t), await S.beforeDelete?.(e, t);
2598
+ await k.beforeDelete?.(e, t), await O.beforeDelete?.(e, t);
1073
2599
  }
1074
- } }), { app: E } = p({
1075
- dataAdapter: g,
1076
- managementDataAdapter: _,
1077
- ...h,
1078
- tenantOperationExecutor: v,
1079
- entityHooks: C,
1080
- managementApiExtensions: [...l, {
2600
+ } }), { app: ae } = _({
2601
+ dataAdapter: y,
2602
+ managementDataAdapter: b,
2603
+ ...v,
2604
+ tenantOperationExecutor: te,
2605
+ ...w ? { rolloutController: w } : {},
2606
+ entityHooks: re,
2607
+ managementApiExtensions: [...f, {
1081
2608
  path: "/tenants",
1082
- router: T
2609
+ router: ie
1083
2610
  }],
1084
- managementApiMiddleware: [...h.managementApiMiddleware ?? [], ...y ? [U()] : []]
2611
+ managementApiMiddleware: [...v.managementApiMiddleware ?? [], ...E ? [Vt()] : []]
1085
2612
  });
1086
2613
  return {
1087
- app: E,
1088
- controlPlaneTenantId: r
1089
- };
1090
- }
1091
- //#endregion
1092
- //#region src/rollout/defaults-projection.ts
1093
- function J(e = {}) {
1094
- return {
1095
- connections: e.connections ?? !0,
1096
- resourceServers: e.resourceServers ?? !0,
1097
- hooks: e.hooks ?? !0,
1098
- emailProvider: e.emailProvider ?? !0,
1099
- branding: e.branding ?? !0,
1100
- promptSettings: e.promptSettings ?? !0
1101
- };
1102
- }
1103
- function Y() {
1104
- return {
1105
- upserted: 0,
1106
- errors: []
1107
- };
1108
- }
1109
- function je(e) {
1110
- return {
1111
- tenantId: e,
1112
- connections: Y(),
1113
- resourceServers: Y(),
1114
- hooks: Y(),
1115
- emailProvider: Y(),
1116
- branding: Y(),
1117
- promptSettings: Y()
1118
- };
1119
- }
1120
- function Me(e) {
1121
- let t = e.metadata;
1122
- return !!(t && t.inheritable === !0);
1123
- }
1124
- async function X(e, t, n, r) {
1125
- try {
1126
- await r();
1127
- } catch (r) {
1128
- let i = `${t}: ${r instanceof Error ? r.message : String(r)}`;
1129
- if (!n) throw Error(i, { cause: r });
1130
- e.errors.push(i);
1131
- }
1132
- }
1133
- async function Ne(e, t, n) {
1134
- return {
1135
- connections: n.connections ? await d((n) => e.connections.list(t, n), "connections", {
1136
- cursorField: "id",
1137
- pageSize: 100
1138
- }) : [],
1139
- resourceServers: n.resourceServers ? await d((n) => e.resourceServers.list(t, n), "resource_servers", {
1140
- cursorField: "id",
1141
- pageSize: 100
1142
- }) : [],
1143
- hooks: n.hooks ? await d((n) => e.hooks.list(t, n), "hooks", {
1144
- cursorField: "hook_id",
1145
- pageSize: 100
1146
- }) : [],
1147
- emailProvider: n.emailProvider ? await e.emailProviders.get(t) ?? null : null,
1148
- branding: n.branding ? await e.branding.get(t) ?? null : null,
1149
- promptSettings: n.promptSettings ? await e.promptSettings.get(t) ?? null : null
2614
+ app: ae,
2615
+ controlPlaneTenantId: r,
2616
+ rollouts: C
1150
2617
  };
1151
2618
  }
1152
- async function Pe(e, t, n, r, i, o) {
1153
- if (r.connections) for (let r of e.connections) {
1154
- let e = r.id;
1155
- e && await X(o.connections, `connection ${e}`, i, async () => {
1156
- let i = a.parse(r);
1157
- await t.connections.get(n, e) ? await t.connections.update(n, e, i) : await t.connections.create(n, i), o.connections.upserted += 1;
1158
- });
1159
- }
1160
- if (r.resourceServers) for (let r of e.resourceServers) !r.is_system || !r.id || await X(o.resourceServers, `resource_server ${r.id}`, i, async () => {
1161
- let e = v.parse(r);
1162
- await t.resourceServers.get(n, r.id) ? await t.resourceServers.update(n, r.id, e) : await t.resourceServers.create(n, e), o.resourceServers.upserted += 1;
1163
- });
1164
- if (r.hooks) for (let r of e.hooks) !Me(r) || !r.hook_id || await X(o.hooks, `hook ${r.hook_id}`, i, async () => {
1165
- let e = f.parse(r);
1166
- await t.hooks.get(n, r.hook_id) ? await t.hooks.update(n, r.hook_id, e) : await t.hooks.create(n, e), o.hooks.upserted += 1;
1167
- });
1168
- r.emailProvider && e.emailProvider && await X(o.emailProvider, "email_provider", i, async () => {
1169
- let r = e.emailProvider;
1170
- await t.emailProviders.get(n) ? await t.emailProviders.update(n, r) : await t.emailProviders.create(n, r), o.emailProvider.upserted += 1;
1171
- }), r.branding && e.branding && await X(o.branding, "branding", i, async () => {
1172
- await t.branding.set(n, e.branding), o.branding.upserted += 1;
1173
- }), r.promptSettings && e.promptSettings && await X(o.promptSettings, "prompt_settings", i, async () => {
1174
- await t.promptSettings.set(n, e.promptSettings), o.promptSettings.upserted += 1;
1175
- });
1176
- }
1177
- async function Z(e, t) {
1178
- let { controlPlaneTenantId: n, getControlPlaneAdapters: r, getAdapters: i, entities: a, continueOnError: o = !1 } = e, s = J(a), c = await Ne(await r(), n, s), l = await i(t), u = je(t);
1179
- return await Pe(c, l, n, s, o, u), u;
1180
- }
1181
2619
  //#endregion
1182
2620
  //#region src/rollout/payload.ts
1183
- function Fe(e) {
2621
+ function gn(e) {
1184
2622
  let { pkcs7: t, tenant_id: n, ...r } = e;
1185
2623
  return r;
1186
2624
  }
1187
- async function Ie(e, t, n = {}, r) {
1188
- let i = J(n), a = n.signingKeys ?? !0, o = n.tenants ?? !0, s = await Ne(e, t, i), c = a ? (await h(e.keys)).map(Fe) : [], l = o ? await Le(e, t, r) : [];
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) : [];
1189
2627
  return {
1190
2628
  connections: s.connections,
1191
2629
  resourceServers: s.resourceServers.filter((e) => e.is_system),
1192
- hooks: s.hooks.filter(Me),
2630
+ hooks: s.hooks.filter(_e),
1193
2631
  emailProvider: s.emailProvider,
1194
2632
  branding: s.branding,
1195
2633
  promptSettings: s.promptSettings,
@@ -1197,7 +2635,7 @@ async function Ie(e, t, n = {}, r) {
1197
2635
  tenants: l
1198
2636
  };
1199
2637
  }
1200
- async function Le(e, t, n) {
2638
+ async function vn(e, t, n) {
1201
2639
  let r = n && n !== t ? [t, n] : [t], i = [];
1202
2640
  for (let t of r) {
1203
2641
  let n = await e.tenants.get(t);
@@ -1208,19 +2646,19 @@ async function Le(e, t, n) {
1208
2646
  }
1209
2647
  return i;
1210
2648
  }
1211
- async function Re(e, t, n) {
1212
- let r = Y();
2649
+ async function yn(e, t, n) {
2650
+ let r = P();
1213
2651
  if (e.length === 0) return r;
1214
- let i = await h(t.keys), a = new Set(i.map((e) => e.kid));
1215
- for (let i of e) await X(r, `signing_key ${i.kid}`, n, async () => {
1216
- let e = Fe(i);
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);
1217
2655
  a.has(e.kid) || (await t.keys.create(e), a.add(e.kid), r.upserted += 1);
1218
2656
  });
1219
2657
  return r;
1220
2658
  }
1221
- async function ze(e, t, n) {
1222
- let r = Y();
1223
- for (let i of e) await X(r, `tenant ${i.id}`, n, async () => {
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 () => {
1224
2662
  await t.tenants.get(i.id) || (await t.tenants.create({
1225
2663
  id: i.id,
1226
2664
  friendly_name: i.friendly_name
@@ -1228,46 +2666,50 @@ async function ze(e, t, n) {
1228
2666
  });
1229
2667
  return r;
1230
2668
  }
1231
- async function Be(e, t, n, r = {}) {
1232
- let a = r.continueOnError ?? !1, o = J(r.entities), s = r.entities?.signingKeys ?? !0, c = r.entities?.tenants ?? !0, u = {
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 = {
1233
2671
  connections: e.connections,
1234
2672
  resourceServers: e.resourceServers,
1235
2673
  hooks: e.hooks,
1236
- emailProvider: e.emailProvider ? l.parse(e.emailProvider) : null,
1237
- branding: e.branding ? i.parse(e.branding) : null,
1238
- promptSettings: e.promptSettings ? g.parse(e.promptSettings) : null
1239
- }, d = c ? await ze(e.tenants ?? [], t, a) : Y(), f = je(n);
1240
- await Pe(u, t, n, o, a, f);
1241
- let p = s ? await Re(e.signingKeys, t, a) : Y();
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, {
2680
+ continueOnError: i,
2681
+ ...r.resolved
2682
+ }) : void 0;
1242
2683
  return {
1243
- ...f,
2684
+ ...d,
1244
2685
  signingKeys: p,
1245
- tenants: d
2686
+ tenants: u,
2687
+ ...m ? { resolved: m } : {}
1246
2688
  };
1247
2689
  }
1248
2690
  //#endregion
1249
2691
  //#region src/rollout/index.ts
1250
- function Ve(e) {
2692
+ function Sn(e) {
1251
2693
  return {
1252
- syncDefaults: (t) => Z(e, t),
2694
+ syncDefaults: (t) => be(e, t),
1253
2695
  syncDefaultsToTenants: async (t) => {
1254
2696
  let n = [];
1255
- for (let r of t) n.push(await Z(e, r));
2697
+ for (let r of t) n.push(await be(e, r));
1256
2698
  return n;
1257
2699
  }
1258
2700
  };
1259
2701
  }
1260
2702
  //#endregion
1261
2703
  //#region src/plugin.ts
1262
- function He(e) {
1263
- let t = Q(e);
2704
+ function Cn(e) {
2705
+ let t = wn(e);
1264
2706
  return {
1265
2707
  name: "multi-tenancy",
1266
- middleware: q(e),
2708
+ middleware: Kt(e),
1267
2709
  hooks: t,
1268
2710
  routes: [{
1269
2711
  path: "/management",
1270
- handler: H(e, t)
2712
+ handler: At(e, t)
1271
2713
  }],
1272
2714
  onRegister: async () => {
1273
2715
  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");
@@ -1276,29 +2718,29 @@ function He(e) {
1276
2718
  }
1277
2719
  //#endregion
1278
2720
  //#region src/index.ts
1279
- function Q(e) {
1280
- let t = e.accessControl ? T(e.accessControl) : {}, n = e.databaseIsolation ? D(e.databaseIsolation) : {}, r = P(e);
2721
+ function wn(e) {
2722
+ let t = e.accessControl ? ne(e.accessControl) : {}, n = e.databaseIsolation ? re(e.databaseIsolation) : {}, r = gt(e);
1281
2723
  return {
1282
2724
  ...t,
1283
2725
  ...n,
1284
2726
  tenants: r
1285
2727
  };
1286
2728
  }
1287
- function $(t) {
1288
- let n = new e(), r = Q(t);
1289
- return n.route("/tenants", H(t, r)), n;
2729
+ function Tn(t) {
2730
+ let n = new e(), r = wn(t);
2731
+ return n.route("/tenants", At(t, r)), n;
1290
2732
  }
1291
- function Ue(e) {
2733
+ function En(e) {
1292
2734
  return {
1293
- hooks: Q(e),
1294
- middleware: q(e),
1295
- app: $(e),
2735
+ hooks: wn(e),
2736
+ middleware: Kt(e),
2737
+ app: Tn(e),
1296
2738
  config: e,
1297
- wrapAdapters: (t, n) => K(t, {
2739
+ wrapAdapters: (t, n) => Ue(t, {
1298
2740
  controlPlaneTenantId: e.accessControl?.controlPlaneTenantId,
1299
2741
  controlPlaneClientId: n?.controlPlaneClientId
1300
2742
  })
1301
2743
  };
1302
2744
  }
1303
2745
  //#endregion
1304
- export { Be as applyControlPlaneDefaultsPayload, Ie as buildControlPlaneDefaultsPayload, A as buildEngineInstanceId, T as createAccessControlHooks, De as createAccessControlMiddleware, Ee as createControlPlaneTenantMiddleware, D as createDatabaseHooks, ke as createDatabaseMiddleware, Ve as createDirectRolloutAdapter, ne as createInlineExecutor, $ as createMultiTenancy, Q as createMultiTenancyHooks, q as createMultiTenancyMiddleware, He as createMultiTenancyPlugin, M as createOperationRecorder, U as createProtectSyncedMiddleware, P as createProvisioningHooks, Ce as createRuntimeFallbackAdapter, Oe as createSubdomainMiddleware, B as createSyncHooks, H as createTenantsOpenAPIRouter, ie as enqueueTenantOperation, j as errorToMessage, Ae as initMultiTenant, te as inlineStepRunner, N as isTerminalStatus, ye as mergeClientWithFallback, Z as projectControlPlaneDefaults, oe as runRecordedTenantOperation, Ue as setupMultiTenancy, E as validateTenantAccess, K as withRuntimeFallback, Se as withSystemResourceServerInheritance };
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 };