@authhero/multi-tenancy 15.2.0 → 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 (64) hide show
  1. package/dist/multi-tenancy.cjs +1 -1
  2. package/dist/multi-tenancy.mjs +2251 -1204
  3. package/dist/types/index.d.ts +5 -2
  4. package/dist/types/index.d.ts.map +1 -1
  5. package/dist/types/inheritance/legacy.d.ts.map +1 -1
  6. package/dist/types/inheritance/merge.d.ts +1 -0
  7. package/dist/types/inheritance/merge.d.ts.map +1 -1
  8. package/dist/types/inheritance/read.d.ts.map +1 -1
  9. package/dist/types/inheritance/types.d.ts +3 -1
  10. package/dist/types/inheritance/types.d.ts.map +1 -1
  11. package/dist/types/init.d.ts +28 -0
  12. package/dist/types/init.d.ts.map +1 -1
  13. package/dist/types/middleware/config-sync-mode.d.ts +36 -0
  14. package/dist/types/middleware/config-sync-mode.d.ts.map +1 -0
  15. package/dist/types/middleware/index.d.ts +3 -1
  16. package/dist/types/middleware/index.d.ts.map +1 -1
  17. package/dist/types/middleware/protect-synced.d.ts +1 -1
  18. package/dist/types/middleware/protect-synced.d.ts.map +1 -1
  19. package/dist/types/middleware/settings-inheritance.d.ts +20 -2
  20. package/dist/types/middleware/settings-inheritance.d.ts.map +1 -1
  21. package/dist/types/operations/enqueue.d.ts +8 -1
  22. package/dist/types/operations/enqueue.d.ts.map +1 -1
  23. package/dist/types/operations/index.d.ts +3 -1
  24. package/dist/types/operations/index.d.ts.map +1 -1
  25. package/dist/types/operations/recorder.d.ts +2 -0
  26. package/dist/types/operations/recorder.d.ts.map +1 -1
  27. package/dist/types/operations/sync-defaults.d.ts +55 -0
  28. package/dist/types/operations/sync-defaults.d.ts.map +1 -0
  29. package/dist/types/operations/types.d.ts +2 -0
  30. package/dist/types/operations/types.d.ts.map +1 -1
  31. package/dist/types/rollout/index.d.ts +2 -0
  32. package/dist/types/rollout/index.d.ts.map +1 -1
  33. package/dist/types/rollout/payload.d.ts +15 -0
  34. package/dist/types/rollout/payload.d.ts.map +1 -1
  35. package/dist/types/rollout/resolved-sync.d.ts +91 -0
  36. package/dist/types/rollout/resolved-sync.d.ts.map +1 -0
  37. package/dist/types/rollouts/advance.d.ts +44 -0
  38. package/dist/types/rollouts/advance.d.ts.map +1 -0
  39. package/dist/types/rollouts/config.d.ts +54 -0
  40. package/dist/types/rollouts/config.d.ts.map +1 -0
  41. package/dist/types/rollouts/controller.d.ts +29 -0
  42. package/dist/types/rollouts/controller.d.ts.map +1 -0
  43. package/dist/types/rollouts/enumerate.d.ts +25 -0
  44. package/dist/types/rollouts/enumerate.d.ts.map +1 -0
  45. package/dist/types/rollouts/hashes.d.ts +10 -0
  46. package/dist/types/rollouts/hashes.d.ts.map +1 -0
  47. package/dist/types/rollouts/index.d.ts +19 -0
  48. package/dist/types/rollouts/index.d.ts.map +1 -0
  49. package/dist/types/rollouts/plan.d.ts +29 -0
  50. package/dist/types/rollouts/plan.d.ts.map +1 -0
  51. package/dist/types/rollouts/reconcile.d.ts +38 -0
  52. package/dist/types/rollouts/reconcile.d.ts.map +1 -0
  53. package/dist/types/rollouts/status.d.ts +28 -0
  54. package/dist/types/rollouts/status.d.ts.map +1 -0
  55. package/dist/types/rollouts/trigger.d.ts +52 -0
  56. package/dist/types/rollouts/trigger.d.ts.map +1 -0
  57. package/dist/types/rollouts/types.d.ts +25 -0
  58. package/dist/types/rollouts/types.d.ts.map +1 -0
  59. package/dist/types/routes/tenants.d.ts.map +1 -1
  60. package/dist/types/types.d.ts +12 -0
  61. package/dist/types/types.d.ts.map +1 -1
  62. package/dist/types/utils/tenant-tree.d.ts +2 -1
  63. package/dist/types/utils/tenant-tree.d.ts.map +1 -1
  64. package/package.json +5 -5
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("hono"),t=require("authhero"),n=require("@hono/zod-openapi"),r=require("hono/http-exception");function i(e){let{controlPlaneTenantId:t,requireOrganizationMatch:n=!0}=e;return{async onTenantAccessValidation(e,r){if(r===t)return!0;if(n){let t=e.var.org_name,n=e.var.organization_id,i=t||n;return i?i.toLowerCase()===r.toLowerCase():!1}return!0}}}function a(e,t,n,r){if(t===n)return!0;let i=r||e;return i?i.toLowerCase()===t.toLowerCase():!1}function o(e){return{async resolveDataAdapters(t){try{return await e.getAdapters(t)}catch(e){console.error(`Failed to resolve data adapters for tenant ${t}:`,e);return}}}}var s=64;function c(e){return e.replace(/[^a-zA-Z0-9_-]/g,`-`)}function l(e){let t=c(e.id),n=Math.max(0,s-(5+t.length)),r=c(e.kind).slice(0,n),i=3+r.length+2+t.length,a=Math.max(0,s-i);return`op-${r}-${c(e.tenant_id??`fleet`).slice(0,a)}-${t}`.slice(0,s)}var u=2048;function d(e){let t;if(e instanceof Error)t=e.message;else try{t=String(e??`unknown error`)}catch{t=Object.prototype.toString.call(e)}return t.slice(0,u)}function f(e){let{tenantOperations:t,tenantOperationEvents:n}=e;return{async markRunning(e,n){await t.update(e,{status:`running`,...n===void 0?{}:{current_step:n}})},async setCurrentStep(e,n){await t.update(e,{current_step:n})},async appendEvent(e,t){await n.create({operation_id:e,step:t.step,outcome:t.outcome,detail:t.detail,attempt:t.attempt??1})},async markSucceeded(e){await t.update(e,{status:`succeeded`,error:null,finished_at:new Date().toISOString()})},async markFailed(e,n){await t.update(e,{status:`failed`,error:d(n),finished_at:new Date().toISOString()})}}}function p(e){return e===`succeeded`||e===`failed`||e===`cancelled`}var m={async do(e,t,n){let r=typeof t==`function`?t:n;if(!r)throw Error(`StepRunner.do called without a function`);return r()}};function h(e){let t=f(e.stores);return{engine:`inline`,async start(n){let r=e.definitions[n.kind];if(!r){let e=Error(`No inline operation definition for kind "${n.kind}"`);throw await t.markFailed(n.id,e),e}let i=r(n);await t.markRunning(n.id,i[0]?.name);for(let e of i){await t.setCurrentStep(n.id,e.name),await t.appendEvent(n.id,{step:e.name,outcome:`started`});try{let r=await e.run({operation:n,step:m});await t.appendEvent(n.id,{step:e.name,outcome:`succeeded`,detail:r??void 0})}catch(r){throw await t.appendEvent(n.id,{step:e.name,outcome:`failed`,detail:{message:d(r)}}),await t.markFailed(n.id,r),r}}await t.markSucceeded(n.id)}}}async function g(e,t,n){let r=await e.tenantOperations.create({tenant_id:t.tenant_id,rollout_id:t.rollout_id,kind:t.kind,engine:n,initiated_by:t.initiated_by,target_worker_version:t.target_worker_version,target_database_version:t.target_database_version}),i=l(r);try{await e.tenantOperations.update(r.id,{engine_instance_id:i})}catch(t){try{await f(e).markFailed(r.id,t)}catch{}throw t}return{...r,engine_instance_id:i}}async function _(e,t,n){let r=f(e),i=await g(e,n,t.engine);try{await t.start(i)}catch(t){try{let n=await e.tenantOperations.get(i.id);n&&!p(n.status)&&await r.markFailed(i.id,t)}catch(e){console.warn(`Failed to record tenant operation failure:`,e)}throw t}try{return await e.tenantOperations.get(i.id)??i}catch(e){return console.warn(`Failed to re-fetch tenant operation after start:`,e),i}}function v(e){if(e.tenantOperations&&e.tenantOperationEvents)return{tenantOperations:e.tenantOperations,tenantOperationEvents:e.tenantOperationEvents}}async function y(e,t,n){let r=v(e);if(!r){await n(void 0);return}let i=f(r),a=async e=>{try{await e()}catch(e){console.warn(`Failed to record tenant operation progress:`,e)}},o;if(await a(async()=>{let e=await g(r,t,`inline`);o=e.id,await i.markRunning(e.id)}),!o){await n(void 0);return}let s=o,c=!1,l=async(e,t,n)=>{c=!0,await a(async()=>{t===`started`&&await i.setCurrentStep(s,e),await i.appendEvent(s,{step:e,outcome:t,detail:n})})};try{await n(l)}catch(e){throw await a(async()=>{c||await i.appendEvent(s,{step:t.kind,outcome:`failed`,detail:{message:d(e)}}),await i.markFailed(s,e)}),e}await a(async()=>{c||await i.appendEvent(s,{step:t.kind,outcome:`succeeded`}),await i.markSucceeded(s)})}function b(e){return`urn:authhero:tenant:${e.toLowerCase()}`}function x(e){return{async beforeCreate(e,t){return!t.audience&&t.id?{...t,audience:b(t.id)}:t},async afterCreate(n,r){let{accessControl:i,databaseIsolation:a}=e;if(i&&n.ctx&&await S(n,r,i),a?.onProvision){let e=a.onProvision;a.recordProvisionOperations===!1?await e(r.id):await y(n.adapters,{kind:`provision`,tenant_id:r.id,initiated_by:n.ctx?.var.user?.sub},t=>e(r.id,t))}else try{await(0,t.provisionDefaultClients)(n.adapters,r.id,{managementApiIdentifier:t.MANAGEMENT_API_AUDIENCE,managementApiScopes:t.MANAGEMENT_API_SCOPES})}catch(e){throw console.warn(`Failed to provision default clients for tenant ${r.id}:`,e),e}},async beforeDelete(t,n){let{accessControl:r,databaseIsolation:i}=e;if(r)try{let e=(await t.adapters.organizations.list(r.controlPlaneTenantId)).organizations.find(e=>e.name===n);e&&await t.adapters.organizations.remove(r.controlPlaneTenantId,e.id)}catch(e){console.warn(`Failed to remove organization for tenant ${n}:`,e)}if(i?.onDeprovision)try{await i.onDeprovision(n)}catch(e){console.warn(`Failed to deprovision database for tenant ${n}:`,e)}}}}async function S(e,t,n){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,{name:t.id,display_name:t.friendly_name||t.id}),d;if(o&&(d=await C(e,r,s,c)),l&&e.ctx){let t=e.ctx.var.user;if(t?.sub&&!await ee(e,r,t.sub))try{await e.adapters.userOrganizations.create(r,{user_id:t.sub,organization_id:u.id}),d&&await e.adapters.userRoles.create(r,t.sub,d,u.id)}catch(e){console.warn(`Failed to add creator ${t.sub} to organization ${u.id}:`,e)}}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}`)}async function ee(e,n,r){let i=await e.adapters.userRoles.list(n,r,void 0,``);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.MANAGEMENT_API_AUDIENCE))return!0;return!1}async function C(e,n,r,i){let a=(await e.adapters.roles.list(n,{})).roles.find(e=>e.name===r);if(a)return a.id;let o=await e.adapters.roles.create(n,{name:r,description:i}),s=t.MANAGEMENT_API_AUDIENCE,c=t.MANAGEMENT_API_SCOPES.map(e=>({role_id:o.id,resource_server_identifier:s,permission_name:e.value}));return await e.adapters.rolePermissions.assign(n,o.id,c),o.id}function w(e,n,r=()=>!0){let{controlPlaneTenantId:i,getChildTenantIds:a,getAdapters:o}=e,s=new Map;async function c(e,r,i){return(await n(e).list(r,{q:`name:${(0,t.escapeLuceneValue)(i)}`,per_page:1}))[0]??null}async function l(e){let t=await a(),r=n(await o(i));await Promise.all(t.map(async t=>{try{let i=await o(t),a=n(i),s={...r.transform(e),is_system:!0},l=await c(i,t,e.name),u=l?a.getId(l):void 0;if(l&&u){let e=a.preserveOnUpdate?a.preserveOnUpdate(l,s):s;await a.update(t,u,e)}else await a.create(t,s)}catch(n){console.error(`Failed to sync ${r.listKey} "${e.name}" to tenant "${t}":`,n)}}))}async function u(e){let t=await a();await Promise.all(t.map(async t=>{try{let r=await o(t),i=n(r),a=await c(r,t,e),s=a?i.getId(a):void 0;a&&s&&await i.remove(t,s)}catch(n){console.error(`Failed to delete entity "${e}" from tenant "${t}":`,n)}}))}return{afterCreate:async(e,t)=>{e.tenantId===i&&r(t)&&await l(t)},afterUpdate:async(e,t,n)=>{e.tenantId===i&&r(n)&&await l(n)},beforeDelete:async(e,t)=>{if(e.tenantId!==i)return;let a=await n(e.adapters).get(e.tenantId,t);a&&r(a)&&s.set(t,a)},afterDelete:async(e,t)=>{if(e.tenantId!==i)return;let n=s.get(t);n&&(s.delete(t),await u(n.name))}}}function T(e,n,r=()=>!0){let{controlPlaneTenantId:i,getControlPlaneAdapters:a,getAdapters:o}=e;return{async afterCreate(e,s){if(s.id!==i)try{let e=await a(),c=await o(s.id),l=n(e),u=n(c),d=await(0,t.fetchAll)(e=>l.listPaginated(i,e),l.listKey,{cursorField:`id`,pageSize:100});await Promise.all(d.filter(e=>r(e)).map(async e=>{try{let t=l.transform(e);await u.create(s.id,{...t,is_system:!0})}catch(e){console.error(`Failed to sync entity to new tenant "${s.id}":`,e)}}))}catch(e){console.error(`Failed to sync entities to new tenant "${s.id}":`,e)}}}}var E=e=>({list:async(t,n)=>(await e.resourceServers.list(t,n)).resource_servers,listPaginated:(t,n)=>e.resourceServers.list(t,n),get:(t,n)=>e.resourceServers.get(t,n),create:(t,n)=>e.resourceServers.create(t,n),update:(t,n,r)=>e.resourceServers.update(t,n,r),remove:(t,n)=>e.resourceServers.remove(t,n),listKey:`resource_servers`,getId:e=>e.id,transform:e=>({id:e.id,name:e.name,identifier:e.identifier,scopes:e.scopes,signing_alg:e.signing_alg,token_lifetime:e.token_lifetime,token_lifetime_for_web:e.token_lifetime_for_web})}),D=e=>({list:async(t,n)=>(await e.roles.list(t,n)).roles,listPaginated:(t,n)=>e.roles.list(t,n),get:(t,n)=>e.roles.get(t,n),create:(t,n)=>e.roles.create(t,n),update:(t,n,r)=>e.roles.update(t,n,r),remove:(t,n)=>e.roles.remove(t,n),listKey:`roles`,getId:e=>e.id,transform:e=>({id:e.id,name:e.name,description:e.description})});function O(e){return e.metadata?.sync!==!1}function te(e){let{sync:n={},filters:r={}}=e,i=n.resourceServers??!0,a=n.roles??!0,o=e=>O(e)?r.resourceServers?r.resourceServers(e):!0:!1,s=e=>O(e)?r.roles?r.roles(e):!0:!1,c=i?w(e,E,o):void 0,l=a?w(e,D,s):void 0,u=i?T(e,E,o):void 0,d=a?T(e,D,s):void 0,f=a?{async afterCreate(n,i){if(i.id!==e.controlPlaneTenantId){await d?.afterCreate?.(n,i);try{let n=await e.getControlPlaneAdapters(),a=await e.getAdapters(i.id),o=await(0,t.fetchAll)(t=>n.roles.list(e.controlPlaneTenantId,t),`roles`,{cursorField:`id`,pageSize:100}),s=new Map;for(let e of o.filter(e=>r.roles?.(e)??!0)){let t=await p(a,i.id,e.name);t&&s.set(e.name,t.id)}for(let t of o.filter(e=>r.roles?.(e)??!0)){let r=s.get(t.name);if(r)try{let o=await n.rolePermissions.list(e.controlPlaneTenantId,t.id,{});o.length>0&&await a.rolePermissions.assign(i.id,r,o.map(e=>({role_id:r,resource_server_identifier:e.resource_server_identifier,permission_name:e.permission_name})))}catch(e){console.error(`Failed to sync permissions for role "${t.name}" to tenant "${i.id}":`,e)}}}catch(e){console.error(`Failed to sync role permissions to tenant "${i.id}":`,e)}}}}:void 0;async function p(e,n,r){return(await e.roles.list(n,{q:`name:${(0,t.escapeLuceneValue)(r)}`,per_page:1})).roles[0]??null}return{entityHooks:{resourceServers:c,roles:l},tenantHooks:{async afterCreate(e,t){let n=[u?.afterCreate,f?.afterCreate??d?.afterCreate],r=[];for(let i of n)if(i)try{await i(e,t)}catch(e){r.push(e instanceof Error?e:Error(String(e)))}if(r.length===1)throw r[0];if(r.length>1)throw AggregateError(r,r.map(e=>e.message).join(`; `))}}}}function k(e){return e.var.data??e.env.data}async function ne(e){let{tenantId:t,parentTenantId:n,getTenant:i,getChildren:a}=e,o=e.maxDepth??2;if(!n)return;if(t&&n===t)throw new r.HTTPException(400,{message:`A tenant cannot be its own parent`});let s=new Set(t?[t]:[]),c=0,l=n;for(;l;){if(s.has(l))throw new r.HTTPException(400,{message:`Setting parent_tenant_id to '${n}' would create a cycle`});s.add(l);let e=await i(l);if(!e)throw new r.HTTPException(400,{message:`Parent tenant '${l}' not found`});if(c+=1,c>o)throw new r.HTTPException(400,{message:`Tenant tree is limited to ${o} levels above a tenant`});l=e.parent_tenant_id}if(t&&a){let e=new Set([t]),i=0,s=[t];for(;s.length>0;){let t=[];for(let n of s)for(let r of await a(n))e.has(r)||(e.add(r),t.push(r));if(t.length>0&&(i+=1,c+i>o))throw new r.HTTPException(400,{message:`Moving tenant under '${n}' would make its descendant '${t[0]}' exceed the tenant tree limit of ${o} levels`});s=t}}}var re=n.z.object({sub:n.z.string(),tenant_id:n.z.string().optional(),org_id:n.z.string().optional(),scope:n.z.string().optional(),permissions:n.z.array(n.z.string()).optional()}).passthrough();function ie(e){let t=re.safeParse(e);return t.success?t.data:void 0}function ae(e){let t=e.permissions??[],n=e.scope?e.scope.split(` `).filter(Boolean):[],r=new Set([...t,...n]);return r.has(`delete:tenants`)||r.has(`admin:organizations`)}function A(e,i){let a=new n.OpenAPIHono;return a.openapi((0,n.createRoute)({tags:[`tenants`],method:`get`,path:`/`,request:{query:t.auth0QuerySchema},security:[{Bearer:[]}],responses:{200:{content:{"application/json":{schema:n.z.object({tenants:n.z.array(t.tenantSchema),start:n.z.number().optional(),limit:n.z.number().optional(),length:n.z.number().optional(),total:n.z.number().optional()})}},description:`List of tenants`}}}),async n=>{let{page:i,per_page:a,include_totals:o,q:s}=n.req.valid(`query`),c=n.var.user,l=c?.permissions||[];if(!(c?.org_id??n.var.organization_id)&&l.includes(`admin:organizations`)){let e=await k(n).tenants.list({page:i,per_page:a,include_totals:o,q:s});return o?n.json({tenants:e.tenants,start:e.totals?.start??0,limit:e.totals?.limit??a,length:e.tenants.length,total:e.totals?.length}):n.json({tenants:e.tenants})}let u=e.accessControl?.controlPlaneTenantId??k(n).multiTenancyConfig?.controlPlaneTenantId;if(u&&!c?.sub)throw new r.HTTPException(403,{message:`Access denied: token has no subject`});if(u&&c?.sub){let e=(await(0,t.fetchAll)(e=>k(n).userOrganizations.listUserOrganizations(u,c.sub,e),`organizations`)).map(e=>e.name);if(e.length===0)return o?n.json({tenants:[],start:0,limit:a??50,length:0,total:0}):n.json({tenants:[]});let r=e.length,l=i??0,d=a??50,f=l*d,p=e.slice(f,f+d);if(p.length===0)return o?n.json({tenants:[],start:f,limit:d,length:0,total:r}):n.json({tenants:[]});let m=p.map(e=>`id:${e}`).join(` OR `),h=s?`(${m}) AND (${s})`:m,g=await k(n).tenants.list({q:h,per_page:d,include_totals:!1});return o?n.json({tenants:g.tenants,start:f,limit:d,length:g.tenants.length,total:r}):n.json({tenants:g.tenants})}let d=await k(n).tenants.list({page:i,per_page:a,include_totals:o,q:s});return o?n.json({tenants:d.tenants,start:d.totals?.start??0,limit:d.totals?.limit??a,length:d.tenants.length,total:d.totals?.length}):n.json({tenants:d.tenants})}),a.openapi((0,n.createRoute)({tags:[`tenants`],method:`post`,path:`/`,request:{body:{content:{"application/json":{schema:t.tenantInsertSchema}}}},security:[{Bearer:[]}],responses:{201:{content:{"application/json":{schema:t.tenantSchema}},description:`Tenant created`},400:{description:`Validation error`},409:{description:`Tenant with this ID already exists`}}}),async e=>{if(!e.var.user?.sub)throw new r.HTTPException(401,{message:`Authentication required to create tenants`});let t=e.req.valid(`json`),n={adapters:k(e),ctx:e};i.tenants?.beforeCreate&&(t=await i.tenants.beforeCreate(n,t)),await ne({tenantId:t.id,parentTenantId:t.parent_tenant_id,getTenant:t=>k(e).tenants.get(t)});let a=await k(e).tenants.create(t);return i.tenants?.afterCreate&&await i.tenants.afterCreate(n,a),e.json(a,201)}),a.openapi((0,n.createRoute)({tags:[`tenants`],method:`delete`,path:`/{id}`,request:{params:n.z.object({id:n.z.string()})},security:[{Bearer:[`delete:tenants`]}],responses:{204:{description:`Tenant deleted`},403:{description:`Access denied or cannot delete the control plane`},404:{description:`Tenant not found`}}}),async n=>{let{id:a}=n.req.valid(`param`),o=e.accessControl?.controlPlaneTenantId??k(n).multiTenancyConfig?.controlPlaneTenantId;if(o){let e=ie(n.var.user);if(!e?.sub)throw new r.HTTPException(401,{message:`Authentication required`});if(a===o)throw new r.HTTPException(403,{message:`Cannot delete the control plane`});let i=n.var.org_name,s=a.toLowerCase(),c=!!i&&i.toLowerCase()===s;if(!c){let t=!!(e.org_id??n.var.organization_id??i),r=!e.tenant_id||e.tenant_id===o;!t&&r&&ae(e)&&(c=!0)}if(c||=(await(0,t.fetchAll)(t=>k(n).userOrganizations.listUserOrganizations(o,e.sub,t),`organizations`)).some(e=>e.name?.toLowerCase()===s),!c)throw new r.HTTPException(403,{message:`Access denied to this tenant`})}if(!await k(n).tenants.get(a))throw new r.HTTPException(404,{message:`Tenant not found`});let s={adapters:k(n),ctx:n};return i.tenants?.beforeDelete&&await i.tenants.beforeDelete(s,a),await k(n).tenants.remove(a),i.tenants?.afterDelete&&await i.tenants.afterDelete(s,a),n.body(null,204)}),a.openapi((0,n.createRoute)({tags:[`tenants`,`settings`],method:`get`,path:`/settings`,request:{headers:n.z.object({"tenant-id":n.z.string().optional()})},security:[{Bearer:[`read:tenants`]}],responses:{200:{content:{"application/json":{schema:t.tenantSchema}},description:`Current tenant settings`}}}),async e=>{let t=await k(e).tenants.get(e.var.tenant_id);if(!t)throw new r.HTTPException(404,{message:`Tenant not found`});return e.json(t)}),a.openapi((0,n.createRoute)({tags:[`tenants`,`settings`],method:`patch`,path:`/settings`,request:{headers:n.z.object({"tenant-id":n.z.string().optional()}),body:{content:{"application/json":{schema:n.z.object(t.tenantInsertSchema.shape).partial()}}}},security:[{Bearer:[`update:tenants`]}],responses:{200:{content:{"application/json":{schema:t.tenantSchema}},description:`Updated tenant settings`}}}),async e=>{let{id:n,...i}=e.req.valid(`json`),a=await k(e).tenants.get(e.var.tenant_id);if(!a)throw new r.HTTPException(404,{message:`Tenant not found`});if(`default_client_id`in i){let n=i.default_client_id;if(typeof n==`string`&&n.length>0){let i=await k(e).clients.get(e.var.tenant_id,n);if(!i)throw new r.HTTPException(400,{message:`Client with id '${n}' not found`});if(!(0,t.isInteractiveClient)(i))throw new r.HTTPException(400,{message:`Client '${n}' is not an interactive client and cannot be used as the default client`})}}`parent_tenant_id`in i&&await ne({tenantId:e.var.tenant_id,parentTenantId:i.parent_tenant_id,getTenant:t=>k(e).tenants.get(t),getChildren:async n=>(await(0,t.fetchAll)(t=>k(e).tenants.list(t),`tenants`)).filter(e=>e.parent_tenant_id===n).map(e=>e.id)});let o=(0,t.deepMergePatch)(a,i);await k(e).tenants.update(e.var.tenant_id,o);let s=await k(e).tenants.get(e.var.tenant_id);if(!s)throw new r.HTTPException(500,{message:`Failed to retrieve updated tenant`});return e.json(s)}),a}function oe(e){for(let{pattern:t,type:n}of[{pattern:/\/api\/v2\/resource-servers\/([^/]+)$/,type:`resource_server`},{pattern:/\/api\/v2\/roles\/([^/]+)$/,type:`role`},{pattern:/\/api\/v2\/connections\/([^/]+)$/,type:`connection`}]){let r=e.match(t);if(r&&r[1])return{type:n,id:r[1]}}return null}async function se(e,t,n){try{switch(n.type){case`resource_server`:return(await e.resourceServers.get(t,n.id))?.is_system===!0;case`role`:return(await e.roles.get(t,n.id))?.is_system===!0;case`connection`:return(await e.connections.get(t,n.id))?.is_system===!0;default:return!1}}catch{return!1}}function ce(e){return{resource_server:`resource server`,role:`role`,connection:`connection`}[e]}function j(){return async(e,t)=>{if(![`PATCH`,`PUT`,`DELETE`].includes(e.req.method))return t();let n=oe(e.req.path);if(!n)return t();let i=e.var.tenant_id||e.req.header(`x-tenant-id`)||e.req.header(`tenant-id`);if(!i)return t();if(await se(k(e),i,n))throw new r.HTTPException(403,{message:`This ${ce(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`});return t()}}async function le(e){let{tenantId:t,getTenant:n,legacyControlPlane:i}=e,a=e.maxDepth??2,o=await n(t);if(!o?.parent_tenant_id)return i&&i!==t?[i]:[];let s=[],c=new Set([t]),l=o.parent_tenant_id;for(;l;){if(c.has(l))throw new r.HTTPException(400,{message:`Tenant chain for '${t}' contains a cycle at '${l}'`});if(c.add(l),s.length>=a)throw new r.HTTPException(400,{message:`Tenant chain for '${t}' is deeper than ${a}`});let e=await n(l);if(!e)break;s.push(l),l=e.parent_tenant_id}return s}function M(e){let t={};for(let n of e??[])n.value!==void 0&&(t[n.name]=n.value);return t}function ue(e,t){if(!e.inherit)return e;let n=t.find(t=>t.name===e.name&&t.is_system);if(!n)return e;let r={...M(n.secrets),...M(e.secrets)};return{...e,code:n.code,secrets:Object.entries(r).map(([e,t])=>({name:e,value:t}))}}function de(e,t){if(!t)return e;let n=new Set(e.hooks.map(e=>e.hook_id)),r=t.hooks.filter(e=>X(e)&&!n.has(e.hook_id));return{connections:e.connections.map(e=>q(e,t.connections)),resourceServers:e.resourceServers.map(e=>e.is_system?Y(e,t.resourceServers.find(t=>t.id===e.id)??null):e),hooks:[...e.hooks,...r],actions:e.actions.map(e=>ue(e,t.actions)),emailProvider:e.emailProvider??t.emailProvider,branding:e.branding,promptSettings:e.promptSettings}}var fe=()=>({connections:[],resourceServers:[],hooks:[],actions:[],emailProvider:null,branding:null,promptSettings:null});function N(e,t){if(t.scope)return t.scope;switch(e){case`connection`:case`emailProvider`:return`shared`;case`resourceServer`:case`action`:return t.is_system?`shared`:`local`;case`hook`:return X(t)?`shared`:`local`;default:return`local`}}function P(e){return e.override??`fields`}var pe=/secret|password|private_key|api_key|token/i;function me(e,t){let n={...e??{}};for(let[e,r]of Object.entries(t??{}))pe.test(e)&&(n[e]=r);return n}function F(e,t){switch(P(e)){case`none`:return{...e,id:t.id};case`secrets`:return{...e,id:t.id,options:me(e.options,t.options)};default:return{...e,...t,options:{...e.options??{},...t.options??{}}}}}function he(e,t){switch(P(e)){case`none`:return{...e,id:t.id};case`secrets`:return{...e,id:t.id,signing_secret:t.signing_secret??e.signing_secret};default:return{...t,scopes:je(t.scopes,e.scopes)}}}function I(e){return new Map((e??[]).map(e=>[e.name,e]))}function ge(e,t){let n=P(e);if(n===`none`)return{...e,id:t.id};let r=I(e.secrets);if(n===`secrets`||n===`fields`)for(let[e,n]of I(t.secrets))r.set(e,n);return{...n===`fields`&&!t.inherit?t:e,id:t.id,secrets:[...r.values()]}}function _e(e,t){let n=new Set,r=[...e].reverse().concat(t),i=(e,t,r,i)=>r?t:t.filter(t=>{let r=N(e,t);return r===`local`?!1:(r===`platform`&&n.add(`${e}:${i(t)}`),!0)}),a=fe(),o=e=>`${e.strategy}:${e.name}`,s=e=>e.identifier,c=e=>e.hook_id??``,l=e=>e.name,u=new Map,d=[],f=new Map,p=new Map,m=new Map;r.forEach((e,t)=>{let h=t===r.length-1;for(let t of i(`connection`,e.connections,h,o)){let e=u.get(t.strategy);h?d.push(e?F(e,t):t):u.set(t.strategy,e?F(e,t):t)}for(let t of i(`resourceServer`,e.resourceServers,h,s)){let e=f.get(s(t));f.set(s(t),e?he(e,t):t)}for(let t of i(`hook`,e.hooks,h,c))p.set(c(t),t);for(let t of i(`action`,e.actions,h,l)){let e=m.get(l(t));m.set(l(t),e?ge(e,t):t)}for(let t of[`emailProvider`,`branding`,`promptSettings`]){let r=e[t];r&&(h||N(t,r)!==`local`)&&(!h&&N(t,r)===`platform`&&n.add(`${t}:singleton`),a[t]=r)}});let h=new Set(r[r.length-1].connections.map(e=>e.strategy));return a.connections=[...d,...[...u.values()].filter(e=>!h.has(e.strategy))],a.resourceServers=[...f.values()],a.hooks=[...p.values()],a.actions=[...m.values()],{...a,hidden:[...n]}}function L(e={}){return{connections:e.connections??!0,resourceServers:e.resourceServers??!0,hooks:e.hooks??!0,emailProvider:e.emailProvider??!0,branding:e.branding??!0,promptSettings:e.promptSettings??!0}}function R(){return{upserted:0,errors:[]}}function ve(e){return{tenantId:e,connections:R(),resourceServers:R(),hooks:R(),emailProvider:R(),branding:R(),promptSettings:R()}}function z(e){let t=e.metadata;return!!(t&&t.inheritable===!0)}async function B(e,t,n,r){try{await r()}catch(r){let i=`${t}: ${r instanceof Error?r.message:String(r)}`;if(!n)throw Error(i,{cause:r});e.errors.push(i)}}async function V(e,n,r){return{connections:r.connections?await(0,t.fetchAll)(t=>e.connections.list(n,t),`connections`,{cursorField:`id`,pageSize:100}):[],resourceServers:r.resourceServers?await(0,t.fetchAll)(t=>e.resourceServers.list(n,t),`resource_servers`,{cursorField:`id`,pageSize:100}):[],hooks:r.hooks?await(0,t.fetchAll)(t=>e.hooks.list(n,t),`hooks`,{cursorField:`hook_id`,pageSize:100}):[],emailProvider:r.emailProvider?await e.emailProviders.get(n)??null:null,branding:r.branding?await e.branding.get(n)??null:null,promptSettings:r.promptSettings?await e.promptSettings.get(n)??null:null}}async function H(e,n,r,i,a,o){if(i.connections)for(let i of e.connections){let e=i.id;e&&await B(o.connections,`connection ${e}`,a,async()=>{let a=t.connectionInsertSchema.parse(i);await n.connections.get(r,e)?await n.connections.update(r,e,a):await n.connections.create(r,a),o.connections.upserted+=1})}if(i.resourceServers)for(let i of e.resourceServers)!i.is_system||!i.id||await B(o.resourceServers,`resource_server ${i.id}`,a,async()=>{let e=t.resourceServerInsertSchema.parse(i);await n.resourceServers.get(r,i.id)?await n.resourceServers.update(r,i.id,e):await n.resourceServers.create(r,e),o.resourceServers.upserted+=1});if(i.hooks)for(let i of e.hooks)!z(i)||!i.hook_id||await B(o.hooks,`hook ${i.hook_id}`,a,async()=>{let e=t.hookInsertSchema.parse(i);await n.hooks.get(r,i.hook_id)?await n.hooks.update(r,i.hook_id,e):await n.hooks.create(r,e),o.hooks.upserted+=1});i.emailProvider&&e.emailProvider&&await B(o.emailProvider,`email_provider`,a,async()=>{let t=e.emailProvider;await n.emailProviders.get(r)?await n.emailProviders.update(r,t):await n.emailProviders.create(r,t),o.emailProvider.upserted+=1}),i.branding&&e.branding&&await B(o.branding,`branding`,a,async()=>{await n.branding.set(r,e.branding),o.branding.upserted+=1}),i.promptSettings&&e.promptSettings&&await B(o.promptSettings,`prompt_settings`,a,async()=>{await n.promptSettings.set(r,e.promptSettings),o.promptSettings.upserted+=1})}async function U(e,t){let{controlPlaneTenantId:n,getControlPlaneAdapters:r,getAdapters:i,entities:a,continueOnError:o=!1}=e,s=L(a),c=await V(await r(),n,s),l=await i(t),u=ve(t);return await H(c,l,n,s,o,u),u}async function W(e,n){let r=await V(e,n,{connections:!0,resourceServers:!0,hooks:!0,emailProvider:!0,branding:!0,promptSettings:!0}),i=await(0,t.fetchAll)(t=>e.actions.list(n,t),`actions`,{cursorField:`id`,pageSize:100});return{...r,actions:i}}var ye=/secret|password|private_key|api_key|token/i,be=new Set([`id`,`tenant_id`,`created_at`,`updated_at`,`scope`,`override`,`enforce`,`enabled_clients`]);async function G(e){let t=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(e));return[...new Uint8Array(t)].map(e=>e.toString(16).padStart(2,`0`)).join(``).slice(0,16)}async function K(e,t=``){if(Array.isArray(e)){if(t===`secrets`){let t={};for(let n of e)t[n.name]=n.value===void 0?null:`sha256:${await G(n.value)}`;return t}return Promise.all(e.map(e=>K(e,t)))}if(e&&typeof e==`object`){let t={};for(let n of Object.keys(e).sort()){let r=e[n];r!=null&&(t[n]=typeof r==`string`&&ye.test(n)?`sha256:${await G(r)}`:await K(r,n))}return t}return e}async function xe(e){let t={};for(let[n,r]of Object.entries(e))be.has(n)||(t[n]=r);return await K(t)}var Se={connection:e=>`${e.strategy}:${e.name}`,resourceServer:e=>e.identifier,hook:e=>e.hook_id,action:e=>e.name},Ce=new Set([`connection`,`resourceServer`,`action`,`emailProvider`,`branding`,`promptSettings`]);async function we(e){let t=new Map,n=async(e,n,r)=>{let i=t.get(e)??new Map;i.set(n,await xe(r)),t.set(e,i)};for(let[t,r]of Object.entries(Se)){let i=e[{connection:`connections`,resourceServer:`resourceServers`,hook:`hooks`,action:`actions`}[t]];for(let e of i)await n(t,r(e),e)}for(let t of[`emailProvider`,`branding`,`promptSettings`])e[t]&&await n(t,`singleton`,e[t]);return t}async function Te(e,t){let[n,r]=await Promise.all([we(e),we(t)]),i=[],a=new Set([...n.keys(),...r.keys()]);for(let e of a){let t=n.get(e)??new Map,a=r.get(e)??new Map;for(let n of new Set([...t.keys(),...a.keys()])){let r=t.get(n),o=a.get(n);if(r&&!o)i.push({entity:e,key:n,kind:`missing`,fields:[],expected:!1});else if(!r&&o)i.push({entity:e,key:n,kind:`extra`,fields:[],expected:Ce.has(e)});else if(r&&o){let t=JSON.stringify(r),a=JSON.stringify(o);if(t===a)continue;let s=[...new Set([...Object.keys(r),...Object.keys(o)])].filter(e=>JSON.stringify(r[e])!==JSON.stringify(o[e])).sort();i.push({entity:e,key:n,kind:`changed`,fields:s,expected:!1,legacy_hash:await G(t),new_hash:await G(a)})}}}return i}async function Ee(e){let{adapters:t,tenantId:n,legacyControlPlane:r}=e,i=await le({tenantId:n,getTenant:e=>t.tenants.get(e),legacyControlPlane:r,maxDepth:e.maxDepth}),a=await W(t,n),o=await Promise.all(i.map(e=>W(t,e))),s=r&&r!==n?await W(t,r):void 0,{hidden:c,...l}=_e(o,a),u=new Set(c);return(await Te(de(a,s),l)).filter(e=>!u.has(`${e.entity}:${e.key}`))}var De=3600*1e3,Oe=1e4;function ke(e,t){let n=t.sample??1,r=t.intervalMs??6e4,i=new Map,a=new Set,o=new Map;async function s(n,r){let i=await Ee({adapters:e,tenantId:n,legacyControlPlane:r}),a=Date.now();o.size>Oe&&o.clear();for(let s of i){if(s.expected&&!t.includeExpected)continue;let i=await G([n,s.entity,s.key,s.kind,s.fields.join(`,`)].join(`|`)),c=o.get(i);c!==void 0&&a-c<De||(o.set(i,a),await Ae(e,n,s,r))}}return{schedule(e,t){if(a.has(e)||n<1&&Math.random()>=n)return;let o=Date.now(),c=i.get(e);c!==void 0&&o-c<r||(i.set(e,o),a.add(e),s(e,t).catch(()=>{}).finally(()=>a.delete(e)))}}}async function Ae(e,n,r,i){await e.logs.create(n,{type:t.LogTypes.CONFIG_INHERITANCE_DIFF,date:new Date().toISOString(),isMobile:!1,description:`${r.kind} ${r.entity} ${r.key}`,details:{shadow:`config-inheritance`,legacy_control_plane:i,...r}})}function q(e,n){let r=n.find(t=>t.strategy===e.strategy);if(!r?.options)return e;let i=t.connectionSchema.passthrough().parse({...r,...e});return i.options=t.connectionOptionsSchema.passthrough().parse({...r.options||{},...e.options}),i}function J(e,t){let n=[...t||[],...e||[]];return[...new Set(n)]}function je(e,t){if(!t?.length)return e||[];if(!e?.length)return t;let n=new Map;for(let e of t)n.set(e.value,e);for(let t of e)n.set(t.value,t);return Array.from(n.values())}function Y(e,t){return t?{...e,scopes:je(e.scopes,t.scopes)}:e}function Me(e,t){return t?{...e,callbacks:J(e.callbacks,t.callbacks),web_origins:J(e.web_origins,t.web_origins),allowed_logout_urls:J(e.allowed_logout_urls,t.allowed_logout_urls),allowed_origins:J(e.allowed_origins,t.allowed_origins)}:e}function Ne(e){let{controlPlaneTenantId:t,controlPlaneClientId:n,resolveControlPlane:r}=e;if(r)return async e=>r({tenant_id:e});if(!t)return async()=>void 0;let i={tenantId:t,clientId:n};return async()=>i}function Pe(e,t){return{...e.resourceServers,get:async(n,r)=>{let i=await e.resourceServers.get(n,r);if(!i)return i;let a=await t(n);return!a||n===a.tenantId||!i.is_system?i:Y(i,await e.resourceServers.get(a.tenantId,r))},list:async(n,r)=>{let i=await e.resourceServers.list(n,r),a=await t(n);if(!a||n===a.tenantId)return i;let o=a.tenantId,s=i.resource_servers.filter(e=>!!(e.is_system&&e.id)).map(e=>e.id);if(s.length===0)return i;let c=new Map;await Promise.all(s.map(async t=>{let n=await e.resourceServers.get(o,t);n&&c.set(t,n)}));let l=i.resource_servers.map(e=>e.is_system&&e.id?Y(e,c.get(e.id)??null):e);return{...i,resource_servers:l}}}}function Fe(e,t){let n=Ne({controlPlaneTenantId:t.controlPlaneTenantId,resolveControlPlane:t.resolveControlPlane});return{...e,resourceServers:Pe(e,n)}}function Ie(e,t){let{controlPlaneTenantId:n,controlPlaneClientId:r,resolveControlPlane:i,inheritanceShadow:a}=t,o=Ne({controlPlaneTenantId:n,controlPlaneClientId:r,resolveControlPlane:i}),s=a?ke(e,a===!0?{}:a):void 0,c=s?async e=>{let t=await o(e);return s.schedule(e,t?.tenantId),t}:o;return{...e,multiTenancyConfig:{controlPlaneTenantId:n,controlPlaneClientId:r,resolveControlPlane:i},connections:{...e.connections,get:async(t,n)=>{let r=await e.connections.get(t,n);if(!r)return r;let i=await c(t);return!i||t===i.tenantId?r:q(r,(await e.connections.list(i.tenantId)).connections||[])},list:async(t,n)=>{let r=await e.connections.list(t,n),i=await c(t);if(!i||t===i.tenantId)return r;let a=await e.connections.list(i.tenantId),o=r.connections.map(e=>q(e,a.connections||[]));return{...r,connections:o}}},clientConnections:{...e.clientConnections,listByClient:async(t,n)=>{let r=await e.clientConnections.listByClient(t,n);r.length===0&&(r=(await e.connections.list(t)).connections||[]);let i=await c(t);if(!i||t===i.tenantId)return r;let a=await e.connections.list(i.tenantId);return r.map(e=>q(e,a.connections||[]))}},emailProviders:{...e.emailProviders,get:async t=>{let n=await e.emailProviders.get(t);if(n)return n;let r=await c(t);return!r||t===r.tenantId?null:e.emailProviders.get(r.tenantId)}},resourceServers:Pe(e,c),hooks:Le(e,c)}}function X(e){if(!e||typeof e!=`object`)return!1;let t=e.metadata;return!t||typeof t!=`object`?!1:t.inheritable===!0}function Le(e,t){return{...e.hooks,list:async(n,r)=>{let i=await e.hooks.list(n,r),a=await t(n);if(!a||n===a.tenantId)return i;let o=((await e.hooks.list(a.tenantId,r)).hooks||[]).filter(X);if(o.length===0)return i;let s=new Set((i.hooks||[]).map(e=>e.hook_id)),c=o.filter(e=>!s.has(e.hook_id));return{...i,hooks:[...i.hooks||[],...c],length:typeof i.length==`number`?i.length+c.length:i.length}},get:async(n,r)=>{let i=await e.hooks.get(n,r);if(i)return i;let a=await t(n);if(!a||n===a.tenantId)return i;let o=await e.hooks.get(a.tenantId,r);return o&&X(o)?o:null}}}function Z(e,t){return Ie(e,t)}function Re(e){return async(t,n)=>{let r=t.var.user;return r?.tenant_id===e&&r.org_name&&t.set(`tenant_id`,r.org_name),n()}}function ze(e){return async(n,i)=>{if(!e.accessControl)return i();let{controlPlaneTenantId:o}=e.accessControl,s=n.var.org_name,c=n.var.organization_id,l=s||c,u=n.var.tenant_id,d=n.var.user,f=(d?.aud?Array.isArray(d.aud)?d.aud:[d.aud]:[]).includes(t.MANAGEMENT_API_AUDIENCE);if(!u&&l&&f&&(n.set(`tenant_id`,l),u=l),!u)throw new r.HTTPException(400,{message:`Tenant ID not found in request`});if(!a(c,u,o,s))throw new r.HTTPException(403,{message:`Access denied to tenant ${u}`});return i()}}function Be(e){return async(t,n)=>{if(!e.subdomainRouting)return n();let{baseDomain:i,reservedSubdomains:a=[],resolveSubdomain:o}=e.subdomainRouting,s=t.req.header(`x-forwarded-host`)||t.req.header(`host`)||``,c=null;if(s.endsWith(i)){let e=s.slice(0,-(i.length+1));e&&!e.includes(`.`)&&(c=e)}if(c&&a.includes(c)&&(c=null),!c)return e.accessControl&&t.set(`tenant_id`,e.accessControl.controlPlaneTenantId),n();let l=null;if(o)l=await o(c);else if(e.subdomainRouting.useOrganizations!==!1&&e.accessControl)try{let n=await k(t).organizations.get(e.accessControl.controlPlaneTenantId,c);n&&(l=n.id)}catch{}if(!l)throw new r.HTTPException(404,{message:`Tenant not found for subdomain: ${c}`});return t.set(`tenant_id`,l),n()}}function Ve(e){return async(t,n)=>{if(!e.databaseIsolation)return n();let i=t.var.tenant_id;if(!i)throw new r.HTTPException(400,{message:`Tenant ID not found in request`});try{let n=await e.databaseIsolation.getAdapters(i);t.set(`baseData`,n),t.env={...t.env,data:n}}catch(e){throw console.error(`Failed to resolve database for tenant ${i}:`,e),new r.HTTPException(500,{message:`Failed to resolve tenant database`})}return n()}}function Q(e){let t=Be(e),n=ze(e),r=Ve(e);return async(e,i)=>(await t(e,async()=>{}),await n(e,async()=>{}),await r(e,async()=>{}),i())}function He(e){let{dataAdapter:n,controlPlane:r,controlPlane:{tenantId:i=`control_plane`,clientId:a}={},resolveControlPlane:o,inheritanceShadow:s,sync:c={resourceServers:!0,roles:!0},defaultPermissions:l=[`tenant:admin`],requireOrganizationMatch:u=!1,managementApiExtensions:d=[],entityHooks:f,getChildTenantIds:p,getAdapters:m,...g}=e;if(o&&!r)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.");let v=n,y=n;r&&(v=Z(n,{controlPlaneTenantId:i,controlPlaneClientId:a,resolveControlPlane:o,inheritanceShadow:s}),y={...Fe(n,{controlPlaneTenantId:i,resolveControlPlane:o}),multiTenancyConfig:{controlPlaneTenantId:i,controlPlaneClientId:a,resolveControlPlane:o}});let b=g.tenantOperationExecutor;if(!b&&n.tenantOperations&&n.tenantOperationEvents&&g.tenantUpgrade){let e={tenantOperations:n.tenantOperations,tenantOperationEvents:n.tenantOperationEvents},t=g.tenantUpgrade,r=h({stores:e,definitions:{upgrade:e=>[{name:`upgrade`,async run(){if(!e.tenant_id)throw Error(`upgrade operations require a tenant_id`);await t(e.tenant_id)}}]}});b={engine:r.engine,enqueue:t=>_(e,r,{...t,tenant_id:t.tenant_id})}}let S=c!==!1,ee=S?{resourceServers:c.resourceServers??!0,roles:c.roles??!0}:{resourceServers:!1,roles:!1},{entityHooks:C,tenantHooks:w}=te({controlPlaneTenantId:i,getChildTenantIds:p??(async()=>(await(0,t.fetchAll)(e=>v.tenants.list(e),`tenants`,{cursorField:`id`,pageSize:100})).filter(e=>e.id!==i).map(e=>e.id)),getAdapters:m??(async()=>v),getControlPlaneAdapters:async()=>v,sync:ee}),T={resourceServers:[C.resourceServers,...f?.resourceServers??[]],roles:[C.roles,...f?.roles??[]],connections:f?.connections??[],tenants:f?.tenants??[],rolePermissions:f?.rolePermissions??[]},E=x({accessControl:{controlPlaneTenantId:i,requireOrganizationMatch:u,defaultPermissions:l}}),D=A({accessControl:{controlPlaneTenantId:i,requireOrganizationMatch:u,defaultPermissions:l}},{tenants:{async beforeCreate(e,t){return E.beforeCreate&&(t=await E.beforeCreate(e,t)),w.beforeCreate&&(t=await w.beforeCreate(e,t)),t},async afterCreate(e,t){await E.afterCreate?.(e,t),await w.afterCreate?.(e,t)},async beforeDelete(e,t){await E.beforeDelete?.(e,t),await w.beforeDelete?.(e,t)}}}),{app:O}=(0,t.init)({dataAdapter:v,managementDataAdapter:y,...g,tenantOperationExecutor:b,entityHooks:T,managementApiExtensions:[...d,{path:`/tenants`,router:D}],managementApiMiddleware:[...g.managementApiMiddleware??[],...S?[j()]:[]]});return{app:O,controlPlaneTenantId:i}}function Ue(e){let{pkcs7:t,tenant_id:n,...r}=e;return r}async function We(e,n,r={},i){let a=L(r),o=r.signingKeys??!0,s=r.tenants??!0,c=await V(e,n,a),l=o?(await(0,t.listControlPlaneKeys)(e.keys)).map(Ue):[],u=s?await Ge(e,n,i):[];return{connections:c.connections,resourceServers:c.resourceServers.filter(e=>e.is_system),hooks:c.hooks.filter(z),emailProvider:c.emailProvider,branding:c.branding,promptSettings:c.promptSettings,signingKeys:l,tenants:u}}async function Ge(e,t,n){let r=n&&n!==t?[t,n]:[t],i=[];for(let t of r){let n=await e.tenants.get(t);i.push({id:t,friendly_name:n?.friendly_name||t})}return i}async function Ke(e,n,r){let i=R();if(e.length===0)return i;let a=await(0,t.listControlPlaneKeys)(n.keys),o=new Set(a.map(e=>e.kid));for(let t of e)await B(i,`signing_key ${t.kid}`,r,async()=>{let e=Ue(t);o.has(e.kid)||(await n.keys.create(e),o.add(e.kid),i.upserted+=1)});return i}async function qe(e,t,n){let r=R();for(let i of e)await B(r,`tenant ${i.id}`,n,async()=>{await t.tenants.get(i.id)||(await t.tenants.create({id:i.id,friendly_name:i.friendly_name}),r.upserted+=1)});return r}async function Je(e,n,r,i={}){let a=i.continueOnError??!1,o=L(i.entities),s=i.entities?.signingKeys??!0,c=i.entities?.tenants??!0,l={connections:e.connections,resourceServers:e.resourceServers,hooks:e.hooks,emailProvider:e.emailProvider?t.emailProviderSchema.parse(e.emailProvider):null,branding:e.branding?t.brandingSchema.parse(e.branding):null,promptSettings:e.promptSettings?t.promptSettingSchema.parse(e.promptSettings):null},u=c?await qe(e.tenants??[],n,a):R(),d=ve(r);await H(l,n,r,o,a,d);let f=s?await Ke(e.signingKeys,n,a):R();return{...d,signingKeys:f,tenants:u}}function Ye(e){return{syncDefaults:t=>U(e,t),syncDefaultsToTenants:async t=>{let n=[];for(let r of t)n.push(await U(e,r));return n}}}function Xe(e){let t=$(e);return{name:`multi-tenancy`,middleware:Q(e),hooks:t,routes:[{path:`/management`,handler:A(e,t)}],onRegister:async()=>{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`)}}}function $(e){let t=e.accessControl?i(e.accessControl):{},n=e.databaseIsolation?o(e.databaseIsolation):{},r=x(e);return{...t,...n,tenants:r}}function Ze(t){let n=new e.Hono,r=$(t);return n.route(`/tenants`,A(t,r)),n}function Qe(e){return{hooks:$(e),middleware:Q(e),app:Ze(e),config:e,wrapAdapters:(t,n)=>Z(t,{controlPlaneTenantId:e.accessControl?.controlPlaneTenantId,controlPlaneClientId:n?.controlPlaneClientId})}}exports.applyControlPlaneDefaultsPayload=Je,exports.buildControlPlaneDefaultsPayload=We,exports.buildEngineInstanceId=l,exports.compareShadow=Ee,exports.computeLegacyConfig=de,exports.createAccessControlHooks=i,exports.createAccessControlMiddleware=ze,exports.createControlPlaneTenantMiddleware=Re,exports.createDatabaseHooks=o,exports.createDatabaseMiddleware=Ve,exports.createDirectRolloutAdapter=Ye,exports.createInlineExecutor=h,exports.createMultiTenancy=Ze,exports.createMultiTenancyHooks=$,exports.createMultiTenancyMiddleware=Q,exports.createMultiTenancyPlugin=Xe,exports.createOperationRecorder=f,exports.createProtectSyncedMiddleware=j,exports.createProvisioningHooks=x,exports.createRuntimeFallbackAdapter=Ie,exports.createShadowReporter=ke,exports.createSubdomainMiddleware=Be,exports.createSyncHooks=te,exports.createTenantsOpenAPIRouter=A,exports.diffConfig=Te,exports.effectiveOverride=P,exports.effectiveScope=N,exports.enqueueTenantOperation=_,exports.errorToMessage=d,exports.initMultiTenant=He,exports.inlineStepRunner=m,exports.isTerminalStatus=p,exports.mergeClientWithFallback=Me,exports.mergeConfig=_e,exports.projectControlPlaneDefaults=U,exports.readConfigRows=W,exports.resolveTenantChain=le,exports.runRecordedTenantOperation=y,exports.setupMultiTenancy=Qe,exports.validateTenantAccess=a,exports.withRuntimeFallback=Z,exports.withSystemResourceServerInheritance=Fe;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("hono"),t=require("authhero"),n=require("hono/http-exception"),r=require("@hono/zod-openapi");function i(e){let{controlPlaneTenantId:t,requireOrganizationMatch:n=!0}=e;return{async onTenantAccessValidation(e,r){if(r===t)return!0;if(n){let t=e.var.org_name,n=e.var.organization_id,i=t||n;return i?i.toLowerCase()===r.toLowerCase():!1}return!0}}}function a(e,t,n,r){if(t===n)return!0;let i=r||e;return i?i.toLowerCase()===t.toLowerCase():!1}function o(e){return{async resolveDataAdapters(t){try{return await e.getAdapters(t)}catch(e){console.error(`Failed to resolve data adapters for tenant ${t}:`,e);return}}}}var s=64;function c(e){return e.replace(/[^a-zA-Z0-9_-]/g,`-`)}function l(e){let t=c(e.id),n=Math.max(0,s-(5+t.length)),r=c(e.kind).slice(0,n),i=3+r.length+2+t.length,a=Math.max(0,s-i);return`op-${r}-${c(e.tenant_id??`fleet`).slice(0,a)}-${t}`.slice(0,s)}var u=2048;function d(e){let t;if(e instanceof Error)t=e.message;else try{t=String(e??`unknown error`)}catch{t=Object.prototype.toString.call(e)}return t.slice(0,u)}function f(e){let{tenantOperations:t,tenantOperationEvents:n}=e;return{async markRunning(e,n){await t.update(e,{status:`running`,...n===void 0?{}:{current_step:n}})},async setCurrentStep(e,n){await t.update(e,{current_step:n})},async appendEvent(e,t){await n.create({operation_id:e,step:t.step,outcome:t.outcome,detail:t.detail,attempt:t.attempt??1})},async setResult(e,n){await t.update(e,{result:n})},async markSucceeded(e){await t.update(e,{status:`succeeded`,error:null,finished_at:new Date().toISOString()})},async markFailed(e,n){await t.update(e,{status:`failed`,error:d(n),finished_at:new Date().toISOString()})}}}function p(e){return e===`succeeded`||e===`failed`||e===`cancelled`}var m={async do(e,t,n){let r=typeof t==`function`?t:n;if(!r)throw Error(`StepRunner.do called without a function`);return r()}};function h(e){let t=f(e.stores);return{engine:`inline`,async start(n){let r=e.definitions[n.kind];if(!r){let e=Error(`No inline operation definition for kind "${n.kind}"`);throw await t.markFailed(n.id,e),e}let i=r(n);await t.markRunning(n.id,i[0]?.name);for(let e of i){await t.setCurrentStep(n.id,e.name),await t.appendEvent(n.id,{step:e.name,outcome:`started`});try{let r=await e.run({operation:n,step:m});await t.appendEvent(n.id,{step:e.name,outcome:`succeeded`,detail:r??void 0})}catch(r){throw await t.appendEvent(n.id,{step:e.name,outcome:`failed`,detail:{message:d(r)}}),await t.markFailed(n.id,r),r}}await t.markSucceeded(n.id)}}}async function g(e,t,n){let r=await e.tenantOperations.create({tenant_id:t.tenant_id,rollout_id:t.rollout_id,kind:t.kind,engine:n,initiated_by:t.initiated_by,target_worker_version:t.target_worker_version,target_database_version:t.target_database_version,input:t.input}),i=l(r);try{await e.tenantOperations.update(r.id,{engine_instance_id:i})}catch(t){try{await f(e).markFailed(r.id,t)}catch{}throw t}return{...r,engine_instance_id:i}}async function _(e,t,n,r={}){let i=f(e),a=await g(e,n,t.engine);try{await t.start(a)}catch(t){let n=null;try{let r=await e.tenantOperations.get(a.id);r&&!p(r.status)&&await i.markFailed(a.id,t),n=await e.tenantOperations.get(a.id)}catch(e){console.warn(`Failed to record tenant operation failure:`,e)}if(r.returnFailed&&n)return n;throw t}try{return await e.tenantOperations.get(a.id)??a}catch(e){return console.warn(`Failed to re-fetch tenant operation after start:`,e),a}}async function v(e){let{tenantId:t,parentTenantId:r,getTenant:i,getChildren:a}=e,o=e.maxDepth??2;if(!r)return;if(t&&r===t)throw new n.HTTPException(400,{message:`A tenant cannot be its own parent`});let s=new Set(t?[t]:[]),c=0,l=r;for(;l;){if(s.has(l))throw new n.HTTPException(400,{message:`Setting parent_tenant_id to '${r}' would create a cycle`});s.add(l);let e=await i(l);if(!e)throw new n.HTTPException(400,{message:`Parent tenant '${l}' not found`});if(c+=1,c>o)throw new n.HTTPException(400,{message:`Tenant tree is limited to ${o} levels above a tenant`});l=e.parent_tenant_id}if(t&&a){let e=new Set([t]),i=0,s=[t];for(;s.length>0;){let t=[];for(let n of s)for(let r of await a(n))e.has(r)||(e.add(r),t.push(r));if(t.length>0&&(i+=1,c+i>o))throw new n.HTTPException(400,{message:`Moving tenant under '${r}' would make its descendant '${t[0]}' exceed the tenant tree limit of ${o} levels`});s=t}}}async function y(e){let{tenantId:t,getTenant:r,legacyControlPlane:i}=e,a=e.maxDepth??2,o=await r(t);if(!o?.parent_tenant_id)return i&&i!==t?[i]:[];let s=[],c=new Set([t]),l=o.parent_tenant_id;for(;l;){if(c.has(l))throw new n.HTTPException(400,{message:`Tenant chain for '${t}' contains a cycle at '${l}'`});if(c.add(l),s.length>=a)throw new n.HTTPException(400,{message:`Tenant chain for '${t}' is deeper than ${a}`});let e=await r(l);if(!e)break;s.push(l),l=e.parent_tenant_id}return s}function b(e){let t={};for(let n of e??[])n.value!==void 0&&(t[n.name]=n.value);return t}function x(e,t){if(!e.inherit)return e;let n=t.find(t=>t.name===e.name&&t.is_system);if(!n)return e;let r={...b(n.secrets),...b(e.secrets)};return{...e,code:n.code,secrets:Object.entries(r).map(([e,t])=>({name:e,value:t}))}}function ee(e,t){if(!t)return e;let n=new Set(e.hooks.map(e=>e.hook_id)),r=t.hooks.filter(e=>be(e)&&!n.has(e.hook_id));return{connections:e.connections.map(e=>P(e,t.connections)),resourceServers:e.resourceServers.map(e=>e.is_system?me(e,t.resourceServers.find(t=>t.id===e.id)??null):e),hooks:[...e.hooks,...r],hookCode:e.hookCode,actions:e.actions.map(e=>x(e,t.actions)),emailProvider:e.emailProvider??t.emailProvider,branding:e.branding,promptSettings:e.promptSettings}}function S(e={}){return{connections:e.connections??!0,resourceServers:e.resourceServers??!0,hooks:e.hooks??!0,emailProvider:e.emailProvider??!0,branding:e.branding??!0,promptSettings:e.promptSettings??!0}}function C(){return{upserted:0,errors:[]}}function w(e){return{tenantId:e,connections:C(),resourceServers:C(),hooks:C(),emailProvider:C(),branding:C(),promptSettings:C()}}function T(e){let t=e.metadata;return!!(t&&t.inheritable===!0)}async function E(e,t,n,r){try{await r()}catch(r){let i=`${t}: ${r instanceof Error?r.message:String(r)}`;if(!n)throw Error(i,{cause:r});e.errors.push(i)}}async function D(e,n,r){return{connections:r.connections?await(0,t.fetchAll)(t=>e.connections.list(n,t),`connections`,{cursorField:`id`,pageSize:100}):[],resourceServers:r.resourceServers?await(0,t.fetchAll)(t=>e.resourceServers.list(n,t),`resource_servers`,{cursorField:`id`,pageSize:100}):[],hooks:r.hooks?await(0,t.fetchAll)(t=>e.hooks.list(n,t),`hooks`,{cursorField:`hook_id`,pageSize:100}):[],emailProvider:r.emailProvider?await e.emailProviders.get(n)??null:null,branding:r.branding?await e.branding.get(n)??null:null,promptSettings:r.promptSettings?await e.promptSettings.get(n)??null:null}}async function O(e,n,r,i,a,o){if(i.connections)for(let i of e.connections){let e=i.id;e&&await E(o.connections,`connection ${e}`,a,async()=>{let a=t.connectionInsertSchema.parse(i);await n.connections.get(r,e)?await n.connections.update(r,e,a):await n.connections.create(r,a),o.connections.upserted+=1})}if(i.resourceServers)for(let i of e.resourceServers)!i.is_system||!i.id||await E(o.resourceServers,`resource_server ${i.id}`,a,async()=>{let e=t.resourceServerInsertSchema.parse(i);await n.resourceServers.get(r,i.id)?await n.resourceServers.update(r,i.id,e):await n.resourceServers.create(r,e),o.resourceServers.upserted+=1});if(i.hooks)for(let i of e.hooks)!T(i)||!i.hook_id||await E(o.hooks,`hook ${i.hook_id}`,a,async()=>{let e=t.hookInsertSchema.parse(i);await n.hooks.get(r,i.hook_id)?await n.hooks.update(r,i.hook_id,e):await n.hooks.create(r,e),o.hooks.upserted+=1});i.emailProvider&&e.emailProvider&&await E(o.emailProvider,`email_provider`,a,async()=>{let t=e.emailProvider;await n.emailProviders.get(r)?await n.emailProviders.update(r,t):await n.emailProviders.create(r,t),o.emailProvider.upserted+=1}),i.branding&&e.branding&&await E(o.branding,`branding`,a,async()=>{await n.branding.set(r,e.branding),o.branding.upserted+=1}),i.promptSettings&&e.promptSettings&&await E(o.promptSettings,`prompt_settings`,a,async()=>{await n.promptSettings.set(r,e.promptSettings),o.promptSettings.upserted+=1})}async function k(e,t){let{controlPlaneTenantId:n,getControlPlaneAdapters:r,getAdapters:i,entities:a,continueOnError:o=!1}=e,s=S(a),c=await D(await r(),n,s),l=await i(t),u=w(t);return await O(c,l,n,s,o,u),u}async function A(e,n){let r=await D(e,n,{connections:!0,resourceServers:!0,hooks:!0,emailProvider:!0,branding:!0,promptSettings:!0}),i=await(0,t.fetchAll)(t=>e.actions.list(n,t),`actions`,{cursorField:`id`,pageSize:100}),a=new Set(i.map(e=>e.id)),o=new Set;for(let e of r.hooks){let t=e.code_id;t&&!a.has(t)&&o.add(t)}let s=[];for(let t of o){let r=await e.hookCode.get(n,t);r&&s.push(r)}return{...r,actions:i,hookCode:s}}var te=/secret|password|private_key|api_key|token/i,j=new Set([`id`,`tenant_id`,`created_at`,`updated_at`,`scope`,`override`,`enforce`,`enabled_clients`]);async function M(e){let t=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(e));return[...new Uint8Array(t)].map(e=>e.toString(16).padStart(2,`0`)).join(``).slice(0,16)}async function N(e,t=``){if(Array.isArray(e)){if(t===`secrets`){let t={};for(let n of e)t[n.name]=n.value===void 0?null:`sha256:${await M(n.value)}`;return t}return Promise.all(e.map(e=>N(e,t)))}if(e&&typeof e==`object`){let t={};for(let n of Object.keys(e).sort()){let r=e[n];r!=null&&(t[n]=typeof r==`string`&&te.test(n)?`sha256:${await M(r)}`:await N(r,n))}return t}return e}async function ne(e){let t={};for(let[n,r]of Object.entries(e))j.has(n)||(t[n]=r);return await N(t)}var re={connection:e=>`${e.strategy}:${e.name}`,resourceServer:e=>e.identifier,hook:e=>e.hook_id,action:e=>e.name},ie=new Set([`connection`,`resourceServer`,`action`,`emailProvider`,`branding`,`promptSettings`]);async function ae(e){let t=new Map,n=async(e,n,r)=>{let i=t.get(e)??new Map;i.set(n,await ne(r)),t.set(e,i)};for(let[t,r]of Object.entries(re)){let i=e[{connection:`connections`,resourceServer:`resourceServers`,hook:`hooks`,action:`actions`}[t]];for(let e of i)await n(t,r(e),e)}for(let t of[`emailProvider`,`branding`,`promptSettings`])e[t]&&await n(t,`singleton`,e[t]);return t}async function oe(e,t){let[n,r]=await Promise.all([ae(e),ae(t)]),i=[],a=new Set([...n.keys(),...r.keys()]);for(let e of a){let t=n.get(e)??new Map,a=r.get(e)??new Map;for(let n of new Set([...t.keys(),...a.keys()])){let r=t.get(n),o=a.get(n);if(r&&!o)i.push({entity:e,key:n,kind:`missing`,fields:[],expected:!1});else if(!r&&o)i.push({entity:e,key:n,kind:`extra`,fields:[],expected:ie.has(e)});else if(r&&o){let t=JSON.stringify(r),a=JSON.stringify(o);if(t===a)continue;let s=[...new Set([...Object.keys(r),...Object.keys(o)])].filter(e=>JSON.stringify(r[e])!==JSON.stringify(o[e])).sort();i.push({entity:e,key:n,kind:`changed`,fields:s,expected:!1,legacy_hash:await M(t),new_hash:await M(a)})}}}return i}async function se(e){let{adapters:t,tenantId:n,legacyControlPlane:r}=e,i=await y({tenantId:n,getTenant:e=>t.tenants.get(e),legacyControlPlane:r,maxDepth:e.maxDepth}),a=await A(t,n),o=await Promise.all(i.map(e=>A(t,e))),s=r&&r!==n?await A(t,r):void 0,{hidden:c,...l}=Ae(o,a),u=new Set(c);return(await oe(ee(a,s),l)).filter(e=>!u.has(`${e.entity}:${e.key}`))}var ce=3600*1e3,le=1e4;function ue(e,t){let n=t.sample??1,r=t.intervalMs??6e4,i=new Map,a=new Set,o=new Map;async function s(n,r){let i=await se({adapters:e,tenantId:n,legacyControlPlane:r}),a=Date.now();o.size>le&&o.clear();for(let s of i){if(s.expected&&!t.includeExpected)continue;let i=await M([n,s.entity,s.key,s.kind,s.fields.join(`,`)].join(`|`)),c=o.get(i);c!==void 0&&a-c<ce||(o.set(i,a),await de(e,n,s,r))}}return{schedule(e,t){if(a.has(e)||n<1&&Math.random()>=n)return;let o=Date.now(),c=i.get(e);c!==void 0&&o-c<r||(i.set(e,o),a.add(e),s(e,t).catch(()=>{}).finally(()=>a.delete(e)))}}}async function de(e,n,r,i){await e.logs.create(n,{type:t.LogTypes.CONFIG_INHERITANCE_DIFF,date:new Date().toISOString(),isMobile:!1,description:`${r.kind} ${r.entity} ${r.key}`,details:{shadow:`config-inheritance`,legacy_control_plane:i,...r}})}function fe(e){let{base:t,getTenant:n,controlPlaneTenantId:r}=e,i=e.ttlMs??3e4,a=e.maxEntries??1e3,o=new Map;async function s(e){if(e===r)return!1;let t=o.get(e),s=Date.now();if(t&&t.expires>s)return t.synced;try{let t=(await n(e))?.config_sync===`synced`;return o.size>=a&&o.clear(),o.set(e,{synced:t,expires:s+i}),t}catch{return!1}}return{isSynced:s,invalidate(e){e?o.delete(e):o.clear()},async resolve({tenant_id:e}){let n=await t(e);return!n||n.tenantId===e?n:await s(e)?void 0:n}}}function P(e,n){let r=n.find(t=>t.strategy===e.strategy);if(!r?.options)return e;let i=t.connectionSchema.passthrough().parse({...r,...e});return i.options=t.connectionOptionsSchema.passthrough().parse({...r.options||{},...e.options}),i}function F(e,t){let n=[...t||[],...e||[]];return[...new Set(n)]}function pe(e,t){if(!t?.length)return e||[];if(!e?.length)return t;let n=new Map;for(let e of t)n.set(e.value,e);for(let t of e)n.set(t.value,t);return Array.from(n.values())}function me(e,t){return t?{...e,scopes:pe(e.scopes,t.scopes)}:e}function he(e,t){return t?{...e,callbacks:F(e.callbacks,t.callbacks),web_origins:F(e.web_origins,t.web_origins),allowed_logout_urls:F(e.allowed_logout_urls,t.allowed_logout_urls),allowed_origins:F(e.allowed_origins,t.allowed_origins)}:e}function ge(e){let{controlPlaneTenantId:t,controlPlaneClientId:n,resolveControlPlane:r}=e;if(r)return async e=>r({tenant_id:e});if(!t)return async()=>void 0;let i={tenantId:t,clientId:n};return async()=>i}function _e(e,t){return{...e.resourceServers,get:async(n,r)=>{let i=await e.resourceServers.get(n,r);if(!i)return i;let a=await t(n);return!a||n===a.tenantId||!i.is_system?i:me(i,await e.resourceServers.get(a.tenantId,r))},list:async(n,r)=>{let i=await e.resourceServers.list(n,r),a=await t(n);if(!a||n===a.tenantId)return i;let o=a.tenantId,s=i.resource_servers.filter(e=>!!(e.is_system&&e.id)).map(e=>e.id);if(s.length===0)return i;let c=new Map;await Promise.all(s.map(async t=>{let n=await e.resourceServers.get(o,t);n&&c.set(t,n)}));let l=i.resource_servers.map(e=>e.is_system&&e.id?me(e,c.get(e.id)??null):e);return{...i,resource_servers:l}}}}function ve(e,t){let n=ge({controlPlaneTenantId:t.controlPlaneTenantId,resolveControlPlane:t.resolveControlPlane});return{...e,resourceServers:_e(e,n)}}function ye(e,t){let{controlPlaneTenantId:n,controlPlaneClientId:r,resolveControlPlane:i,inheritanceShadow:a}=t,o=t.configSync??fe({base:ge({controlPlaneTenantId:n,controlPlaneClientId:r,resolveControlPlane:i}),getTenant:async t=>await e.tenants.get(t)??null,controlPlaneTenantId:n}),s=e=>o.resolve({tenant_id:e}),c=a?ue(e,a===!0?{}:a):void 0,l=c?async e=>{let t=await s(e);return await o.isSynced(e)||c.schedule(e,t?.tenantId),t}:s;return{...e,multiTenancyConfig:{controlPlaneTenantId:n,controlPlaneClientId:r,resolveControlPlane:o.resolve},connections:{...e.connections,get:async(t,n)=>{let r=await e.connections.get(t,n);if(!r)return r;let i=await l(t);return!i||t===i.tenantId?r:P(r,(await e.connections.list(i.tenantId)).connections||[])},list:async(t,n)=>{let r=await e.connections.list(t,n),i=await l(t);if(!i||t===i.tenantId)return r;let a=await e.connections.list(i.tenantId),o=r.connections.map(e=>P(e,a.connections||[]));return{...r,connections:o}}},clientConnections:{...e.clientConnections,listByClient:async(t,n)=>{let r=await e.clientConnections.listByClient(t,n);r.length===0&&(r=(await e.connections.list(t)).connections||[]);let i=await l(t);if(!i||t===i.tenantId)return r;let a=await e.connections.list(i.tenantId);return r.map(e=>P(e,a.connections||[]))}},emailProviders:{...e.emailProviders,get:async t=>{let n=await e.emailProviders.get(t);if(n)return n;let r=await l(t);return!r||t===r.tenantId?null:e.emailProviders.get(r.tenantId)}},resourceServers:_e(e,l),hooks:xe(e,l)}}function be(e){if(!e||typeof e!=`object`)return!1;let t=e.metadata;return!t||typeof t!=`object`?!1:t.inheritable===!0}function xe(e,t){return{...e.hooks,list:async(n,r)=>{let i=await e.hooks.list(n,r),a=await t(n);if(!a||n===a.tenantId)return i;let o=((await e.hooks.list(a.tenantId,r)).hooks||[]).filter(be);if(o.length===0)return i;let s=new Set((i.hooks||[]).map(e=>e.hook_id)),c=[];for(let e of o)s.has(e.hook_id)||e.hook_id&&s.has(await z(`hook`,n,e.hook_id))||c.push(e);return{...i,hooks:[...i.hooks||[],...c],length:typeof i.length==`number`?i.length+c.length:i.length}},get:async(n,r)=>{let i=await e.hooks.get(n,r);if(i)return i;let a=await t(n);if(!a||n===a.tenantId)return i;let o=await e.hooks.get(a.tenantId,r);return o&&be(o)?o:null}}}function Se(e,t){return ye(e,t)}var Ce=()=>({connections:[],resourceServers:[],hooks:[],hookCode:[],actions:[],emailProvider:null,branding:null,promptSettings:null});function I(e,t){if(t.scope)return t.scope;switch(e){case`connection`:case`emailProvider`:return`shared`;case`resourceServer`:case`action`:return t.is_system?`shared`:`local`;case`hook`:return be(t)?`shared`:`local`;default:return`local`}}function L(e){return e.override??`fields`}var we=/secret|password|private_key|api_key|token/i;function Te(e,t){let n={...e??{}};for(let[e,r]of Object.entries(t??{}))we.test(e)&&(n[e]=r);return n}function Ee(e,t){switch(L(e)){case`none`:return{...e,id:t.id};case`secrets`:return{...e,id:t.id,options:Te(e.options,t.options)};default:return{...e,...t,options:{...e.options??{},...t.options??{}}}}}function De(e,t){switch(L(e)){case`none`:return{...e,id:t.id};case`secrets`:return{...e,id:t.id,signing_secret:t.signing_secret??e.signing_secret};default:return{...t,scopes:pe(t.scopes,e.scopes)}}}function Oe(e){return new Map((e??[]).map(e=>[e.name,e]))}function ke(e,t){let n=L(e);if(n===`none`)return{...e,id:t.id};let r=Oe(e.secrets);if(n===`secrets`||n===`fields`)for(let[e,n]of Oe(t.secrets))r.set(e,n);return{...n===`fields`&&!t.inherit?t:e,id:t.id,secrets:[...r.values()]}}function Ae(e,t){let n=new Set,r=[...e].reverse().concat(t),i=(e,t,r,i)=>r?t:t.filter(t=>{let r=I(e,t);return r===`local`?!1:(r===`platform`&&n.add(`${e}:${i(t)}`),!0)}),a=Ce(),o=e=>`${e.strategy}:${e.name}`,s=e=>e.identifier,c=e=>e.hook_id??``,l=e=>e.name,u=new Map,d=[],f=new Map,p=new Map,m=new Map;r.forEach((e,t)=>{let h=t===r.length-1;for(let t of i(`connection`,e.connections,h,o)){let e=u.get(t.strategy);h?d.push(e?Ee(e,t):t):u.set(t.strategy,e?Ee(e,t):t)}for(let t of i(`resourceServer`,e.resourceServers,h,s)){let e=f.get(s(t));f.set(s(t),e?De(e,t):t)}for(let t of i(`hook`,e.hooks,h,c))p.set(c(t),t);for(let t of i(`action`,e.actions,h,l)){let e=m.get(l(t));m.set(l(t),e?ke(e,t):t)}for(let t of[`emailProvider`,`branding`,`promptSettings`]){let r=e[t];r&&(h||I(t,r)!==`local`)&&(!h&&I(t,r)===`platform`&&n.add(`${t}:singleton`),a[t]=r)}});let h=new Set(r[r.length-1].connections.map(e=>e.strategy));a.connections=[...d,...[...u.values()].filter(e=>!h.has(e.strategy))],a.resourceServers=[...f.values()],a.hooks=[...p.values()];let g=new Set(a.hooks.map(e=>e.code_id).filter(e=>!!e)),_=new Map;for(let e of[...r].reverse())for(let t of e.hookCode)g.has(t.id)&&!_.has(t.id)&&_.set(t.id,t);return a.hookCode=[..._.values()],a.actions=[...m.values()],{...a,hidden:[...n]}}function R(e){return Array.isArray(e)?`[${e.map(R).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)}:${R(t)}`).join(`,`)}}`:JSON.stringify(e)??`null`}async function je(e){let t=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(e));return[...new Uint8Array(t)].map(e=>e.toString(16).padStart(2,`0`)).join(``)}var Me={connection:`con_`,resourceServer:`api_`,hook:`h_`,hookCode:`hc_`,action:`act_`};async function z(e,t,n){let r=await je(`${t}|${e}|${n}`);return`${Me[e]}sy${r.slice(0,15)}`}function B(e,t){let n=t;switch(e){case`connection`:return`${n.strategy}:${n.name}`;case`resourceServer`:return n.identifier;case`action`:return n.name;case`hookCode`:return n.id;case`hook`:return n.hook_id}}async function Ne(e,t,n={}){let r=await y({tenantId:t,getTenant:t=>e.tenants.get(t),legacyControlPlane:n.legacyControlPlane,maxDepth:n.maxDepth}),i=Ae(await Promise.all(r.map(t=>A(e,t))),Ce()),a={version:1,chain:r,connections:i.connections,resourceServers:i.resourceServers,hookCode:i.hookCode,actions:i.actions,hooks:i.hooks,emailProvider:i.emailProvider,branding:i.branding,promptSettings:i.promptSettings,hidden:i.hidden,deletes:n.deletes??[]};return{...a,hash:await je(R(a))}}function Pe(e,t){if(typeof e==`string`)e.startsWith(`enc:v1:`)&&t.add(e);else if(Array.isArray(e))for(let n of e)Pe(n,t);else if(e&&typeof e==`object`)for(let n of Object.values(e))Pe(n,t)}function Fe(e){let t=e.slice(7),n=t.indexOf(`:`);return n===-1?`default`:t.slice(0,n)}async function Ie(e,n){let r=new Set;Pe(e,r);let i=new Set;for(let e of r)await(0,t.canDecrypt)(e,n)||i.add(Fe(e));return[...i].sort()}var V=()=>({added:0,changed:0,unchanged:0,deleted:0,errors:[]}),Le=e=>R(e);async function Re(e,n,r,i={}){let{dryRun:a=!1,continueOnError:o=!0}=i,s={status:a?`dry-run`:`applied`,hash:e.hash,entities:{connection:V(),resourceServer:V(),hookCode:V(),action:V(),hook:V(),emailProvider:V(),branding:V(),promptSettings:V()},changes:[]},c=await n.tenants.get(r),l=!!i.deletes&&e.deletes.length>0;if(!a&&!i.force&&!l&&c?.config_sync_hash===e.hash)return{...s,status:`up-to-date`};if(i.keyRing){let t=await Ie(e,i.keyRing);if(t.length>0)throw Error(`Cannot sync config to '${r}': its key ring cannot decrypt key id(s) ${t.map(e=>`"${e}"`).join(`, `)} carried by the payload. Nothing was written.`)}let u=async(e,t,n)=>{let r=s.entities[e];try{let i=await n();r[i]+=1,i!==`unchanged`&&s.changes.push(`${e}:${t}`)}catch(n){let i=`${e} ${t}: ${n instanceof Error?n.message:String(n)}`;if(!o)throw Error(i,{cause:n});r.errors.push(i)}},d=async e=>e.existing?Le(e.view(e.existing))===Le(e.view(e.desired))?`unchanged`:(a||await e.update(),`changed`):(a||await e.create(),`added`),f=(e,t)=>z(e,r,t),p=new Map;for(let t of e.hookCode)p.set(t.id,await f(`hookCode`,B(`hookCode`,t)));for(let t of e.actions)p.set(t.id,await f(`action`,B(`action`,t)));for(let i of e.connections){let e=B(`connection`,i),a=await f(`connection`,e);await u(`connection`,e,async()=>{let{enabled_clients:e,...o}=i,s=t.connectionInsertSchema.parse({...o,id:a}),c=await n.connections.get(r,a);return d({existing:c?t.connectionInsertSchema.parse(c):null,desired:s,create:()=>n.connections.create(r,s),update:()=>n.connections.update(r,a,s),view:e=>e})})}for(let i of e.resourceServers){let e=B(`resourceServer`,i),a=await f(`resourceServer`,e);await u(`resourceServer`,e,async()=>{let e=t.resourceServerInsertSchema.parse({...i,id:a}),o=await n.resourceServers.get(r,a);return d({existing:o?t.resourceServerInsertSchema.parse(o):null,desired:e,create:()=>n.resourceServers.create(r,e),update:()=>n.resourceServers.update(r,a,e),view:e=>e})})}for(let i of e.hookCode){let e=B(`hookCode`,i),a=p.get(i.id);await u(`hookCode`,e,async()=>{let e=t.hookCodeInsertSchema.parse(i),o=await n.hookCode.get(r,a);return d({existing:o?t.hookCodeInsertSchema.parse(o):null,desired:e,create:()=>n.hookCode.create(r,e,{importMetadata:{id:a}}),update:()=>n.hookCode.update(r,a,e),view:e=>e})})}for(let i of e.actions){let e=B(`action`,i),a=p.get(i.id);await u(`action`,e,async()=>{let e=t.actionInsertSchema.parse(i),o=await n.actions.get(r,a);return d({existing:o?t.actionInsertSchema.parse(o):null,desired:e,create:()=>n.actions.create(r,e,{importMetadata:{id:a}}),update:()=>n.actions.update(r,a,e),view:e=>e})})}for(let i of e.hooks){let e=B(`hook`,i),a=await f(`hook`,e);await u(`hook`,e,async()=>{let e=i.code_id,o=t.hookInsertSchema.parse({...i,hook_id:a,...e?{code_id:p.get(e)??e}:{}}),s=await n.hooks.get(r,a);return d({existing:s?t.hookInsertSchema.parse(s):null,desired:o,create:()=>n.hooks.create(r,o),update:()=>n.hooks.update(r,a,o),view:e=>e})})}e.emailProvider&&await u(`emailProvider`,`singleton`,async()=>{let i=t.emailProviderSchema.parse(e.emailProvider);return await n.emailProviders.get(r)?`unchanged`:(a||await n.emailProviders.create(r,i),`added`)}),e.branding&&await u(`branding`,`singleton`,async()=>{let i=t.brandingSchema.parse(e.branding);return await n.branding.get(r)?`unchanged`:(a||await n.branding.set(r,i),`added`)});for(let t of e.deletes){let e=await f(t.entity,t.key),o=`${t.entity}:${t.key}`;try{if(!await ze(n,r,t.entity,e))continue;s.changes.push(`delete ${o}`),i.deletes&&!a&&(await Be(n,r,t.entity,e),s.entities[t.entity].deleted+=1)}catch(e){s.entities[t.entity].errors.push(`delete ${o}: ${e instanceof Error?e.message:e}`)}}let m=Object.values(s.entities).some(e=>e.errors.length>0);return!a&&!m&&c&&await n.tenants.update(r,{config_sync_hash:e.hash,config_synced_at:new Date().toISOString()}),s}async function ze(e,t,n,r){switch(n){case`connection`:return!!await e.connections.get(t,r);case`resourceServer`:return!!await e.resourceServers.get(t,r);case`hookCode`:return!!await e.hookCode.get(t,r);case`action`:return!!await e.actions.get(t,r);case`hook`:return!!await e.hooks.get(t,r)}}async function Be(e,t,n,r){switch(n){case`connection`:await e.connections.remove(t,r);return;case`resourceServer`:await e.resourceServers.remove(t,r);return;case`hookCode`:await e.hookCode.remove(t,r);return;case`action`:await e.actions.remove(t,r);return;case`hook`:await e.hooks.remove(t,r);return}}function Ve(e){let t=e.input??{};return{dryRun:t.dry_run===!0,force:t.force===!0}}function He(e){return Object.values(e.entities).flatMap(e=>e.errors)}function Ue(e,t){return{dry_run:t.dryRun,status:e.status,hash:e.hash,changes:e.changes,entities:Object.fromEntries(Object.entries(e.entities).map(([e,t])=>[e,{added:t.added,changed:t.changed,unchanged:t.unchanged,deleted:t.deleted,errors:t.errors.length}]))}}async function We(e){let{operation:t,syncConfig:n,recorder:r}=e;if(!t.tenant_id)throw Error(`sync-defaults operations require a tenant_id`);let i=Ve(t),a=await n(t.tenant_id,i),o=Ue(a,i);await r.setResult(t.id,o);let s=He(a);if(s.length>0){let e=s.slice(0,3).join(`; `);throw Error(`sync-defaults reported ${s.length} error(s): ${e}${s.length>3?`; ...`:``}`)}return o}function Ge(e,t){return async(n,r)=>{let i=await e.tenants.get(n);if(!i)throw Error(`Tenant "${n}" not found`);if(i.deployment_type===`wfp`)throw Error(`Tenant "${n}" has its own database: configure a dispatch sync (syncDefaults) for it`);return Re(await Ne(e,n,{legacyControlPlane:(t.resolveControlPlane?await t.resolveControlPlane({tenant_id:n}):{tenantId:t.controlPlaneTenantId})?.tenantId,maxDepth:t.maxDepth}),e,n,{dryRun:r.dryRun,force:r.force})}}function Ke(e){if(e.tenantOperations&&e.tenantOperationEvents)return{tenantOperations:e.tenantOperations,tenantOperationEvents:e.tenantOperationEvents}}async function qe(e,t,n){let r=Ke(e);if(!r){await n(void 0);return}let i=f(r),a=async e=>{try{await e()}catch(e){console.warn(`Failed to record tenant operation progress:`,e)}},o;if(await a(async()=>{let e=await g(r,t,`inline`);o=e.id,await i.markRunning(e.id)}),!o){await n(void 0);return}let s=o,c=!1,l=async(e,t,n)=>{c=!0,await a(async()=>{t===`started`&&await i.setCurrentStep(s,e),await i.appendEvent(s,{step:e,outcome:t,detail:n})})};try{await n(l)}catch(e){throw await a(async()=>{c||await i.appendEvent(s,{step:t.kind,outcome:`failed`,detail:{message:d(e)}}),await i.markFailed(s,e)}),e}await a(async()=>{c||await i.appendEvent(s,{step:t.kind,outcome:`succeeded`}),await i.markSucceeded(s)})}function Je(e){return`urn:authhero:tenant:${e.toLowerCase()}`}function Ye(e){return{async beforeCreate(e,t){return!t.audience&&t.id?{...t,audience:Je(t.id)}:t},async afterCreate(n,r){let{accessControl:i,databaseIsolation:a}=e;if(i&&n.ctx&&await Xe(n,r,i),a?.onProvision){let e=a.onProvision;a.recordProvisionOperations===!1?await e(r.id):await qe(n.adapters,{kind:`provision`,tenant_id:r.id,initiated_by:n.ctx?.var.user?.sub},t=>e(r.id,t))}else try{await(0,t.provisionDefaultClients)(n.adapters,r.id,{managementApiIdentifier:t.MANAGEMENT_API_AUDIENCE,managementApiScopes:t.MANAGEMENT_API_SCOPES})}catch(e){throw console.warn(`Failed to provision default clients for tenant ${r.id}:`,e),e}},async beforeDelete(t,n){let{accessControl:r,databaseIsolation:i}=e;if(r)try{let e=(await t.adapters.organizations.list(r.controlPlaneTenantId)).organizations.find(e=>e.name===n);e&&await t.adapters.organizations.remove(r.controlPlaneTenantId,e.id)}catch(e){console.warn(`Failed to remove organization for tenant ${n}:`,e)}if(i?.onDeprovision)try{await i.onDeprovision(n)}catch(e){console.warn(`Failed to deprovision database for tenant ${n}:`,e)}}}}async function Xe(e,t,n){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,{name:t.id,display_name:t.friendly_name||t.id}),d;if(o&&(d=await Qe(e,r,s,c)),l&&e.ctx){let t=e.ctx.var.user;if(t?.sub&&!await Ze(e,r,t.sub))try{await e.adapters.userOrganizations.create(r,{user_id:t.sub,organization_id:u.id}),d&&await e.adapters.userRoles.create(r,t.sub,d,u.id)}catch(e){console.warn(`Failed to add creator ${t.sub} to organization ${u.id}:`,e)}}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}`)}async function Ze(e,n,r){let i=await e.adapters.userRoles.list(n,r,void 0,``);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.MANAGEMENT_API_AUDIENCE))return!0;return!1}async function Qe(e,n,r,i){let a=(await e.adapters.roles.list(n,{})).roles.find(e=>e.name===r);if(a)return a.id;let o=await e.adapters.roles.create(n,{name:r,description:i}),s=t.MANAGEMENT_API_AUDIENCE,c=t.MANAGEMENT_API_SCOPES.map(e=>({role_id:o.id,resource_server_identifier:s,permission_name:e.value}));return await e.adapters.rolePermissions.assign(n,o.id,c),o.id}function $e(e,n,r=()=>!0){let{controlPlaneTenantId:i,getChildTenantIds:a,getAdapters:o}=e,s=new Map;async function c(e,r,i){return(await n(e).list(r,{q:`name:${(0,t.escapeLuceneValue)(i)}`,per_page:1}))[0]??null}async function l(e){let t=await a(),r=n(await o(i));await Promise.all(t.map(async t=>{try{let i=await o(t),a=n(i),s={...r.transform(e),is_system:!0},l=await c(i,t,e.name),u=l?a.getId(l):void 0;if(l&&u){let e=a.preserveOnUpdate?a.preserveOnUpdate(l,s):s;await a.update(t,u,e)}else await a.create(t,s)}catch(n){console.error(`Failed to sync ${r.listKey} "${e.name}" to tenant "${t}":`,n)}}))}async function u(e){let t=await a();await Promise.all(t.map(async t=>{try{let r=await o(t),i=n(r),a=await c(r,t,e),s=a?i.getId(a):void 0;a&&s&&await i.remove(t,s)}catch(n){console.error(`Failed to delete entity "${e}" from tenant "${t}":`,n)}}))}return{afterCreate:async(e,t)=>{e.tenantId===i&&r(t)&&await l(t)},afterUpdate:async(e,t,n)=>{e.tenantId===i&&r(n)&&await l(n)},beforeDelete:async(e,t)=>{if(e.tenantId!==i)return;let a=await n(e.adapters).get(e.tenantId,t);a&&r(a)&&s.set(t,a)},afterDelete:async(e,t)=>{if(e.tenantId!==i)return;let n=s.get(t);n&&(s.delete(t),await u(n.name))}}}function et(e,n,r=()=>!0){let{controlPlaneTenantId:i,getControlPlaneAdapters:a,getAdapters:o}=e;return{async afterCreate(e,s){if(s.id!==i)try{let e=await a(),c=await o(s.id),l=n(e),u=n(c),d=await(0,t.fetchAll)(e=>l.listPaginated(i,e),l.listKey,{cursorField:`id`,pageSize:100});await Promise.all(d.filter(e=>r(e)).map(async e=>{try{let t=l.transform(e);await u.create(s.id,{...t,is_system:!0})}catch(e){console.error(`Failed to sync entity to new tenant "${s.id}":`,e)}}))}catch(e){console.error(`Failed to sync entities to new tenant "${s.id}":`,e)}}}}var tt=e=>({list:async(t,n)=>(await e.resourceServers.list(t,n)).resource_servers,listPaginated:(t,n)=>e.resourceServers.list(t,n),get:(t,n)=>e.resourceServers.get(t,n),create:(t,n)=>e.resourceServers.create(t,n),update:(t,n,r)=>e.resourceServers.update(t,n,r),remove:(t,n)=>e.resourceServers.remove(t,n),listKey:`resource_servers`,getId:e=>e.id,transform:e=>({id:e.id,name:e.name,identifier:e.identifier,scopes:e.scopes,signing_alg:e.signing_alg,token_lifetime:e.token_lifetime,token_lifetime_for_web:e.token_lifetime_for_web})}),nt=e=>({list:async(t,n)=>(await e.roles.list(t,n)).roles,listPaginated:(t,n)=>e.roles.list(t,n),get:(t,n)=>e.roles.get(t,n),create:(t,n)=>e.roles.create(t,n),update:(t,n,r)=>e.roles.update(t,n,r),remove:(t,n)=>e.roles.remove(t,n),listKey:`roles`,getId:e=>e.id,transform:e=>({id:e.id,name:e.name,description:e.description})});function rt(e){return e.metadata?.sync!==!1}function it(e){let{sync:n={},filters:r={}}=e,i=n.resourceServers??!0,a=n.roles??!0,o=e=>rt(e)?r.resourceServers?r.resourceServers(e):!0:!1,s=e=>rt(e)?r.roles?r.roles(e):!0:!1,c=i?$e(e,tt,o):void 0,l=a?$e(e,nt,s):void 0,u=i?et(e,tt,o):void 0,d=a?et(e,nt,s):void 0,f=a?{async afterCreate(n,i){if(i.id!==e.controlPlaneTenantId){await d?.afterCreate?.(n,i);try{let n=await e.getControlPlaneAdapters(),a=await e.getAdapters(i.id),o=await(0,t.fetchAll)(t=>n.roles.list(e.controlPlaneTenantId,t),`roles`,{cursorField:`id`,pageSize:100}),s=new Map;for(let e of o.filter(e=>r.roles?.(e)??!0)){let t=await p(a,i.id,e.name);t&&s.set(e.name,t.id)}for(let t of o.filter(e=>r.roles?.(e)??!0)){let r=s.get(t.name);if(r)try{let o=await n.rolePermissions.list(e.controlPlaneTenantId,t.id,{});o.length>0&&await a.rolePermissions.assign(i.id,r,o.map(e=>({role_id:r,resource_server_identifier:e.resource_server_identifier,permission_name:e.permission_name})))}catch(e){console.error(`Failed to sync permissions for role "${t.name}" to tenant "${i.id}":`,e)}}}catch(e){console.error(`Failed to sync role permissions to tenant "${i.id}":`,e)}}}}:void 0;async function p(e,n,r){return(await e.roles.list(n,{q:`name:${(0,t.escapeLuceneValue)(r)}`,per_page:1})).roles[0]??null}return{entityHooks:{resourceServers:c,roles:l},tenantHooks:{async afterCreate(e,t){let n=[u?.afterCreate,f?.afterCreate??d?.afterCreate],r=[];for(let i of n)if(i)try{await i(e,t)}catch(e){r.push(e instanceof Error?e:Error(String(e)))}if(r.length===1)throw r[0];if(r.length>1)throw AggregateError(r,r.map(e=>e.message).join(`; `))}}}}function H(e){return e.var.data??e.env.data}var at=r.z.object({sub:r.z.string(),tenant_id:r.z.string().optional(),org_id:r.z.string().optional(),scope:r.z.string().optional(),permissions:r.z.array(r.z.string()).optional()}).passthrough();function ot(e){let t=at.safeParse(e);return t.success?t.data:void 0}function st(e,t,n){return t?!e||n?!1:e.tenant_id===t:!0}function ct(e){let t=e.permissions??[],n=e.scope?e.scope.split(` `).filter(Boolean):[],r=new Set([...t,...n]);return r.has(`delete:tenants`)||r.has(`admin:organizations`)}function U(e,i){let a=new r.OpenAPIHono,o=t=>{let n=ot(t.var.user);return st(n,e.accessControl?.controlPlaneTenantId??H(t).multiTenancyConfig?.controlPlaneTenantId,!!(n?.org_id??t.var.organization_id??t.var.org_name))};if(a.openapi((0,r.createRoute)({tags:[`tenants`],method:`get`,path:`/`,request:{query:t.auth0QuerySchema},security:[{Bearer:[]}],responses:{200:{content:{"application/json":{schema:r.z.object({tenants:r.z.array(t.tenantSchema),start:r.z.number().optional(),limit:r.z.number().optional(),length:r.z.number().optional(),total:r.z.number().optional()})}},description:`List of tenants`}}}),async r=>{let{page:i,per_page:a,include_totals:o,q:s}=r.req.valid(`query`),c=r.var.user,l=c?.permissions||[];if(!(c?.org_id??r.var.organization_id)&&l.includes(`admin:organizations`)){let e=await H(r).tenants.list({page:i,per_page:a,include_totals:o,q:s});return o?r.json({tenants:e.tenants,start:e.totals?.start??0,limit:e.totals?.limit??a,length:e.tenants.length,total:e.totals?.length}):r.json({tenants:e.tenants})}let u=e.accessControl?.controlPlaneTenantId??H(r).multiTenancyConfig?.controlPlaneTenantId;if(u&&!c?.sub)throw new n.HTTPException(403,{message:`Access denied: token has no subject`});if(u&&c?.sub){let e=(await(0,t.fetchAll)(e=>H(r).userOrganizations.listUserOrganizations(u,c.sub,e),`organizations`)).map(e=>e.name);if(e.length===0)return o?r.json({tenants:[],start:0,limit:a??50,length:0,total:0}):r.json({tenants:[]});let n=e.length,l=i??0,d=a??50,f=l*d,p=e.slice(f,f+d);if(p.length===0)return o?r.json({tenants:[],start:f,limit:d,length:0,total:n}):r.json({tenants:[]});let m=p.map(e=>`id:${e}`).join(` OR `),h=s?`(${m}) AND (${s})`:m,g=await H(r).tenants.list({q:h,per_page:d,include_totals:!1});return o?r.json({tenants:g.tenants,start:f,limit:d,length:g.tenants.length,total:n}):r.json({tenants:g.tenants})}let d=await H(r).tenants.list({page:i,per_page:a,include_totals:o,q:s});return o?r.json({tenants:d.tenants,start:d.totals?.start??0,limit:d.totals?.limit??a,length:d.tenants.length,total:d.totals?.length}):r.json({tenants:d.tenants})}),a.openapi((0,r.createRoute)({tags:[`tenants`],method:`post`,path:`/`,request:{body:{content:{"application/json":{schema:t.tenantInsertSchema}}}},security:[{Bearer:[]}],responses:{201:{content:{"application/json":{schema:t.tenantSchema}},description:`Tenant created`},400:{description:`Validation error`},409:{description:`Tenant with this ID already exists`}}}),async t=>{if(!t.var.user?.sub)throw new n.HTTPException(401,{message:`Authentication required to create tenants`});let{config_sync_hash:r,config_synced_at:a,config_sync:s,...c}=t.req.valid(`json`),l=c;if(l.parent_tenant_id&&!o(t))throw new n.HTTPException(403,{message:`Only the control plane can set a tenant's parent`});s!==void 0&&o(t)&&(l={...l,config_sync:s});let u={adapters:H(t),ctx:t};i.tenants?.beforeCreate&&(l=await i.tenants.beforeCreate(u,l)),await v({tenantId:l.id,parentTenantId:l.parent_tenant_id,getTenant:e=>H(t).tenants.get(e)});let d=await H(t).tenants.create(l);return i.tenants?.afterCreate&&await i.tenants.afterCreate(u,d),e.onConfigSyncChange?.(d.id),t.json(d,201)}),a.openapi((0,r.createRoute)({tags:[`tenants`],method:`delete`,path:`/{id}`,request:{params:r.z.object({id:r.z.string()})},security:[{Bearer:[`delete:tenants`]}],responses:{204:{description:`Tenant deleted`},403:{description:`Access denied or cannot delete the control plane`},404:{description:`Tenant not found`}}}),async r=>{let{id:a}=r.req.valid(`param`),o=e.accessControl?.controlPlaneTenantId??H(r).multiTenancyConfig?.controlPlaneTenantId;if(o){let e=ot(r.var.user);if(!e?.sub)throw new n.HTTPException(401,{message:`Authentication required`});if(a===o)throw new n.HTTPException(403,{message:`Cannot delete the control plane`});let i=r.var.org_name,s=a.toLowerCase(),c=!!i&&i.toLowerCase()===s;if(!c){let t=!!(e.org_id??r.var.organization_id??i),n=!e.tenant_id||e.tenant_id===o;!t&&n&&ct(e)&&(c=!0)}if(c||=(await(0,t.fetchAll)(t=>H(r).userOrganizations.listUserOrganizations(o,e.sub,t),`organizations`)).some(e=>e.name?.toLowerCase()===s),!c)throw new n.HTTPException(403,{message:`Access denied to this tenant`})}if(!await H(r).tenants.get(a))throw new n.HTTPException(404,{message:`Tenant not found`});let s={adapters:H(r),ctx:r};return i.tenants?.beforeDelete&&await i.tenants.beforeDelete(s,a),await H(r).tenants.remove(a),i.tenants?.afterDelete&&await i.tenants.afterDelete(s,a),r.body(null,204)}),e.configSyncStatus){let t=e.configSyncStatus;a.openapi((0,r.createRoute)({tags:[`tenants`],method:`get`,path:`/{id}/config-sync`,request:{params:r.z.object({id:r.z.string()})},security:[{Bearer:[`read:tenants`]}],responses:{200:{content:{"application/json":{schema:r.z.object({tenant_id:r.z.string(),parent_tenant_id:r.z.string().nullable(),config_sync:r.z.enum([`inherit-on-read`,`synced`]),config_sync_hash:r.z.string().nullable(),config_synced_at:r.z.string().nullable(),expected_hash:r.z.string().nullable(),drifted:r.z.boolean(),chain:r.z.array(r.z.string()),inherited:r.z.record(r.z.string(),r.z.string())})}},description:`Config sync status of the tenant`},403:{description:`Not allowed to read this tenant`},404:{description:`Tenant not found`}}}),async e=>{let{id:r}=e.req.valid(`param`);if(r!==e.var.tenant_id&&!o(e))throw new n.HTTPException(403,{message:`Config sync status is only readable for your own tenant`});let i=await t(r);if(!i)throw new n.HTTPException(404,{message:`Tenant not found`});return e.json(i)})}return a.openapi((0,r.createRoute)({tags:[`tenants`,`settings`],method:`get`,path:`/settings`,request:{headers:r.z.object({"tenant-id":r.z.string().optional()})},security:[{Bearer:[`read:tenants`]}],responses:{200:{content:{"application/json":{schema:t.tenantSchema}},description:`Current tenant settings`}}}),async e=>{let t=await H(e).tenants.get(e.var.tenant_id);if(!t)throw new n.HTTPException(404,{message:`Tenant not found`});return e.json(t)}),a.openapi((0,r.createRoute)({tags:[`tenants`,`settings`],method:`patch`,path:`/settings`,request:{headers:r.z.object({"tenant-id":r.z.string().optional()}),body:{content:{"application/json":{schema:r.z.object(t.tenantInsertSchema.shape).partial()}}}},security:[{Bearer:[`update:tenants`]}],responses:{200:{content:{"application/json":{schema:t.tenantSchema}},description:`Updated tenant settings`}}}),async r=>{let{id:i,config_sync_hash:a,config_synced_at:s,...c}=r.req.valid(`json`),l=await H(r).tenants.get(r.var.tenant_id);if(!l)throw new n.HTTPException(404,{message:`Tenant not found`});if(`config_sync`in c&&(c.config_sync??`inherit-on-read`)!==(l.config_sync??`inherit-on-read`)&&!o(r))throw new n.HTTPException(403,{message:`Only the control plane can change a tenant's config_sync mode`});if(`default_client_id`in c){let e=c.default_client_id;if(typeof e==`string`&&e.length>0){let i=await H(r).clients.get(r.var.tenant_id,e);if(!i)throw new n.HTTPException(400,{message:`Client with id '${e}' not found`});if(!(0,t.isInteractiveClient)(i))throw new n.HTTPException(400,{message:`Client '${e}' is not an interactive client and cannot be used as the default client`})}}if(`parent_tenant_id`in c){if((c.parent_tenant_id??null)!==(l.parent_tenant_id??null)&&!o(r))throw new n.HTTPException(403,{message:`Only the control plane can change a tenant's parent`});await v({tenantId:r.var.tenant_id,parentTenantId:c.parent_tenant_id,getTenant:e=>H(r).tenants.get(e),getChildren:async e=>(await(0,t.fetchAll)(e=>H(r).tenants.list(e),`tenants`)).filter(t=>t.parent_tenant_id===e).map(e=>e.id)})}let u=(0,t.deepMergePatch)(l,c);await H(r).tenants.update(r.var.tenant_id,u),`config_sync`in c&&e.onConfigSyncChange?.(r.var.tenant_id);let d=await H(r).tenants.get(r.var.tenant_id);if(!d)throw new n.HTTPException(500,{message:`Failed to retrieve updated tenant`});return r.json(d)}),a}function lt(e){for(let{pattern:t,type:n}of[{pattern:/\/api\/v2\/resource-servers\/([^/]+)$/,type:`resource_server`},{pattern:/\/api\/v2\/roles\/([^/]+)$/,type:`role`},{pattern:/\/api\/v2\/connections\/([^/]+)$/,type:`connection`}]){let r=e.match(t);if(r&&r[1])return{type:n,id:r[1]}}return null}async function ut(e,t,n){try{switch(n.type){case`resource_server`:return(await e.resourceServers.get(t,n.id))?.is_system===!0;case`role`:return(await e.roles.get(t,n.id))?.is_system===!0;case`connection`:return(await e.connections.get(t,n.id))?.is_system===!0;default:return!1}}catch{return!1}}function dt(e){return{resource_server:`resource server`,role:`role`,connection:`connection`}[e]}function ft(e){for(let{pattern:t,type:n}of[{pattern:/\/api\/v2\/connections\/([^/]+)$/,type:`connection`},{pattern:/\/api\/v2\/resource-servers\/([^/]+)$/,type:`resource_server`},{pattern:/\/api\/v2\/actions\/actions\/([^/]+)$/,type:`action`},{pattern:/\/api\/v2\/hooks\/([^/]+)$/,type:`hook`},{pattern:/\/api\/v2\/hook-code\/([^/]+)$/,type:`hook_code`}]){let r=e.match(t);if(r?.[1])return{type:n,id:r[1]}}return null}async function pt(e,t,n){try{switch(n.type){case`connection`:return await e.connections.get(t,n.id);case`resource_server`:return await e.resourceServers.get(t,n.id);case`action`:return await e.actions.get(t,n.id);case`hook`:return await e.hooks.get(t,n.id);case`hook_code`:return await e.hookCode.get(t,n.id)}}catch{return null}}var mt={connection:[`options`],resource_server:[`signing_secret`],action:[`secrets`],hook:[],hook_code:[]},ht=new Set([`client_secret`,`app_secret`,`twilio_token`]);function gt(e,t){let n=e=>{let{client_secret:t,...n}=e??{};return n};return W(n(e),n(t))}var W=(e,t)=>JSON.stringify(e)===JSON.stringify(t);function G(e,t){return new n.HTTPException(403,{message:`This ${e.type.replace(`_`,` `)} is synced from a parent tenant and ${t}. Make changes in the parent tenant instead.`})}async function _t(e,t,n){let r=await pt(H(e),t,n);if(!r)return;if(n.type===`hook_code`)throw G(n,`cannot be modified`);if(e.req.method===`DELETE`){if(r.enforce===!0)throw G(n,`cannot be deleted`);return}let i=r.override??`fields`;if(i===`none`)throw G(n,`cannot be edited`);let a={};try{let t=await e.req.raw.clone().json();t&&typeof t==`object`&&(a=t)}catch{}for(let e of[`scope`,`override`,`enforce`])if(e in a&&!W(a[e]??null,r[e]??null))throw G(n,`has a locked ${e}`);if(r.enforce===!0&&a.enabled===!1)throw G(n,`cannot be disabled`);if(i===`secrets`){let e=mt[n.type];for(let[t,i]of Object.entries(a))if(![`scope`,`override`,`enforce`].includes(t)&&!W(i,r[t])){if(!e.includes(t))throw G(n,`only allows its secrets to be changed (not ${t})`);if(t===`options`&&i&&typeof i==`object`){let e=r.options??{};for(let[t,r]of Object.entries(i))if(!W(r,e[t])&&!t.endsWith(`_hint`)&&!(ht.has(t)||t===`configuration`&&gt(r,e[t])))throw G(n,`only allows its secrets to be changed (not options.${t})`)}}}}function vt(){return async(e,r)=>{if(![`PATCH`,`PUT`,`DELETE`].includes(e.req.method))return r();let i=lt(e.req.path),a=ft(e.req.path);if(!i&&!a)return r();let o=e.var.tenant_id||e.req.header(`x-tenant-id`)||e.req.header(`tenant-id`);if(!o)return r();if(i&&await ut(H(e),o,i))throw new n.HTTPException(403,{message:`This ${dt(i.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`});return a&&(0,t.isSyncedRowId)(a.id)&&await _t(e,o,a),r()}}function yt(e){return async(t,n)=>{let r=t.var.user;return r?.tenant_id===e&&r.org_name&&t.set(`tenant_id`,r.org_name),n()}}function bt(e){return async(r,i)=>{if(!e.accessControl)return i();let{controlPlaneTenantId:o}=e.accessControl,s=r.var.org_name,c=r.var.organization_id,l=s||c,u=r.var.tenant_id,d=r.var.user,f=(d?.aud?Array.isArray(d.aud)?d.aud:[d.aud]:[]).includes(t.MANAGEMENT_API_AUDIENCE);if(!u&&l&&f&&(r.set(`tenant_id`,l),u=l),!u)throw new n.HTTPException(400,{message:`Tenant ID not found in request`});if(!a(c,u,o,s))throw new n.HTTPException(403,{message:`Access denied to tenant ${u}`});return i()}}function xt(e){return async(t,r)=>{if(!e.subdomainRouting)return r();let{baseDomain:i,reservedSubdomains:a=[],resolveSubdomain:o}=e.subdomainRouting,s=t.req.header(`x-forwarded-host`)||t.req.header(`host`)||``,c=null;if(s.endsWith(i)){let e=s.slice(0,-(i.length+1));e&&!e.includes(`.`)&&(c=e)}if(c&&a.includes(c)&&(c=null),!c)return e.accessControl&&t.set(`tenant_id`,e.accessControl.controlPlaneTenantId),r();let l=null;if(o)l=await o(c);else if(e.subdomainRouting.useOrganizations!==!1&&e.accessControl)try{let n=await H(t).organizations.get(e.accessControl.controlPlaneTenantId,c);n&&(l=n.id)}catch{}if(!l)throw new n.HTTPException(404,{message:`Tenant not found for subdomain: ${c}`});return t.set(`tenant_id`,l),r()}}function St(e){return async(t,r)=>{if(!e.databaseIsolation)return r();let i=t.var.tenant_id;if(!i)throw new n.HTTPException(400,{message:`Tenant ID not found in request`});try{let n=await e.databaseIsolation.getAdapters(i);t.set(`baseData`,n),t.env={...t.env,data:n}}catch(e){throw console.error(`Failed to resolve database for tenant ${i}:`,e),new n.HTTPException(500,{message:`Failed to resolve tenant database`})}return r()}}function Ct(e){let t=xt(e),n=bt(e),r=St(e);return async(e,i)=>(await t(e,async()=>{}),await n(e,async()=>{}),await r(e,async()=>{}),i())}var wt=[10,50,100],K={canary:1,waves:wt,failure_threshold:.1,max_concurrent:25,debounce_ms:6e4};function q(e){let t=e.config??{};return{...K,trigger:`manual`,root_tenant_id:``,...t,waves:Array.isArray(t.waves)&&t.waves.length>0?t.waves:[...wt]}}function Tt(e,t,n){let r=Array(e).fill(0);if(e===0)return r;let i=Math.min(Math.max(t,0),e),a=[],o=i;for(let t of n){let n=Math.min(e,Math.max(o,Math.ceil(e*t/100)));n>o&&(a.push(n),o=n)}o<e&&a.push(e);let s=+(i>0),c=i;for(let e of a){for(;c<e;c++)r[c]=s;s++}return r}async function Et(e,n,r){let i=r.maxDepth??8,a=await(0,t.fetchAll)(t=>e.tenants.list(t),`tenants`,{cursorField:`id`,pageSize:100}),o=new Map(a.map(e=>[e.id,e])),s=async e=>e.parent_tenant_id??(e.id===n?void 0:await r.resolveLegacyParent(e.id)),c=[];for(let e of a){if(e.id===n||e.config_sync!==`synced`)continue;let t=0,r=e,a=!1;for(;r&&t<=i;){let e=await s(r);if(!e)break;if(t++,e===n){a=!0;break}r=o.get(e)}a&&c.push({tenantId:e.id,depth:t,appliedHash:e.config_sync_hash??null})}return c.sort((e,t)=>e.depth-t.depth||(e.tenantId<t.tenantId?-1:1))}async function J(e,t){return e.resolveControlPlane?(await e.resolveControlPlane({tenant_id:t}))?.tenantId:e.controlPlaneTenantId}function Y(e){let t=new Map;return async n=>{let r=await J(e,n),i=(await y({tenantId:n,getTenant:t=>e.adapters.tenants.get(t),legacyControlPlane:r,maxDepth:e.maxDepth})).join(`>`),a=t.get(i);return a||(a=Ne(e.adapters,n,{legacyControlPlane:r,maxDepth:e.maxDepth}).then(e=>e.hash),t.set(i,a)),a}}var Dt=[`pending`,`canary`,`rolling`,`paused`];function X(e){let{tenantOperations:t,tenantOperationEvents:n}=e.adapters;if(!t||!n)throw Error(`Fleet rollouts need the tenant operations adapters`);return{tenantOperations:t,tenantOperationEvents:n}}function Z(e){if(!e.adapters.rollouts)throw Error(`Fleet rollouts need the rollouts adapter`);return e.adapters.rollouts}async function Ot(e,t,n={}){let r=Z(e),i=X(e),a=q(t),o=await Et(e.adapters,a.root_tenant_id,{resolveLegacyParent:t=>J(e,t),maxDepth:e.maxDepth});if(n.tenantIds){let e=new Set(n.tenantIds);o=o.filter(t=>e.has(t.tenantId))}let s=Y(e),c=[];for(let e of o)(a.force||e.appliedHash!==await s(e.tenantId))&&c.push(e);let l=o.length-c.length;if(c.length===0)return a.trigger===`write`?await r.remove(t.id):await r.update(t.id,{status:`done`,finished_at:new Date(e.now?.()??Date.now()).toISOString(),config:{...a,planned:!0,tenant_count:0}}),{planned:0,upToDate:l};let u=new Set((await Q(e,t.id)).map(e=>e.tenant_id)),d=Tt(c.length,a.canary,a.waves);for(let[n,r]of c.entries())u.has(r.tenantId)||await g(i,{kind:`sync-defaults`,tenant_id:r.tenantId,rollout_id:t.id,initiated_by:`rollout:${t.id}`,input:{wave:d[n],...a.dry_run?{dry_run:!0}:{},...a.force?{force:!0}:{}}},e.executor.engine);return await r.update(t.id,{status:`canary`,config:{...a,planned:!0,tenant_count:c.length}}),{planned:c.length,upToDate:l}}async function Q(e,t){let{tenantOperations:n}=X(e),r=[];for(let e=0;;e++){let{operations:i}=await n.list({rollout_id:t,page:e,per_page:200});if(r.push(...i),i.length<200)break}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)}var $=e=>{let t=e.input?.wave;return typeof t==`number`?t:0},kt=e=>e.status===`failed`||e.status===`cancelled`;function At(e,t,n){let r=t.filter(e=>$(e)===n),i=r.filter(kt).length,a=n===0&&e.canary>0,o=a?0:e.failure_threshold;return r.length===0||i===0||i/r.length<=o?null:`${a?`canary`:`wave ${n}`} failed for ${i} of ${r.length} tenant(s)`}async function jt(e,t){let n=Z(e),r=e.now?.()??Date.now(),i=typeof t==`string`?await n.get(t):t;if(!i||i.kind!==`config-sync`)return{rolloutId:String(i?.id??t),outcome:`skipped`,started:0};let a=i.id;if(!Dt.includes(i.status)||i.status===`paused`)return{rolloutId:a,outcome:`skipped`,started:0};let o=q(i);if(!o.planned){if(r-Date.parse(i.updated_at)<o.debounce_ms)return{rolloutId:a,outcome:`waiting`,started:0};let{planned:t}=await Ot(e,i);if(t===0)return{rolloutId:a,outcome:`planned-empty`,started:0};i=await n.get(a)??i,o=q(i)}let s=await Q(e,a),c=s.filter(e=>!p(e.status));if(c.length===0){let e=Math.max(0,...s.map($)),t=s.length>0&&e>(o.accepted_through??-1)?At(o,s,e):null;return await n.update(a,{status:t?`failed`:`done`,...t?{paused_reason:t}:{},finished_at:new Date(r).toISOString()}),{rolloutId:a,outcome:`done`,started:0}}let l=Math.min(...c.map($)),u=l-1;if(u>=0&&u>(o.accepted_through??-1)){let e=At(o,s,u);if(e)return await n.update(a,{status:`paused`,paused_reason:e}),{rolloutId:a,outcome:`paused`,started:0,wave:l}}let d=l===0?`canary`:`rolling`;i.status!==d&&await n.update(a,{status:d});let m=c.filter(e=>$(e)===l),h=m.filter(e=>e.status===`running`).length,g=Math.max(0,o.max_concurrent-h),{tenantOperations:_,tenantOperationEvents:v}=X(e),y=f({tenantOperations:_,tenantOperationEvents:v}),b=0;for(let t of m.filter(e=>e.status===`pending`).slice(0,g)){try{await y.markRunning(t.id),await e.executor.start(t)}catch(e){try{let n=await _.get(t.id);n&&!p(n.status)&&await y.markFailed(t.id,e)}catch{}}b++}return{rolloutId:a,outcome:b>0?`started`:`running`,started:b,wave:l}}async function Mt(e,t={}){let{rollouts:n}=await Z(e).list({kind:`config-sync`,status:[`pending`,`canary`,`rolling`],per_page:t.limit??20}),r=[];for(let i of n)try{r.push(await jt(e,i))}catch(e){t.logger?.warn(`Advancing rollout ${i.id} failed:`,e)}return r}async function Nt(e,t,n=`paused by an operator`){let r=Z(e),i=await r.get(t);return!i||i.kind!==`config-sync`?null:i.status===`done`||i.status===`failed`?i:(await r.update(t,{status:`paused`,paused_reason:n}),r.get(t))}async function Pt(e,t){let n=Z(e),r=await n.get(t);if(!r||r.kind!==`config-sync`)return null;if(r.status!==`paused`)return r;let i=q(r),a=(await Q(e,t)).filter(e=>!p(e.status)),o=a.length>0?Math.min(...a.map($)):0;return await n.update(t,{status:o===0?`canary`:`rolling`,paused_reason:null,config:{...i,accepted_through:Math.max(i.accepted_through??-1,o-1)}}),n.get(t)}async function Ft(e,n){let r=await e.adapters.tenants.get(n);if(!r)return null;let i=r.config_sync===`synced`,a=await y({tenantId:n,getTenant:t=>e.adapters.tenants.get(t),legacyControlPlane:await J(e,n),maxDepth:e.maxDepth}),o=i?await Y(e)(n):null,s=r.config_sync_hash??null,c={};for(let r of[...a].reverse()){let i=await A(e.adapters,r),a=(e,t)=>I(e,t)===`shared`,o=async(e,i,o)=>{for(let s of i){let i=s.id??s.hook_id;i&&(0,t.isSyncedRowId)(i)||a(o,s)&&(c[await z(e,n,B(e,s))]=r)}};await o(`connection`,i.connections,`connection`),await o(`resourceServer`,i.resourceServers,`resourceServer`),await o(`action`,i.actions,`action`),await o(`hook`,i.hooks,`hook`),i.emailProvider&&a(`emailProvider`,i.emailProvider)&&(c.emailProvider=r),i.branding&&a(`branding`,i.branding)&&(c.branding=r),i.promptSettings&&a(`promptSettings`,i.promptSettings)&&(c.promptSettings=r)}return{tenant_id:n,parent_tenant_id:r.parent_tenant_id??null,config_sync:i?`synced`:`inherit-on-read`,config_sync_hash:s,config_synced_at:r.config_synced_at??null,expected_hash:o,drifted:i&&o!==s,chain:a,inherited:c}}async function It(e,n={}){let r=Z(e),i=n.rootTenantId??e.controlPlaneTenantId,a=n.limit??500,o=await Et(e.adapters,i,{resolveLegacyParent:t=>J(e,t),maxDepth:e.maxDepth}),s=Y(e),c=[];for(let e of o){if(c.length>=a)break;try{let t=await s(e.tenantId);e.appliedHash!==t&&c.push({tenantId:e.tenantId,expected:t,applied:e.appliedHash})}catch(t){n.logger?.warn(`Could not compute the expected hash of ${e.tenantId}:`,t)}}let l={checked:o.length,drifted:c.length,alreadyCovered:0,recentlyFailed:0};if(c.length===0)return l;let u=new Set,{rollouts:d}=await r.list({kind:`config-sync`,status:[...Dt],per_page:100});for(let t of d)for(let n of await Q(e,t.id))n.tenant_id&&!p(n.status)&&u.add(n.tenant_id);for(let r of c)try{await e.adapters.logs.create(r.tenantId,{type:t.LogTypes.CONFIG_DRIFT,date:new Date(e.now?.()??Date.now()).toISOString(),isMobile:!1,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`,details:{reason:r.applied?`hash-mismatch`:`never-synced`,applied_hash:r.applied,expected_hash:r.expected,covered_by_open_rollout:u.has(r.tenantId),trigger:`reconcile`}})}catch(e){n.logger?.warn(`Could not record drift for ${r.tenantId}:`,e)}let f=c.filter(e=>!u.has(e.tenantId));l.alreadyCovered=c.length-f.length;let{tenantOperations:m}=X(e),h=e.now?.()??Date.now(),g=n.retryAfterMs??36e5,_=[];for(let e of f){try{let{operations:t}=await m.list({tenant_id:e.tenantId,kind:`sync-defaults`,per_page:5}),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];if(n?.status===`failed`&&h-Date.parse(n.updated_at)<g){l.recentlyFailed++;continue}}catch(t){n.logger?.warn(`Could not read the latest sync of ${e.tenantId}:`,t)}_.push(e)}if(_.length===0)return l;let v=await r.create({kind:`config-sync`,initiated_by:`reconcile`,config:{...K,trigger:`reconcile`,root_tenant_id:i,planned:!1}});return await Ot(e,v,{tenantIds:_.map(e=>e.tenantId)}),l.rolloutId=v.id,l}function Lt(e,t){return e===`hookCode`?!0:!t||typeof t!=`object`?!1:I(e,t)!==`local`}async function Rt(e,t,n){let r=Z(e),{rollouts:i}=await r.list({kind:`config-sync`,status:`pending`,per_page:100}),a=i.find(e=>{let n=q(e);return n.trigger===`write`&&n.planned!==!0&&n.origin_tenant_id===t});return a?(await r.update(a.id,{}),await r.get(a.id)??a):r.create({kind:`config-sync`,initiated_by:n??`write:${t}`,config:{...K,trigger:`write`,root_tenant_id:t,origin_tenant_id:t,planned:!1}})}async function zt(e,t){if(t===e.controlPlaneTenantId)return!0;try{let{tenants:n}=await e.adapters.tenants.list({q:`parent_tenant_id:${t}`,per_page:1});return n.some(e=>e.parent_tenant_id===t)}catch{return!0}}function Bt(e,t={}){let n=async n=>{try{await zt(e,n)&&await Rt(e,n)}catch(e){t.logger?.warn(`Could not record a config change for ${n}:`,e)}},r=e=>({afterCreate:async(t,r)=>{Lt(e,r)&&await n(t.tenantId)},afterUpdate:async(t,r,i)=>{Lt(e,i)&&await n(t.tenantId)},afterDelete:async e=>n(e.tenantId)});return{actions:r(`action`),hooks:r(`hook`),hookCode:r(`hookCode`),connections:r(`connection`),resourceServers:r(`resourceServer`)}}function Vt(e){return{async create(t){let n={...K,waves:t.waves??[...K.waves],canary:t.canary??K.canary,failure_threshold:t.failureThreshold??K.failure_threshold,max_concurrent:t.maxConcurrent??K.max_concurrent,trigger:`manual`,root_tenant_id:t.rootTenantId??e.controlPlaneTenantId,dry_run:t.dryRun,force:t.force,planned:!1},r=Z(e),i=await r.create({kind:`config-sync`,initiated_by:t.initiatedBy,config:n});return await Ot(e,i,{tenantIds:t.tenantIds}),await jt(e,i.id),await r.get(i.id)??i},pause:(t,n)=>Nt(e,t,n),resume:t=>Pt(e,t)}}function Ht(e){let{dataAdapter:n,controlPlane:r,controlPlane:{tenantId:i=`control_plane`,clientId:a}={},resolveControlPlane:o,inheritanceShadow:s,syncDefaults:c,rolloutExecutor:l,sync:u={resourceServers:!0,roles:!0},defaultPermissions:d=[`tenant:admin`],requireOrganizationMatch:p=!1,managementApiExtensions:m=[],entityHooks:g,getChildTenantIds:v,getAdapters:y,...b}=e;if(o&&!r)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.");let x=n,ee=n,S;if(r){let e=fe({base:ge({controlPlaneTenantId:i,controlPlaneClientId:a,resolveControlPlane:o}),getTenant:async e=>await n.tenants.get(e)??null,controlPlaneTenantId:i});S=t=>e.invalidate(t),x=Se(n,{controlPlaneTenantId:i,controlPlaneClientId:a,resolveControlPlane:o,inheritanceShadow:s,configSync:e}),ee={...ve(n,{controlPlaneTenantId:i,resolveControlPlane:e.resolve}),multiTenancyConfig:{controlPlaneTenantId:i,controlPlaneClientId:a,resolveControlPlane:e.resolve}}}let C=b.tenantOperationExecutor,w;if(n.tenantOperations&&n.tenantOperationEvents){let e={tenantOperations:n.tenantOperations,tenantOperationEvents:n.tenantOperationEvents},t=b.tenantUpgrade,r=f(e),a=c??Ge(n,{controlPlaneTenantId:i,resolveControlPlane:o}),s=h({stores:e,definitions:{...t?{upgrade:e=>[{name:`upgrade`,async run(){if(!e.tenant_id)throw Error(`upgrade operations require a tenant_id`);await t(e.tenant_id)}}]}:{},"sync-defaults":e=>[{name:`sync-defaults`,run:()=>We({operation:e,syncConfig:a,recorder:r})}]}});w=s,C??={engine:s.engine,kinds:t?[`upgrade`,`sync-defaults`]:[`sync-defaults`],enqueue:t=>_(e,s,{...t,tenant_id:t.tenant_id},{returnFailed:t.kind===`sync-defaults`})}}let T=l??w,E=T&&n.rollouts&&n.tenantOperations&&n.tenantOperationEvents?{adapters:n,executor:T,controlPlaneTenantId:i,resolveControlPlane:o}:void 0,D=E?Vt(E):void 0,O=E?Bt(E,{logger:console}):void 0,k=u!==!1,A=k?{resourceServers:u.resourceServers??!0,roles:u.roles??!0}:{resourceServers:!1,roles:!1},{entityHooks:te,tenantHooks:j}=it({controlPlaneTenantId:i,getChildTenantIds:v??(async()=>(await(0,t.fetchAll)(e=>x.tenants.list(e),`tenants`,{cursorField:`id`,pageSize:100})).filter(e=>e.id!==i).map(e=>e.id)),getAdapters:y??(async()=>x),getControlPlaneAdapters:async()=>x,sync:A}),M={resourceServers:[te.resourceServers,O?.resourceServers,...g?.resourceServers??[]],roles:[te.roles,...g?.roles??[]],connections:[O?.connections,...g?.connections??[]],tenants:g?.tenants??[],rolePermissions:g?.rolePermissions??[],actions:[O?.actions,...g?.actions??[]],hooks:[O?.hooks,...g?.hooks??[]],hookCode:[O?.hookCode,...g?.hookCode??[]]},N=Ye({accessControl:{controlPlaneTenantId:i,requireOrganizationMatch:p,defaultPermissions:d}}),ne=U({accessControl:{controlPlaneTenantId:i,requireOrganizationMatch:p,defaultPermissions:d},onConfigSyncChange:e=>S?.(e),configSyncStatus:e=>Ft({adapters:n,controlPlaneTenantId:i,resolveControlPlane:o},e)},{tenants:{async beforeCreate(e,t){return N.beforeCreate&&(t=await N.beforeCreate(e,t)),j.beforeCreate&&(t=await j.beforeCreate(e,t)),t},async afterCreate(e,t){await N.afterCreate?.(e,t),await j.afterCreate?.(e,t)},async beforeDelete(e,t){await N.beforeDelete?.(e,t),await j.beforeDelete?.(e,t)}}}),{app:re}=(0,t.init)({dataAdapter:x,managementDataAdapter:ee,...b,tenantOperationExecutor:C,...D?{rolloutController:D}:{},entityHooks:M,managementApiExtensions:[...m,{path:`/tenants`,router:ne}],managementApiMiddleware:[...b.managementApiMiddleware??[],...k?[vt()]:[]]});return{app:re,controlPlaneTenantId:i,rollouts:E}}function Ut(e){let{pkcs7:t,tenant_id:n,...r}=e;return r}async function Wt(e,n,r={},i){let a=S(r),o=r.signingKeys??!0,s=r.tenants??!0,c=await D(e,n,a),l=o?(await(0,t.listControlPlaneKeys)(e.keys)).map(Ut):[],u=s?await Gt(e,n,i):[];return{connections:c.connections,resourceServers:c.resourceServers.filter(e=>e.is_system),hooks:c.hooks.filter(T),emailProvider:c.emailProvider,branding:c.branding,promptSettings:c.promptSettings,signingKeys:l,tenants:u}}async function Gt(e,t,n){let r=n&&n!==t?[t,n]:[t],i=[];for(let t of r){let n=await e.tenants.get(t);i.push({id:t,friendly_name:n?.friendly_name||t})}return i}async function Kt(e,n,r){let i=C();if(e.length===0)return i;let a=await(0,t.listControlPlaneKeys)(n.keys),o=new Set(a.map(e=>e.kid));for(let t of e)await E(i,`signing_key ${t.kid}`,r,async()=>{let e=Ut(t);o.has(e.kid)||(await n.keys.create(e),o.add(e.kid),i.upserted+=1)});return i}async function qt(e,t,n){let r=C();for(let i of e)await E(r,`tenant ${i.id}`,n,async()=>{await t.tenants.get(i.id)||(await t.tenants.create({id:i.id,friendly_name:i.friendly_name}),r.upserted+=1)});return r}async function Jt(e,n,r,i={}){let a=i.continueOnError??!1,o=S(i.entities),s=i.entities?.signingKeys??!0,c=i.entities?.tenants??!0,l={connections:e.connections,resourceServers:e.resourceServers,hooks:e.hooks,emailProvider:e.emailProvider?t.emailProviderSchema.parse(e.emailProvider):null,branding:e.branding?t.brandingSchema.parse(e.branding):null,promptSettings:e.promptSettings?t.promptSettingSchema.parse(e.promptSettings):null},u=c?await qt(e.tenants??[],n,a):C(),d=w(r);await O(l,n,r,o,a,d);let f=s?await Kt(e.signingKeys,n,a):C(),p=e.resolved&&i.resolved?await Re(e.resolved,n,i.resolved.tenantId,{continueOnError:a,...i.resolved}):void 0;return{...d,signingKeys:f,tenants:u,...p?{resolved:p}:{}}}function Yt(e){return{syncDefaults:t=>k(e,t),syncDefaultsToTenants:async t=>{let n=[];for(let r of t)n.push(await k(e,r));return n}}}function Xt(e){let t=Zt(e);return{name:`multi-tenancy`,middleware:Ct(e),hooks:t,routes:[{path:`/management`,handler:U(e,t)}],onRegister:async()=>{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`)}}}function Zt(e){let t=e.accessControl?i(e.accessControl):{},n=e.databaseIsolation?o(e.databaseIsolation):{},r=Ye(e);return{...t,...n,tenants:r}}function Qt(t){let n=new e.Hono,r=Zt(t);return n.route(`/tenants`,U(t,r)),n}function $t(e){return{hooks:Zt(e),middleware:Ct(e),app:Qt(e),config:e,wrapAdapters:(t,n)=>Se(t,{controlPlaneTenantId:e.accessControl?.controlPlaneTenantId,controlPlaneClientId:n?.controlPlaneClientId})}}exports.DEFAULT_ROLLOUT_SETTINGS=K,exports.DEFAULT_ROLLOUT_WAVES=wt,exports.advanceRollout=jt,exports.advanceRollouts=Mt,exports.applyControlPlaneDefaultsPayload=Jt,exports.applyResolvedConfigBlock=Re,exports.assignWaves=Tt,exports.buildControlPlaneDefaultsPayload=Wt,exports.buildEngineInstanceId=l,exports.buildResolvedConfigBlock=Ne,exports.compareShadow=se,exports.computeLegacyConfig=ee,exports.createAccessControlHooks=i,exports.createAccessControlMiddleware=bt,exports.createConfigSyncResolver=fe,exports.createControlPlaneTenantMiddleware=yt,exports.createDatabaseHooks=o,exports.createDatabaseMiddleware=St,exports.createDirectRolloutAdapter=Yt,exports.createExpectedHash=Y,exports.createInProcessSyncConfig=Ge,exports.createInlineExecutor=h,exports.createMultiTenancy=Qt,exports.createMultiTenancyHooks=Zt,exports.createMultiTenancyMiddleware=Ct,exports.createMultiTenancyPlugin=Xt,exports.createOperationRecorder=f,exports.createOperationRow=g,exports.createProtectSyncedMiddleware=vt,exports.createProvisioningHooks=Ye,exports.createRolloutController=Vt,exports.createRolloutWriteHooks=Bt,exports.createRuntimeFallbackAdapter=ye,exports.createShadowReporter=ue,exports.createSubdomainMiddleware=xt,exports.createSyncHooks=it,exports.createTenantsOpenAPIRouter=U,exports.diffConfig=oe,exports.effectiveOverride=L,exports.effectiveScope=I,exports.enqueueTenantOperation=_,exports.errorToMessage=d,exports.findUndecryptableKeyIds=Ie,exports.getConfigSyncStatus=Ft,exports.initMultiTenant=Ht,exports.inlineStepRunner=m,exports.isPublishedRow=Lt,exports.isTerminalStatus=p,exports.listRolloutOperations=Q,exports.listSyncedDescendants=Et,exports.mergeClientWithFallback=he,exports.mergeConfig=Ae,exports.pauseRollout=Nt,exports.planRollout=Ot,exports.projectControlPlaneDefaults=k,exports.readConfigRows=A,exports.readRolloutConfig=q,exports.reconcileConfigDrift=It,exports.requestRollout=Rt,exports.resolveTenantChain=y,exports.resumeRollout=Pt,exports.runRecordedTenantOperation=qe,exports.runSyncDefaultsStep=We,exports.setupMultiTenancy=$t,exports.summarizeSyncResult=Ue,exports.syncErrors=He,exports.syncOptionsOf=Ve,exports.syncedRowId=z,exports.validateTenantAccess=a,exports.withRuntimeFallback=Se,exports.withSystemResourceServerInheritance=ve;