@authhero/multi-tenancy 15.1.2 → 15.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/multi-tenancy.cjs +1 -1
- package/dist/multi-tenancy.mjs +2145 -703
- package/dist/types/index.d.ts +6 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/inheritance/chain.d.ts +18 -0
- package/dist/types/inheritance/chain.d.ts.map +1 -0
- package/dist/types/inheritance/index.d.ts +10 -0
- package/dist/types/inheritance/index.d.ts.map +1 -0
- package/dist/types/inheritance/legacy.d.ts +7 -0
- package/dist/types/inheritance/legacy.d.ts.map +1 -0
- package/dist/types/inheritance/merge.d.ts +40 -0
- package/dist/types/inheritance/merge.d.ts.map +1 -0
- package/dist/types/inheritance/read.d.ts +5 -0
- package/dist/types/inheritance/read.d.ts.map +1 -0
- package/dist/types/inheritance/report.d.ts +20 -0
- package/dist/types/inheritance/report.d.ts.map +1 -0
- package/dist/types/inheritance/shadow.d.ts +30 -0
- package/dist/types/inheritance/shadow.d.ts.map +1 -0
- package/dist/types/inheritance/types.d.ts +24 -0
- package/dist/types/inheritance/types.d.ts.map +1 -0
- package/dist/types/init.d.ts +38 -0
- package/dist/types/init.d.ts.map +1 -1
- package/dist/types/middleware/config-sync-mode.d.ts +36 -0
- package/dist/types/middleware/config-sync-mode.d.ts.map +1 -0
- package/dist/types/middleware/index.d.ts +3 -1
- package/dist/types/middleware/index.d.ts.map +1 -1
- package/dist/types/middleware/protect-synced.d.ts +1 -1
- package/dist/types/middleware/protect-synced.d.ts.map +1 -1
- package/dist/types/middleware/settings-inheritance.d.ts +51 -3
- package/dist/types/middleware/settings-inheritance.d.ts.map +1 -1
- package/dist/types/operations/enqueue.d.ts +8 -1
- package/dist/types/operations/enqueue.d.ts.map +1 -1
- package/dist/types/operations/index.d.ts +3 -1
- package/dist/types/operations/index.d.ts.map +1 -1
- package/dist/types/operations/recorder.d.ts +2 -0
- package/dist/types/operations/recorder.d.ts.map +1 -1
- package/dist/types/operations/sync-defaults.d.ts +55 -0
- package/dist/types/operations/sync-defaults.d.ts.map +1 -0
- package/dist/types/operations/types.d.ts +2 -0
- package/dist/types/operations/types.d.ts.map +1 -1
- package/dist/types/rollout/index.d.ts +2 -0
- package/dist/types/rollout/index.d.ts.map +1 -1
- package/dist/types/rollout/payload.d.ts +15 -0
- package/dist/types/rollout/payload.d.ts.map +1 -1
- package/dist/types/rollout/resolved-sync.d.ts +91 -0
- package/dist/types/rollout/resolved-sync.d.ts.map +1 -0
- package/dist/types/rollouts/advance.d.ts +44 -0
- package/dist/types/rollouts/advance.d.ts.map +1 -0
- package/dist/types/rollouts/config.d.ts +54 -0
- package/dist/types/rollouts/config.d.ts.map +1 -0
- package/dist/types/rollouts/controller.d.ts +29 -0
- package/dist/types/rollouts/controller.d.ts.map +1 -0
- package/dist/types/rollouts/enumerate.d.ts +25 -0
- package/dist/types/rollouts/enumerate.d.ts.map +1 -0
- package/dist/types/rollouts/hashes.d.ts +10 -0
- package/dist/types/rollouts/hashes.d.ts.map +1 -0
- package/dist/types/rollouts/index.d.ts +19 -0
- package/dist/types/rollouts/index.d.ts.map +1 -0
- package/dist/types/rollouts/plan.d.ts +29 -0
- package/dist/types/rollouts/plan.d.ts.map +1 -0
- package/dist/types/rollouts/reconcile.d.ts +38 -0
- package/dist/types/rollouts/reconcile.d.ts.map +1 -0
- package/dist/types/rollouts/status.d.ts +28 -0
- package/dist/types/rollouts/status.d.ts.map +1 -0
- package/dist/types/rollouts/trigger.d.ts +52 -0
- package/dist/types/rollouts/trigger.d.ts.map +1 -0
- package/dist/types/rollouts/types.d.ts +25 -0
- package/dist/types/rollouts/types.d.ts.map +1 -0
- package/dist/types/routes/tenants.d.ts.map +1 -1
- package/dist/types/types.d.ts +12 -0
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/index.d.ts +1 -0
- package/dist/types/utils/index.d.ts.map +1 -1
- package/dist/types/utils/tenant-tree.d.ts +33 -0
- package/dist/types/utils/tenant-tree.d.ts.map +1 -0
- package/package.json +5 -5
package/dist/multi-tenancy.cjs
CHANGED
|
@@ -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 w(e,r,s,c)),l&&e.ctx){let t=e.ctx.var.user;if(t?.sub&&!await C(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 C(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 w(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 T(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 E(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 D=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})}),O=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 k(e){return e.metadata?.sync!==!1}function A(e){let{sync:n={},filters:r={}}=e,i=n.resourceServers??!0,a=n.roles??!0,o=e=>k(e)?r.resourceServers?r.resourceServers(e):!0:!1,s=e=>k(e)?r.roles?r.roles(e):!0:!1,c=i?T(e,D,o):void 0,l=a?T(e,O,s):void 0,u=i?E(e,D,o):void 0,d=a?E(e,O,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 j(e){return e.var.data??e.env.data}var ee=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 te(e){let t=ee.safeParse(e);return t.success?t.data:void 0}function ne(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 M(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 j(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??j(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=>j(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 j(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 j(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:j(e),ctx:e};i.tenants?.beforeCreate&&(t=await i.tenants.beforeCreate(n,t));let a=await j(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??j(n).multiTenancyConfig?.controlPlaneTenantId;if(o){let e=te(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&&ne(e)&&(c=!0)}if(c||=(await(0,t.fetchAll)(t=>j(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 j(n).tenants.get(a))throw new r.HTTPException(404,{message:`Tenant not found`});let s={adapters:j(n),ctx:n};return i.tenants?.beforeDelete&&await i.tenants.beforeDelete(s,a),await j(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 j(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 j(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 j(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`})}}let o=(0,t.deepMergePatch)(a,i);await j(e).tenants.update(e.var.tenant_id,o);let s=await j(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 re(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 ie(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 ae(e){return{resource_server:`resource server`,role:`role`,connection:`connection`}[e]}function oe(){return async(e,t)=>{if(![`PATCH`,`PUT`,`DELETE`].includes(e.req.method))return t();let n=re(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 ie(j(e),i,n))throw new r.HTTPException(403,{message:`This ${ae(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`});return t()}}function N(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 P(e,t){let n=[...t||[],...e||[]];return[...new Set(n)]}function se(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 F(e,t){return t?{...e,scopes:se(e.scopes,t.scopes)}:e}function ce(e,t){return t?{...e,callbacks:P(e.callbacks,t.callbacks),web_origins:P(e.web_origins,t.web_origins),allowed_logout_urls:P(e.allowed_logout_urls,t.allowed_logout_urls),allowed_origins:P(e.allowed_origins,t.allowed_origins)}:e}function I(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 L(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:F(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?F(e,c.get(e.id)??null):e);return{...i,resource_servers:l}}}}function R(e,t){let n=I({controlPlaneTenantId:t.controlPlaneTenantId,resolveControlPlane:t.resolveControlPlane});return{...e,resourceServers:L(e,n)}}function z(e,t){let{controlPlaneTenantId:n,controlPlaneClientId:r,resolveControlPlane:i}=t,a=I({controlPlaneTenantId:n,controlPlaneClientId:r,resolveControlPlane:i});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 a(t);return!i||t===i.tenantId?r:N(r,(await e.connections.list(i.tenantId)).connections||[])},list:async(t,n)=>{let r=await e.connections.list(t,n),i=await a(t);if(!i||t===i.tenantId)return r;let o=await e.connections.list(i.tenantId),s=r.connections.map(e=>N(e,o.connections||[]));return{...r,connections:s}}},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 a(t);if(!i||t===i.tenantId)return r;let o=await e.connections.list(i.tenantId);return r.map(e=>N(e,o.connections||[]))}},emailProviders:{...e.emailProviders,get:async t=>{let n=await e.emailProviders.get(t);if(n)return n;let r=await a(t);return!r||t===r.tenantId?null:e.emailProviders.get(r.tenantId)}},resourceServers:L(e,a),hooks:le(e,a)}}function B(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(B);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&&B(o)?o:null}}}function V(e,t){return z(e,t)}function ue(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 H(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 U(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 j(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 W(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 G(e){let t=U(e),n=H(e),r=W(e);return async(e,i)=>(await t(e,async()=>{}),await n(e,async()=>{}),await r(e,async()=>{}),i())}function de(e){let{dataAdapter:n,controlPlane:r,controlPlane:{tenantId:i=`control_plane`,clientId:a}={},resolveControlPlane:o,sync:s={resourceServers:!0,roles:!0},defaultPermissions:c=[`tenant:admin`],requireOrganizationMatch:l=!1,managementApiExtensions:u=[],entityHooks:d,getChildTenantIds:f,getAdapters:p,...m}=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 g=n,v=n;r&&(g=V(n,{controlPlaneTenantId:i,controlPlaneClientId:a,resolveControlPlane:o}),v={...R(n,{controlPlaneTenantId:i,resolveControlPlane:o}),multiTenancyConfig:{controlPlaneTenantId:i,controlPlaneClientId:a,resolveControlPlane:o}});let y=m.tenantOperationExecutor;if(!y&&n.tenantOperations&&n.tenantOperationEvents&&m.tenantUpgrade){let e={tenantOperations:n.tenantOperations,tenantOperationEvents:n.tenantOperationEvents},t=m.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)}}]}});y={engine:r.engine,enqueue:t=>_(e,r,{...t,tenant_id:t.tenant_id})}}let b=s!==!1,S=b?{resourceServers:s.resourceServers??!0,roles:s.roles??!0}:{resourceServers:!1,roles:!1},{entityHooks:C,tenantHooks:w}=A({controlPlaneTenantId:i,getChildTenantIds:f??(async()=>(await(0,t.fetchAll)(e=>g.tenants.list(e),`tenants`,{cursorField:`id`,pageSize:100})).filter(e=>e.id!==i).map(e=>e.id)),getAdapters:p??(async()=>g),getControlPlaneAdapters:async()=>g,sync:S}),T={resourceServers:[C.resourceServers,...d?.resourceServers??[]],roles:[C.roles,...d?.roles??[]],connections:d?.connections??[],tenants:d?.tenants??[],rolePermissions:d?.rolePermissions??[]},E=x({accessControl:{controlPlaneTenantId:i,requireOrganizationMatch:l,defaultPermissions:c}}),D=M({accessControl:{controlPlaneTenantId:i,requireOrganizationMatch:l,defaultPermissions:c}},{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:g,managementDataAdapter:v,...m,tenantOperationExecutor:y,entityHooks:T,managementApiExtensions:[...u,{path:`/tenants`,router:D}],managementApiMiddleware:[...m.managementApiMiddleware??[],...b?[oe()]:[]]});return{app:O,controlPlaneTenantId:i}}function K(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 q(){return{upserted:0,errors:[]}}function J(e){return{tenantId:e,connections:q(),resourceServers:q(),hooks:q(),emailProvider:q(),branding:q(),promptSettings:q()}}function Y(e){let t=e.metadata;return!!(t&&t.inheritable===!0)}async function X(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 Z(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 fe(e,n,r,i,a,o){if(i.connections)for(let i of e.connections){let e=i.id;e&&await X(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 X(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)!Y(i)||!i.hook_id||await X(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 X(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 X(o.branding,`branding`,a,async()=>{await n.branding.set(r,e.branding),o.branding.upserted+=1}),i.promptSettings&&e.promptSettings&&await X(o.promptSettings,`prompt_settings`,a,async()=>{await n.promptSettings.set(r,e.promptSettings),o.promptSettings.upserted+=1})}async function Q(e,t){let{controlPlaneTenantId:n,getControlPlaneAdapters:r,getAdapters:i,entities:a,continueOnError:o=!1}=e,s=K(a),c=await Z(await r(),n,s),l=await i(t),u=J(t);return await fe(c,l,n,s,o,u),u}function pe(e){let{pkcs7:t,tenant_id:n,...r}=e;return r}async function me(e,n,r={},i){let a=K(r),o=r.signingKeys??!0,s=r.tenants??!0,c=await Z(e,n,a),l=o?(await(0,t.listControlPlaneKeys)(e.keys)).map(pe):[],u=s?await he(e,n,i):[];return{connections:c.connections,resourceServers:c.resourceServers.filter(e=>e.is_system),hooks:c.hooks.filter(Y),emailProvider:c.emailProvider,branding:c.branding,promptSettings:c.promptSettings,signingKeys:l,tenants:u}}async function he(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 ge(e,n,r){let i=q();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 X(i,`signing_key ${t.kid}`,r,async()=>{let e=pe(t);o.has(e.kid)||(await n.keys.create(e),o.add(e.kid),i.upserted+=1)});return i}async function _e(e,t,n){let r=q();for(let i of e)await X(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 ve(e,n,r,i={}){let a=i.continueOnError??!1,o=K(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 _e(e.tenants??[],n,a):q(),d=J(r);await fe(l,n,r,o,a,d);let f=s?await ge(e.signingKeys,n,a):q();return{...d,signingKeys:f,tenants:u}}function ye(e){return{syncDefaults:t=>Q(e,t),syncDefaultsToTenants:async t=>{let n=[];for(let r of t)n.push(await Q(e,r));return n}}}function be(e){let t=$(e);return{name:`multi-tenancy`,middleware:G(e),hooks:t,routes:[{path:`/management`,handler:M(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 xe(t){let n=new e.Hono,r=$(t);return n.route(`/tenants`,M(t,r)),n}function Se(e){return{hooks:$(e),middleware:G(e),app:xe(e),config:e,wrapAdapters:(t,n)=>V(t,{controlPlaneTenantId:e.accessControl?.controlPlaneTenantId,controlPlaneClientId:n?.controlPlaneClientId})}}exports.applyControlPlaneDefaultsPayload=ve,exports.buildControlPlaneDefaultsPayload=me,exports.buildEngineInstanceId=l,exports.createAccessControlHooks=i,exports.createAccessControlMiddleware=H,exports.createControlPlaneTenantMiddleware=ue,exports.createDatabaseHooks=o,exports.createDatabaseMiddleware=W,exports.createDirectRolloutAdapter=ye,exports.createInlineExecutor=h,exports.createMultiTenancy=xe,exports.createMultiTenancyHooks=$,exports.createMultiTenancyMiddleware=G,exports.createMultiTenancyPlugin=be,exports.createOperationRecorder=f,exports.createProtectSyncedMiddleware=oe,exports.createProvisioningHooks=x,exports.createRuntimeFallbackAdapter=z,exports.createSubdomainMiddleware=U,exports.createSyncHooks=A,exports.createTenantsOpenAPIRouter=M,exports.enqueueTenantOperation=_,exports.errorToMessage=d,exports.initMultiTenant=de,exports.inlineStepRunner=m,exports.isTerminalStatus=p,exports.mergeClientWithFallback=ce,exports.projectControlPlaneDefaults=Q,exports.runRecordedTenantOperation=y,exports.setupMultiTenancy=Se,exports.validateTenantAccess=a,exports.withRuntimeFallback=V,exports.withSystemResourceServerInheritance=R;
|
|
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`&>(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;
|