@authhero/multi-tenancy 13.10.1 → 13.12.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.
@@ -1 +1 @@
1
- "use strict";var X=Object.defineProperty;var H=(t,a,i)=>a in t?X(t,a,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[a]=i;var M=(t,a,i)=>H(t,typeof a!="symbol"?a+"":a,i);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const j=require("hono"),A=require("authhero"),k=require("zod"),z=require("@authhero/adapter-interfaces"),b=require("@hono/zod-openapi");var w=class extends Error{constructor(a=500,i){super(i==null?void 0:i.message,{cause:i==null?void 0:i.cause});M(this,"res");M(this,"status");this.res=i==null?void 0:i.res,this.status=a}getResponse(){return this.res?new Response(this.res.body,{status:this.status,headers:this.res.headers}):new Response(this.message,{status:this.status})}};function U(t){const{controlPlaneTenantId:a,requireOrganizationMatch:i=!0}=t;return{async onTenantAccessValidation(e,n){if(n===a)return!0;if(i){const r=e.var.org_name,d=e.var.organization_id,o=r||d;return o?o===n:!1}return!0}}}function F(t,a,i,e){if(a===i)return!0;const n=e||t;return n?n===a:!1}function N(t){return{async resolveDataAdapters(a){try{return await t.getAdapters(a)}catch(i){console.error(`Failed to resolve data adapters for tenant ${a}:`,i);return}}}}function E(t){return{async beforeCreate(a,i){return!i.audience&&i.id?{...i,audience:A.getTenantAudience(i.id)}:i},async afterCreate(a,i){const{accessControl:e,databaseIsolation:n,settingsInheritance:r}=t;e&&a.ctx&&await x(a,i,e),n!=null&&n.onProvision&&await n.onProvision(i.id),(r==null?void 0:r.inheritFromControlPlane)!==!1&&a.ctx&&await te(a,i,t)},async beforeDelete(a,i){const{accessControl:e,databaseIsolation:n}=t;if(e)try{const d=(await a.adapters.organizations.list(e.controlPlaneTenantId)).organizations.find(o=>o.name===i);d&&await a.adapters.organizations.remove(e.controlPlaneTenantId,d.id)}catch(r){console.warn(`Failed to remove organization for tenant ${i}:`,r)}if(n!=null&&n.onDeprovision)try{await n.onDeprovision(i)}catch(r){console.warn(`Failed to deprovision database for tenant ${i}:`,r)}}}}async function x(t,a,i){const{controlPlaneTenantId:e,defaultPermissions:n,defaultRoles:r,issuer:d,adminRoleName:o="Tenant Admin",adminRoleDescription:c="Full access to all tenant management operations",addCreatorToOrganization:s=!0}=i,u=await t.adapters.organizations.create(e,{name:a.id,display_name:a.friendly_name||a.id});let f;if(d&&(f=await ee(t,e,o,c)),s&&t.ctx){const l=t.ctx.var.user;if(l!=null&&l.sub)try{await t.adapters.userOrganizations.create(e,{user_id:l.sub,organization_id:u.id}),f&&await t.adapters.userRoles.create(e,l.sub,f,u.id)}catch(p){console.warn(`Failed to add creator ${l.sub} to organization ${u.id}:`,p)}}r&&r.length>0&&console.log(`Would assign roles ${r.join(", ")} to organization ${u.id}`),n&&n.length>0&&console.log(`Would grant permissions ${n.join(", ")} to organization ${u.id}`)}async function ee(t,a,i,e){const r=(await t.adapters.roles.list(a,{})).roles.find(s=>s.name===i);if(r)return r.id;const d=await t.adapters.roles.create(a,{name:i,description:e}),o=A.MANAGEMENT_API_AUDIENCE,c=A.MANAGEMENT_API_SCOPES.map(s=>({role_id:d.id,resource_server_identifier:o,permission_name:s.value}));return await t.adapters.rolePermissions.assign(a,d.id,c),d.id}async function te(t,a,i){const{accessControl:e,settingsInheritance:n}=i;if(!e)return;const r=await t.adapters.tenants.get(e.controlPlaneTenantId);if(!r)return;let d={...r};const o=["id","created_at","updated_at","friendly_name","audience","sender_email","sender_name"];for(const c of o)delete d[c];if(n!=null&&n.inheritedKeys){const c={};for(const s of n.inheritedKeys)s in r&&!o.includes(s)&&(c[s]=r[s]);d=c}if(n!=null&&n.excludedKeys)for(const c of n.excludedKeys)delete d[c];n!=null&&n.transformSettings&&(d=n.transformSettings(d,a.id)),Object.keys(d).length>0&&await t.adapters.tenants.update(a.id,d)}function K(t){const{controlPlaneTenantId:a,getChildTenantIds:i,getAdapters:e,shouldSync:n=()=>!0,transformForSync:r}=t;async function d(s,u,f){return(await s.resourceServers.list(u,{q:`identifier:${f}`,per_page:1})).resource_servers[0]??null}async function o(s,u){const f=await i();await Promise.all(f.map(async l=>{try{const p=await e(l),y={...r?r(s,l):{name:s.name,identifier:s.identifier,scopes:s.scopes,signing_alg:s.signing_alg,signing_secret:s.signing_secret,token_lifetime:s.token_lifetime,token_lifetime_for_web:s.token_lifetime_for_web,skip_consent_for_verifiable_first_party_clients:s.skip_consent_for_verifiable_first_party_clients,allow_offline_access:s.allow_offline_access,verificationKey:s.verificationKey,options:s.options},is_system:!0};if(u==="create"){const T=await d(p,l,s.identifier);T&&T.id?await p.resourceServers.update(l,T.id,y):await p.resourceServers.create(l,y)}else{const T=await d(p,l,s.identifier);T&&T.id&&await p.resourceServers.update(l,T.id,y)}}catch(p){console.error(`Failed to sync resource server "${s.identifier}" to tenant "${l}":`,p)}}))}async function c(s){const u=await i();await Promise.all(u.map(async f=>{try{const l=await e(f),p=await d(l,f,s);p&&p.id&&await l.resourceServers.remove(f,p.id)}catch(l){console.error(`Failed to delete resource server "${s}" from tenant "${f}":`,l)}}))}return{afterCreate:async(s,u)=>{s.tenantId===a&&n(u)&&await o(u,"create")},afterUpdate:async(s,u,f)=>{s.tenantId===a&&n(f)&&await o(f,"update")},afterDelete:async(s,u)=>{s.tenantId===a&&await c(u)}}}function B(t){const{controlPlaneTenantId:a,getControlPlaneAdapters:i,getAdapters:e,shouldSync:n=()=>!0,transformForSync:r}=t;return{async afterCreate(d,o){if(o.id!==a)try{const c=await i(),s=await e(o.id),u=await A.fetchAll(f=>c.resourceServers.list(a,f),"resource_servers",{cursorField:"id",pageSize:100});await Promise.all(u.filter(f=>n(f)).map(async f=>{const l=f;try{const p=r?r(l,o.id):{name:l.name,identifier:l.identifier,scopes:l.scopes,signing_alg:l.signing_alg,signing_secret:l.signing_secret,token_lifetime:l.token_lifetime,token_lifetime_for_web:l.token_lifetime_for_web,skip_consent_for_verifiable_first_party_clients:l.skip_consent_for_verifiable_first_party_clients,allow_offline_access:l.allow_offline_access,verificationKey:l.verificationKey,options:l.options};await s.resourceServers.create(o.id,{...p,is_system:!0})}catch(p){console.error(`Failed to sync resource server "${l.identifier}" to new tenant "${o.id}":`,p)}}))}catch(c){console.error(`Failed to sync resource servers to new tenant "${o.id}":`,c)}}}}function W(t){const{controlPlaneTenantId:a,getChildTenantIds:i,getAdapters:e,shouldSync:n=()=>!0,transformForSync:r}=t;async function d(c,s,u){return(await c.roles.list(s,{q:`name:${u}`,per_page:1})).roles[0]??null}async function o(c,s){const u=await i();await Promise.all(u.map(async f=>{try{const l=await e(f),_={...r?r(c,f):{name:c.name,description:c.description},is_system:!0};if(s==="create"){const y=await d(l,f,c.name);y&&y.id?await l.roles.update(f,y.id,_):await l.roles.create(f,_)}else{const y=await d(l,f,c.name);y&&y.id&&await l.roles.update(f,y.id,_)}}catch(l){console.error(`Failed to sync role "${c.name}" to tenant "${f}":`,l)}}))}return{afterCreate:async(c,s)=>{c.tenantId===a&&n(s)&&await o(s,"create")},afterUpdate:async(c,s,u)=>{c.tenantId===a&&n(u)&&await o(u,"update")},afterDelete:async(c,s)=>{c.tenantId===a&&console.warn(`Role ${s} was deleted from control plane. Child tenant roles with matching names should be deleted manually or implement role name tracking.`)}}}function G(t){const{controlPlaneTenantId:a,getControlPlaneAdapters:i,getAdapters:e,shouldSync:n=()=>!0,transformForSync:r,syncPermissions:d=!0}=t;return{async afterCreate(o,c){if(c.id!==a)try{const s=await i(),u=await e(c.id),f=await A.fetchAll(p=>s.roles.list(a,p),"roles",{cursorField:"id",pageSize:100}),l=new Map;if(await Promise.all(f.filter(p=>n(p)).map(async p=>{const _=p;try{const y=r?r(_,c.id):{name:_.name,description:_.description},T=await u.roles.create(c.id,{...y,is_system:!0});l.set(_.id,T.id)}catch(y){console.error(`Failed to sync role "${_.name}" to new tenant "${c.id}":`,y)}})),d)for(const[p,_]of l)try{const y=await s.rolePermissions.list(a,p,{});y.length>0&&await u.rolePermissions.assign(c.id,_,y.map(T=>({role_id:_,resource_server_identifier:T.resource_server_identifier,permission_name:T.permission_name})))}catch(y){console.error(`Failed to sync permissions for role to new tenant "${c.id}":`,y)}}catch(s){console.error(`Failed to sync roles to new tenant "${c.id}":`,s)}}}}function $(t,a){const i=new j.Hono;return i.get("/",async e=>{var f,l;const n=z.auth0QuerySchema.parse(e.req.query()),{page:r,per_page:d,include_totals:o,q:c}=n,s=e.var.user;if(t.accessControl&&(s!=null&&s.sub)){const p=t.accessControl.controlPlaneTenantId,y=(await e.env.data.userOrganizations.listUserOrganizations(p,s.sub,{})).organizations.map(P=>P.name),T=await e.env.data.tenants.list({page:r,per_page:d,include_totals:o,q:c}),S=T.tenants.filter(P=>y.includes(P.id));return o?e.json({tenants:S,start:((f=T.totals)==null?void 0:f.start)??0,limit:((l=T.totals)==null?void 0:l.limit)??d,length:S.length}):e.json(S)}const u=await e.env.data.tenants.list({page:r,per_page:d,include_totals:o,q:c});return o?e.json(u):e.json(u.tenants)}),i.get("/:id",async e=>{const n=e.req.param("id");if(t.accessControl){const d=e.var.user,o=t.accessControl.controlPlaneTenantId;if(n!==o){if(!(d!=null&&d.sub))throw new w(401,{message:"Authentication required"});if(!(await e.env.data.userOrganizations.listUserOrganizations(o,d.sub,{})).organizations.some(u=>u.name===n))throw new w(403,{message:"Access denied to this tenant"})}}const r=await e.env.data.tenants.get(n);if(!r)throw new w(404,{message:"Tenant not found"});return e.json(r)}),i.post("/",async e=>{var n,r,d;try{const o=e.var.user;if(!(o!=null&&o.sub))throw new w(401,{message:"Authentication required to create tenants"});let c=z.tenantInsertSchema.parse(await e.req.json());const s={adapters:e.env.data,ctx:e};(n=a.tenants)!=null&&n.beforeCreate&&(c=await a.tenants.beforeCreate(s,c));const u=await e.env.data.tenants.create(c);return(r=a.tenants)!=null&&r.afterCreate&&await a.tenants.afterCreate(s,u),e.json(u,201)}catch(o){throw o instanceof k.z.ZodError?new w(400,{message:"Validation error",cause:o}):o instanceof Error&&("code"in o&&o.code==="SQLITE_CONSTRAINT_PRIMARYKEY"||(d=o.message)!=null&&d.includes("UNIQUE constraint failed"))?new w(409,{message:"Tenant with this ID already exists"}):o}}),i.patch("/:id",async e=>{var l,p;const n=e.req.param("id");if(t.accessControl){const _=e.var.user;if(!(_!=null&&_.sub))throw new w(401,{message:"Authentication required to update tenants"});const y=t.accessControl.controlPlaneTenantId;if(n!==y&&!(await e.env.data.userOrganizations.listUserOrganizations(y,_.sub,{})).organizations.some(P=>P.name===n))throw new w(403,{message:"Access denied to update this tenant"})}const r=z.tenantInsertSchema.partial().parse(await e.req.json()),{id:d,...o}=r;if(!await e.env.data.tenants.get(n))throw new w(404,{message:"Tenant not found"});const s={adapters:e.env.data,ctx:e};let u=o;(l=a.tenants)!=null&&l.beforeUpdate&&(u=await a.tenants.beforeUpdate(s,n,o)),await e.env.data.tenants.update(n,u);const f=await e.env.data.tenants.get(n);if(!f)throw new w(404,{message:"Tenant not found after update"});return(p=a.tenants)!=null&&p.afterUpdate&&await a.tenants.afterUpdate(s,f),e.json(f)}),i.delete("/:id",async e=>{var o,c;const n=e.req.param("id");if(t.accessControl&&n===t.accessControl.controlPlaneTenantId)throw new w(400,{message:"Cannot delete the control plane"});if(t.accessControl){const s=e.var.user;if(!(s!=null&&s.sub))throw new w(401,{message:"Authentication required to delete tenants"});const u=t.accessControl.controlPlaneTenantId;if(!(await e.env.data.userOrganizations.listUserOrganizations(u,s.sub,{})).organizations.some(p=>p.name===n))throw new w(403,{message:"Access denied to delete this tenant"})}if(!await e.env.data.tenants.get(n))throw new w(404,{message:"Tenant not found"});const d={adapters:e.env.data,ctx:e};return(o=a.tenants)!=null&&o.beforeDelete&&await a.tenants.beforeDelete(d,n),await e.env.data.tenants.remove(n),(c=a.tenants)!=null&&c.afterDelete&&await a.tenants.afterDelete(d,n),e.body(null,204)}),i}function ae(t,a){const i=new b.OpenAPIHono;return i.openapi(b.createRoute({tags:["tenants"],method:"get",path:"/",request:{query:z.auth0QuerySchema},security:[{Bearer:[]}],responses:{200:{content:{"application/json":{schema:b.z.object({tenants:b.z.array(z.tenantSchema),start:b.z.number().optional(),limit:b.z.number().optional(),length:b.z.number().optional()})}},description:"List of tenants"}}}),async e=>{var f,l,p,_;const n=e.req.valid("query"),{page:r,per_page:d,include_totals:o,q:c}=n,s=e.var.user;if(t.accessControl&&(s!=null&&s.sub)){const y=t.accessControl.controlPlaneTenantId,S=(await A.fetchAll(I=>e.env.data.userOrganizations.listUserOrganizations(y,s.sub,I),"organizations")).map(I=>I.name),P=await e.env.data.tenants.list({page:r,per_page:d,include_totals:o,q:c}),O=P.tenants.filter(I=>S.includes(I.id));return o?e.json({tenants:O,start:((f=P.totals)==null?void 0:f.start)??0,limit:((l=P.totals)==null?void 0:l.limit)??d,length:O.length}):e.json({tenants:O})}const u=await e.env.data.tenants.list({page:r,per_page:d,include_totals:o,q:c});return o?e.json({tenants:u.tenants,start:((p=u.totals)==null?void 0:p.start)??0,limit:((_=u.totals)==null?void 0:_.limit)??d,length:u.tenants.length}):e.json({tenants:u.tenants})}),i.openapi(b.createRoute({tags:["tenants"],method:"get",path:"/{id}",request:{params:b.z.object({id:b.z.string()})},security:[{Bearer:[]}],responses:{200:{content:{"application/json":{schema:z.tenantSchema}},description:"Tenant details"},404:{description:"Tenant not found"}}}),async e=>{const{id:n}=e.req.valid("param");if(t.accessControl){const d=e.var.user,o=t.accessControl.controlPlaneTenantId;if(n!==o){if(!(d!=null&&d.sub))throw new w(401,{message:"Authentication required"});if(!(await A.fetchAll(u=>e.env.data.userOrganizations.listUserOrganizations(o,d.sub,u),"organizations")).some(u=>u.name===n))throw new w(403,{message:"Access denied to this tenant"})}}const r=await e.env.data.tenants.get(n);if(!r)throw new w(404,{message:"Tenant not found"});return e.json(r)}),i.openapi(b.createRoute({tags:["tenants"],method:"post",path:"/",request:{body:{content:{"application/json":{schema:z.tenantInsertSchema}}}},security:[{Bearer:[]}],responses:{201:{content:{"application/json":{schema:z.tenantSchema}},description:"Tenant created"},400:{description:"Validation error"}}}),async e=>{var c,s;const n=e.var.user;if(!(n!=null&&n.sub))throw new w(401,{message:"Authentication required to create tenants"});let r=e.req.valid("json");const d={adapters:e.env.data,ctx:e};(c=a.tenants)!=null&&c.beforeCreate&&(r=await a.tenants.beforeCreate(d,r));const o=await e.env.data.tenants.create(r);return(s=a.tenants)!=null&&s.afterCreate&&await a.tenants.afterCreate(d,o),e.json(o,201)}),i.openapi(b.createRoute({tags:["tenants"],method:"patch",path:"/{id}",request:{params:b.z.object({id:b.z.string()}),body:{content:{"application/json":{schema:b.z.object(z.tenantInsertSchema.shape).partial()}}}},security:[{Bearer:["update:tenants"]}],responses:{200:{content:{"application/json":{schema:z.tenantSchema}},description:"Tenant updated"},403:{description:"Access denied"},404:{description:"Tenant not found"}}}),async e=>{var u,f;const{id:n}=e.req.valid("param");if(t.accessControl){const l=e.var.user,p=t.accessControl.controlPlaneTenantId;if(!(l!=null&&l.sub))throw new w(401,{message:"Authentication required"});if(n!==p&&!(await A.fetchAll(T=>e.env.data.userOrganizations.listUserOrganizations(p,l.sub,T),"organizations")).some(T=>T.name===n))throw new w(403,{message:"Access denied to this tenant"})}if(!await e.env.data.tenants.get(n))throw new w(404,{message:"Tenant not found"});const d=e.req.valid("json"),o={adapters:e.env.data,ctx:e};let c=d;(u=a.tenants)!=null&&u.beforeUpdate&&(c=await a.tenants.beforeUpdate(o,n,d)),await e.env.data.tenants.update(n,c);const s=await e.env.data.tenants.get(n);if(!s)throw new w(500,{message:"Failed to retrieve updated tenant"});return(f=a.tenants)!=null&&f.afterUpdate&&await a.tenants.afterUpdate(o,s),e.json(s)}),i.openapi(b.createRoute({tags:["tenants"],method:"delete",path:"/{id}",request:{params:b.z.object({id:b.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 e=>{var o,c;const{id:n}=e.req.valid("param");if(t.accessControl){const s=e.var.user,u=t.accessControl.controlPlaneTenantId;if(!(s!=null&&s.sub))throw new w(401,{message:"Authentication required"});if(n===u)throw new w(403,{message:"Cannot delete the control plane"});if(!(await A.fetchAll(p=>e.env.data.userOrganizations.listUserOrganizations(u,s.sub,p),"organizations")).some(p=>p.name===n))throw new w(403,{message:"Access denied to this tenant"})}if(!await e.env.data.tenants.get(n))throw new w(404,{message:"Tenant not found"});const d={adapters:e.env.data,ctx:e};return(o=a.tenants)!=null&&o.beforeDelete&&await a.tenants.beforeDelete(d,n),await e.env.data.tenants.remove(n),(c=a.tenants)!=null&&c.afterDelete&&await a.tenants.afterDelete(d,n),e.body(null,204)}),i}function ne(t){const a=[{pattern:/\/api\/v2\/resource-servers\/([^/]+)$/,type:"resource_server"},{pattern:/\/api\/v2\/roles\/([^/]+)$/,type:"role"},{pattern:/\/api\/v2\/connections\/([^/]+)$/,type:"connection"}];for(const{pattern:i,type:e}of a){const n=t.match(i);if(n&&n[1])return{type:e,id:n[1]}}return null}async function se(t,a,i){try{switch(i.type){case"resource_server":{const e=await t.resourceServers.get(a,i.id);return(e==null?void 0:e.is_system)===!0}case"role":{const e=await t.roles.get(a,i.id);return(e==null?void 0:e.is_system)===!0}case"connection":{const e=await t.connections.get(a,i.id);return(e==null?void 0:e.is_system)===!0}default:return!1}}catch{return!1}}function re(t){return{resource_server:"resource server",role:"role",connection:"connection"}[t]}function Q(){return async(t,a)=>{if(!["PATCH","PUT","DELETE"].includes(t.req.method))return a();const i=ne(t.req.path);if(!i)return a();const e=t.var.tenant_id||t.req.header("x-tenant-id")||t.req.header("tenant-id");if(!e)return a();if(await se(t.env.data,e,i))throw new w(403,{message:`This ${re(i.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`});return a()}}function L(t){return async(a,i)=>{if(!t.accessControl)return i();const e=a.var.tenant_id,n=a.var.organization_id;if(!e)throw new w(400,{message:"Tenant ID not found in request"});if(!F(n,e,t.accessControl.controlPlaneTenantId))throw new w(403,{message:`Access denied to tenant ${e}`});return i()}}function V(t){return async(a,i)=>{if(!t.subdomainRouting)return i();const{baseDomain:e,reservedSubdomains:n=[],resolveSubdomain:r}=t.subdomainRouting,d=a.req.header("host")||"";let o=null;if(d.endsWith(e)){const s=d.slice(0,-(e.length+1));s&&!s.includes(".")&&(o=s)}if(o&&n.includes(o)&&(o=null),!o)return t.accessControl&&a.set("tenant_id",t.accessControl.controlPlaneTenantId),i();let c=null;if(r)c=await r(o);else if(t.subdomainRouting.useOrganizations!==!1&&t.accessControl)try{const s=await a.env.data.organizations.get(t.accessControl.controlPlaneTenantId,o);s&&(c=s.id)}catch{}if(!c)throw new w(404,{message:`Tenant not found for subdomain: ${o}`});return a.set("tenant_id",c),i()}}function Y(t){return async(a,i)=>{if(!t.databaseIsolation)return i();const e=a.var.tenant_id;if(!e)throw new w(400,{message:"Tenant ID not found in request"});try{const n=await t.databaseIsolation.getAdapters(e);a.env.data=n}catch(n){throw console.error(`Failed to resolve database for tenant ${e}:`,n),new w(500,{message:"Failed to resolve tenant database"})}return i()}}function D(t){const a=V(t),i=L(t),e=Y(t);return async(n,r)=>(await a(n,async()=>{}),await i(n,async()=>{}),await e(n,async()=>{}),r())}function ie(t){const a=q(t);return{name:"multi-tenancy",middleware:D(t),hooks:a,routes:[{path:"/management",handler:$(t,a)}],onRegister:async()=>{console.log("Multi-tenancy plugin registered"),t.accessControl&&console.log(` - Access control enabled (control plane: ${t.accessControl.controlPlaneTenantId})`),t.subdomainRouting&&console.log(` - Subdomain routing enabled (base domain: ${t.subdomainRouting.baseDomain})`),t.databaseIsolation&&console.log(" - Database isolation enabled")}}}function q(t){const a=t.accessControl?U(t.accessControl):{},i=t.databaseIsolation?N(t.databaseIsolation):{},e=E(t);return{...a,...i,tenants:e}}function Z(t){const a=new j.Hono,i=q(t);return a.route("/tenants",$(t,i)),a}function oe(t){return{hooks:q(t),middleware:D(t),app:Z(t),config:t}}function ce(t){const{controlPlaneTenantId:a="control_plane",syncResourceServers:i=!0,syncRoles:e=!0,multiTenancy:n,entityHooks:r,...d}=t,o={...n,accessControl:{controlPlaneTenantId:a,requireOrganizationMatch:!1,defaultPermissions:["tenant:admin"],...n==null?void 0:n.accessControl}},c=q(o);let s,u;i&&(s=K({controlPlaneTenantId:a,getChildTenantIds:async()=>(await A.fetchAll(m=>t.dataAdapter.tenants.list(m),"tenants",{cursorField:"id",pageSize:100})).filter(m=>m.id!==a).map(m=>m.id),getAdapters:async h=>t.dataAdapter}),u=B({controlPlaneTenantId:a,getControlPlaneAdapters:async()=>t.dataAdapter,getAdapters:async h=>t.dataAdapter}));let f,l;e&&(f=W({controlPlaneTenantId:a,getChildTenantIds:async()=>(await A.fetchAll(m=>t.dataAdapter.tenants.list(m),"tenants",{cursorField:"id",pageSize:100})).filter(m=>m.id!==a).map(m=>m.id),getAdapters:async h=>t.dataAdapter}),l=G({controlPlaneTenantId:a,getControlPlaneAdapters:async()=>t.dataAdapter,getAdapters:async h=>t.dataAdapter,syncPermissions:!0}));const p=async(h,m,...g)=>{const v=[];if(h)try{await h(...g)}catch(C){v.push(C instanceof Error?C:new Error(String(C)))}if(m)try{await m(...g)}catch(C){v.push(C instanceof Error?C:new Error(String(C)))}if(v.length===1)throw v[0];if(v.length>1)throw new AggregateError(v,`Multiple hook errors: ${v.map(C=>C.message).join("; ")}`)},_=async(h,...m)=>{const g=[];for(const v of h)if(v)try{await v(...m)}catch(C){g.push(C instanceof Error?C:new Error(String(C)))}if(g.length===1)throw g[0];if(g.length>1)throw new AggregateError(g,`Multiple hook errors: ${g.map(v=>v.message).join("; ")}`)},y={...r,resourceServers:s?{...r==null?void 0:r.resourceServers,afterCreate:async(h,m)=>{var g;await p((g=r==null?void 0:r.resourceServers)==null?void 0:g.afterCreate,s==null?void 0:s.afterCreate,h,m)},afterUpdate:async(h,m,g)=>{var v;await p((v=r==null?void 0:r.resourceServers)==null?void 0:v.afterUpdate,s==null?void 0:s.afterUpdate,h,m,g)},afterDelete:async(h,m)=>{var g;await p((g=r==null?void 0:r.resourceServers)==null?void 0:g.afterDelete,s==null?void 0:s.afterDelete,h,m)}}:r==null?void 0:r.resourceServers,roles:f?{...r==null?void 0:r.roles,afterCreate:async(h,m)=>{var g;await p((g=r==null?void 0:r.roles)==null?void 0:g.afterCreate,f==null?void 0:f.afterCreate,h,m)},afterUpdate:async(h,m,g)=>{var v;await p((v=r==null?void 0:r.roles)==null?void 0:v.afterUpdate,f==null?void 0:f.afterUpdate,h,m,g)},afterDelete:async(h,m)=>{var g;await p((g=r==null?void 0:r.roles)==null?void 0:g.afterDelete,f==null?void 0:f.afterDelete,h,m)}}:r==null?void 0:r.roles,tenants:u||l?{...r==null?void 0:r.tenants,afterCreate:async(h,m)=>{var g;await _([(g=r==null?void 0:r.tenants)==null?void 0:g.afterCreate,u==null?void 0:u.afterCreate,l==null?void 0:l.afterCreate],h,m)}}:r==null?void 0:r.tenants},T={...c,tenants:u||l?{...c.tenants,afterCreate:async(h,m)=>{var g;(g=c.tenants)!=null&&g.afterCreate&&await c.tenants.afterCreate(h,m),await _([u==null?void 0:u.afterCreate,l==null?void 0:l.afterCreate],h,m)}}:c.tenants},S=ae(o,T),P=A.init({...d,entityHooks:y,managementApiExtensions:[...d.managementApiExtensions||[],{path:"/tenants",router:S}]}),{app:O,managementApp:I,...J}=P,R=new j.Hono;return R.onError((h,m)=>h instanceof w?h.getResponse():(console.error(h),m.json({message:"Internal Server Error"},500))),R.use("/api/v2/*",Q()),R.route("/",O),{app:R,managementApp:I,...J,multiTenancyConfig:o,multiTenancyHooks:c}}Object.defineProperty(exports,"MANAGEMENT_API_SCOPES",{enumerable:!0,get:()=>A.MANAGEMENT_API_SCOPES});Object.defineProperty(exports,"fetchAll",{enumerable:!0,get:()=>A.fetchAll});Object.defineProperty(exports,"seed",{enumerable:!0,get:()=>A.seed});exports.createAccessControlHooks=U;exports.createAccessControlMiddleware=L;exports.createDatabaseHooks=N;exports.createDatabaseMiddleware=Y;exports.createMultiTenancy=Z;exports.createMultiTenancyHooks=q;exports.createMultiTenancyMiddleware=D;exports.createMultiTenancyPlugin=ie;exports.createProtectSyncedMiddleware=Q;exports.createProvisioningHooks=E;exports.createResourceServerSyncHooks=K;exports.createRoleSyncHooks=W;exports.createSubdomainMiddleware=V;exports.createTenantResourceServerSyncHooks=B;exports.createTenantRoleSyncHooks=G;exports.createTenantsRouter=$;exports.init=ce;exports.setupMultiTenancy=oe;exports.validateTenantAccess=F;
1
+ "use strict";var Z=Object.defineProperty;var H=(e,t,s)=>t in e?Z(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s;var F=(e,t,s)=>H(e,typeof t!="symbol"?t+"":t,s);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const N=require("hono"),T=require("authhero"),C=require("@hono/zod-openapi"),I=require("@authhero/adapter-interfaces");var v=class extends Error{constructor(t=500,s){super(s==null?void 0:s.message,{cause:s==null?void 0:s.cause});F(this,"res");F(this,"status");this.res=s==null?void 0:s.res,this.status=t}getResponse(){return this.res?new Response(this.res.body,{status:this.status,headers:this.res.headers}):new Response(this.message,{status:this.status})}};function U(e){const{controlPlaneTenantId:t,requireOrganizationMatch:s=!0}=e;return{async onTenantAccessValidation(a,i){if(i===t)return!0;if(s){const n=a.var.org_name,u=a.var.organization_id,l=n||u;return l?l===i:!1}return!0}}}function E(e,t,s,a){if(t===s)return!0;const i=a||e;return i?i===t:!1}function K(e){return{async resolveDataAdapters(t){try{return await e.getAdapters(t)}catch(s){console.error(`Failed to resolve data adapters for tenant ${t}:`,s);return}}}}function G(e){return{async beforeCreate(t,s){return!s.audience&&s.id?{...s,audience:T.getTenantAudience(s.id)}:s},async afterCreate(t,s){const{accessControl:a,databaseIsolation:i,settingsInheritance:n}=e;a&&t.ctx&&await x(t,s,a),i!=null&&i.onProvision&&await i.onProvision(s.id),(n==null?void 0:n.inheritFromControlPlane)!==!1&&t.ctx&&await ae(t,s,e)},async beforeDelete(t,s){const{accessControl:a,databaseIsolation:i}=e;if(a)try{const u=(await t.adapters.organizations.list(a.controlPlaneTenantId)).organizations.find(l=>l.name===s);u&&await t.adapters.organizations.remove(a.controlPlaneTenantId,u.id)}catch(n){console.warn(`Failed to remove organization for tenant ${s}:`,n)}if(i!=null&&i.onDeprovision)try{await i.onDeprovision(s)}catch(n){console.warn(`Failed to deprovision database for tenant ${s}:`,n)}}}}async function x(e,t,s){const{controlPlaneTenantId:a,defaultPermissions:i,defaultRoles:n,issuer:u,adminRoleName:l="Tenant Admin",adminRoleDescription:c="Full access to all tenant management operations",addCreatorToOrganization:r=!0}=s,f=await e.adapters.organizations.create(a,{name:t.id,display_name:t.friendly_name||t.id});let d;if(u&&(d=await te(e,a,l,c)),r&&e.ctx){const o=e.ctx.var.user;if(o!=null&&o.sub&&!await ee(e,a,o.sub))try{await e.adapters.userOrganizations.create(a,{user_id:o.sub,organization_id:f.id}),d&&await e.adapters.userRoles.create(a,o.sub,d,f.id)}catch(g){console.warn(`Failed to add creator ${o.sub} to organization ${f.id}:`,g)}}n&&n.length>0&&console.log(`Would assign roles ${n.join(", ")} to organization ${f.id}`),i&&i.length>0&&console.log(`Would grant permissions ${i.join(", ")} to organization ${f.id}`)}async function ee(e,t,s){const a=await e.adapters.userRoles.list(t,s,void 0,"");for(const i of a)if((await e.adapters.rolePermissions.list(t,i.id,{per_page:1e3})).some(l=>l.permission_name==="admin:organizations"))return!0;return!1}async function te(e,t,s,a){const n=(await e.adapters.roles.list(t,{})).roles.find(r=>r.name===s);if(n)return n.id;const u=await e.adapters.roles.create(t,{name:s,description:a}),l=T.MANAGEMENT_API_AUDIENCE,c=T.MANAGEMENT_API_SCOPES.map(r=>({role_id:u.id,resource_server_identifier:l,permission_name:r.value}));return await e.adapters.rolePermissions.assign(t,u.id,c),u.id}async function ae(e,t,s){const{accessControl:a,settingsInheritance:i}=s;if(!a)return;const n=await e.adapters.tenants.get(a.controlPlaneTenantId);if(!n)return;let u={...n};const l=["id","created_at","updated_at","friendly_name","audience","sender_email","sender_name"];for(const c of l)delete u[c];if(i!=null&&i.inheritedKeys){const c={};for(const r of i.inheritedKeys)r in n&&!l.includes(r)&&(c[r]=n[r]);u=c}if(i!=null&&i.excludedKeys)for(const c of i.excludedKeys)delete u[c];i!=null&&i.transformSettings&&(u=i.transformSettings(u,t.id)),Object.keys(u).length>0&&await e.adapters.tenants.update(t.id,u)}function B(e){const{controlPlaneTenantId:t,getChildTenantIds:s,getAdapters:a,shouldSync:i=()=>!0,transformForSync:n}=e;async function u(r,f,d){return(await r.resourceServers.list(f,{q:`identifier:${d}`,per_page:1})).resource_servers[0]??null}async function l(r,f){const d=await s();await Promise.all(d.map(async o=>{try{const p=await a(o),h={...n?n(r,o):{name:r.name,identifier:r.identifier,scopes:r.scopes,signing_alg:r.signing_alg,signing_secret:r.signing_secret,token_lifetime:r.token_lifetime,token_lifetime_for_web:r.token_lifetime_for_web,skip_consent_for_verifiable_first_party_clients:r.skip_consent_for_verifiable_first_party_clients,allow_offline_access:r.allow_offline_access,verificationKey:r.verificationKey,options:r.options},is_system:!0};if(f==="create"){const A=await u(p,o,r.identifier);A&&A.id?await p.resourceServers.update(o,A.id,h):await p.resourceServers.create(o,h)}else{const A=await u(p,o,r.identifier);A&&A.id?await p.resourceServers.update(o,A.id,h):await p.resourceServers.create(o,h)}}catch(p){console.error(`Failed to sync resource server "${r.identifier}" to tenant "${o}":`,p)}}))}async function c(r){const f=await s();await Promise.all(f.map(async d=>{try{const o=await a(d),p=await u(o,d,r);p&&p.id&&await o.resourceServers.remove(d,p.id)}catch(o){console.error(`Failed to delete resource server "${r}" from tenant "${d}":`,o)}}))}return{afterCreate:async(r,f)=>{r.tenantId===t&&i(f)&&await l(f,"create")},afterUpdate:async(r,f,d)=>{r.tenantId===t&&i(d)&&await l(d,"update")},afterDelete:async(r,f)=>{r.tenantId===t&&await c(f)}}}function W(e){const{controlPlaneTenantId:t,getControlPlaneAdapters:s,getAdapters:a,shouldSync:i=()=>!0,transformForSync:n}=e;return{async afterCreate(u,l){if(l.id!==t)try{const c=await s(),r=await a(l.id),f=await T.fetchAll(d=>c.resourceServers.list(t,d),"resource_servers",{cursorField:"id",pageSize:100});await Promise.all(f.filter(d=>i(d)).map(async d=>{const o=d;try{const p=n?n(o,l.id):{name:o.name,identifier:o.identifier,scopes:o.scopes,signing_alg:o.signing_alg,signing_secret:o.signing_secret,token_lifetime:o.token_lifetime,token_lifetime_for_web:o.token_lifetime_for_web,skip_consent_for_verifiable_first_party_clients:o.skip_consent_for_verifiable_first_party_clients,allow_offline_access:o.allow_offline_access,verificationKey:o.verificationKey,options:o.options};await r.resourceServers.create(l.id,{...p,is_system:!0})}catch(p){console.error(`Failed to sync resource server "${o.identifier}" to new tenant "${l.id}":`,p)}}))}catch(c){console.error(`Failed to sync resource servers to new tenant "${l.id}":`,c)}}}}function L(e){const{controlPlaneTenantId:t,getChildTenantIds:s,getAdapters:a,shouldSync:i=()=>!0,transformForSync:n}=e;async function u(c,r,f){return(await c.roles.list(r,{q:`name:${f}`,per_page:1})).roles[0]??null}async function l(c,r){const f=await s();await Promise.all(f.map(async d=>{try{const o=await a(d),g={...n?n(c,d):{name:c.name,description:c.description},is_system:!0};if(r==="create"){const h=await u(o,d,c.name);h&&h.id?await o.roles.update(d,h.id,g):await o.roles.create(d,g)}else{const h=await u(o,d,c.name);h&&h.id?await o.roles.update(d,h.id,g):await o.roles.create(d,g)}}catch(o){console.error(`Failed to sync role "${c.name}" to tenant "${d}":`,o)}}))}return{afterCreate:async(c,r)=>{c.tenantId===t&&i(r)&&await l(r,"create")},afterUpdate:async(c,r,f)=>{c.tenantId===t&&i(f)&&await l(f,"update")},afterDelete:async(c,r)=>{c.tenantId===t&&console.warn(`Role ${r} was deleted from control plane. Child tenant roles with matching names should be deleted manually or implement role name tracking.`)}}}function Q(e){const{controlPlaneTenantId:t,getControlPlaneAdapters:s,getAdapters:a,shouldSync:i=()=>!0,transformForSync:n,syncPermissions:u=!0}=e;return{async afterCreate(l,c){if(c.id!==t)try{const r=await s(),f=await a(c.id),d=await T.fetchAll(p=>r.roles.list(t,p),"roles",{cursorField:"id",pageSize:100}),o=new Map;if(await Promise.all(d.filter(p=>i(p)).map(async p=>{const g=p;try{const h=n?n(g,c.id):{name:g.name,description:g.description},A=await f.roles.create(c.id,{...h,is_system:!0});o.set(g.id,A.id)}catch(h){console.error(`Failed to sync role "${g.name}" to new tenant "${c.id}":`,h)}})),u)for(const[p,g]of o)try{const h=await r.rolePermissions.list(t,p,{});h.length>0&&await f.rolePermissions.assign(c.id,g,h.map(A=>({role_id:g,resource_server_identifier:A.resource_server_identifier,permission_name:A.permission_name})))}catch(h){console.error(`Failed to sync permissions for role to new tenant "${c.id}":`,h)}}catch(r){console.error(`Failed to sync roles to new tenant "${c.id}":`,r)}}}}function O(e,t){const s=new C.OpenAPIHono;return s.openapi(C.createRoute({tags:["tenants"],method:"get",path:"/",request:{query:I.auth0QuerySchema},security:[{Bearer:[]}],responses:{200:{content:{"application/json":{schema:C.z.object({tenants:C.z.array(I.tenantSchema),start:C.z.number().optional(),limit:C.z.number().optional(),length:C.z.number().optional()})}},description:"List of tenants"}}}),async a=>{var p,g,h,A;const i=a.req.valid("query"),{page:n,per_page:u,include_totals:l,q:c}=i,r=a.var.user,f=((r==null?void 0:r.scope)||"").split(" "),d=f.includes("auth:read");if(console.log("User scopes:",f,"hasAuthRead:",d),d){const S=await a.env.data.tenants.list({page:n,per_page:u,include_totals:l,q:c});return l?a.json({tenants:S.tenants,start:((p=S.totals)==null?void 0:p.start)??0,limit:((g=S.totals)==null?void 0:g.limit)??u,length:S.tenants.length}):a.json({tenants:S.tenants})}if(e.accessControl&&(r!=null&&r.sub)){const S=e.accessControl.controlPlaneTenantId,R=(await T.fetchAll(M=>a.env.data.userOrganizations.listUserOrganizations(S,r.sub,M),"organizations")).map(M=>M.name);if(R.length===0)return l?a.json({tenants:[],start:0,limit:u??50,length:0}):a.json({tenants:[]});const $=R.length,D=n??0,P=u??50,w=D*P,m=R.slice(w,w+P);if(m.length===0)return l?a.json({tenants:[],start:w,limit:P,length:$}):a.json({tenants:[]});const y=m.map(M=>`id:${M}`).join(" OR "),_=c?`(${y}) AND (${c})`:y,b=await a.env.data.tenants.list({q:_,per_page:P,include_totals:!1});return l?a.json({tenants:b.tenants,start:w,limit:P,length:$}):a.json({tenants:b.tenants})}const o=await a.env.data.tenants.list({page:n,per_page:u,include_totals:l,q:c});return l?a.json({tenants:o.tenants,start:((h=o.totals)==null?void 0:h.start)??0,limit:((A=o.totals)==null?void 0:A.limit)??u,length:o.tenants.length}):a.json({tenants:o.tenants})}),s.openapi(C.createRoute({tags:["tenants"],method:"post",path:"/",request:{body:{content:{"application/json":{schema:I.tenantInsertSchema}}}},security:[{Bearer:[]}],responses:{201:{content:{"application/json":{schema:I.tenantSchema}},description:"Tenant created"},400:{description:"Validation error"},409:{description:"Tenant with this ID already exists"}}}),async a=>{var c,r;const i=a.var.user;if(!(i!=null&&i.sub))throw new v(401,{message:"Authentication required to create tenants"});let n=a.req.valid("json");const u={adapters:a.env.data,ctx:a};(c=t.tenants)!=null&&c.beforeCreate&&(n=await t.tenants.beforeCreate(u,n));const l=await a.env.data.tenants.create(n);return(r=t.tenants)!=null&&r.afterCreate&&await t.tenants.afterCreate(u,l),a.json(l,201)}),s.openapi(C.createRoute({tags:["tenants"],method:"delete",path:"/{id}",request:{params:C.z.object({id:C.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 a=>{var l,c;const{id:i}=a.req.valid("param");if(e.accessControl){const r=a.var.user,f=e.accessControl.controlPlaneTenantId;if(!(r!=null&&r.sub))throw new v(401,{message:"Authentication required"});if(i===f)throw new v(403,{message:"Cannot delete the control plane"});if(!(await T.fetchAll(p=>a.env.data.userOrganizations.listUserOrganizations(f,r.sub,p),"organizations")).some(p=>p.name===i))throw new v(403,{message:"Access denied to this tenant"})}if(!await a.env.data.tenants.get(i))throw new v(404,{message:"Tenant not found"});const u={adapters:a.env.data,ctx:a};return(l=t.tenants)!=null&&l.beforeDelete&&await t.tenants.beforeDelete(u,i),await a.env.data.tenants.remove(i),(c=t.tenants)!=null&&c.afterDelete&&await t.tenants.afterDelete(u,i),a.body(null,204)}),s}function ne(e){const t=[{pattern:/\/api\/v2\/resource-servers\/([^/]+)$/,type:"resource_server"},{pattern:/\/api\/v2\/roles\/([^/]+)$/,type:"role"},{pattern:/\/api\/v2\/connections\/([^/]+)$/,type:"connection"}];for(const{pattern:s,type:a}of t){const i=e.match(s);if(i&&i[1])return{type:a,id:i[1]}}return null}async function re(e,t,s){try{switch(s.type){case"resource_server":{const a=await e.resourceServers.get(t,s.id);return(a==null?void 0:a.is_system)===!0}case"role":{const a=await e.roles.get(t,s.id);return(a==null?void 0:a.is_system)===!0}case"connection":{const a=await e.connections.get(t,s.id);return(a==null?void 0:a.is_system)===!0}default:return!1}}catch{return!1}}function se(e){return{resource_server:"resource server",role:"role",connection:"connection"}[e]}function V(){return async(e,t)=>{if(!["PATCH","PUT","DELETE"].includes(e.req.method))return t();const s=ne(e.req.path);if(!s)return t();const a=e.var.tenant_id||e.req.header("x-tenant-id")||e.req.header("tenant-id");if(!a)return t();if(await re(e.env.data,a,s))throw new v(403,{message:`This ${se(s.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`});return t()}}function k(e){return async(t,s)=>{if(!e.accessControl)return s();const a=t.var.tenant_id,i=t.var.organization_id;if(!a)throw new v(400,{message:"Tenant ID not found in request"});if(!E(i,a,e.accessControl.controlPlaneTenantId))throw new v(403,{message:`Access denied to tenant ${a}`});return s()}}function J(e){return async(t,s)=>{if(!e.subdomainRouting)return s();const{baseDomain:a,reservedSubdomains:i=[],resolveSubdomain:n}=e.subdomainRouting,u=t.req.header("host")||"";let l=null;if(u.endsWith(a)){const r=u.slice(0,-(a.length+1));r&&!r.includes(".")&&(l=r)}if(l&&i.includes(l)&&(l=null),!l)return e.accessControl&&t.set("tenant_id",e.accessControl.controlPlaneTenantId),s();let c=null;if(n)c=await n(l);else if(e.subdomainRouting.useOrganizations!==!1&&e.accessControl)try{const r=await t.env.data.organizations.get(e.accessControl.controlPlaneTenantId,l);r&&(c=r.id)}catch{}if(!c)throw new v(404,{message:`Tenant not found for subdomain: ${l}`});return t.set("tenant_id",c),s()}}function X(e){return async(t,s)=>{if(!e.databaseIsolation)return s();const a=t.var.tenant_id;if(!a)throw new v(400,{message:"Tenant ID not found in request"});try{const i=await e.databaseIsolation.getAdapters(a);t.env.data=i}catch(i){throw console.error(`Failed to resolve database for tenant ${a}:`,i),new v(500,{message:"Failed to resolve tenant database"})}return s()}}function j(e){const t=J(e),s=k(e),a=X(e);return async(i,n)=>(await t(i,async()=>{}),await s(i,async()=>{}),await a(i,async()=>{}),n())}function ie(e){const t=z(e);return{name:"multi-tenancy",middleware:j(e),hooks:t,routes:[{path:"/management",handler:O(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 z(e){const t=e.accessControl?U(e.accessControl):{},s=e.databaseIsolation?K(e.databaseIsolation):{},a=G(e);return{...t,...s,tenants:a}}function Y(e){const t=new N.Hono,s=z(e);return t.route("/tenants",O(e,s)),t}function oe(e){return{hooks:z(e),middleware:j(e),app:Y(e),config:e}}function ce(e){const{controlPlaneTenantId:t="control_plane",syncResourceServers:s=!0,syncRoles:a=!0,multiTenancy:i,entityHooks:n,...u}=e,l={...i,accessControl:{controlPlaneTenantId:t,requireOrganizationMatch:!1,defaultPermissions:["tenant:admin"],...i==null?void 0:i.accessControl}},c=z(l);let r,f;s&&(r=B({controlPlaneTenantId:t,getChildTenantIds:async()=>(await T.fetchAll(m=>e.dataAdapter.tenants.list(m),"tenants",{cursorField:"id",pageSize:100})).filter(m=>m.id!==t).map(m=>m.id),getAdapters:async w=>e.dataAdapter}),f=W({controlPlaneTenantId:t,getControlPlaneAdapters:async()=>e.dataAdapter,getAdapters:async w=>e.dataAdapter}));let d,o;a&&(d=L({controlPlaneTenantId:t,getChildTenantIds:async()=>(await T.fetchAll(m=>e.dataAdapter.tenants.list(m),"tenants",{cursorField:"id",pageSize:100})).filter(m=>m.id!==t).map(m=>m.id),getAdapters:async w=>e.dataAdapter}),o=Q({controlPlaneTenantId:t,getControlPlaneAdapters:async()=>e.dataAdapter,getAdapters:async w=>e.dataAdapter,syncPermissions:!0}));const p=async(w,m,...y)=>{const _=[];if(w)try{await w(...y)}catch(b){_.push(b instanceof Error?b:new Error(String(b)))}if(m)try{await m(...y)}catch(b){_.push(b instanceof Error?b:new Error(String(b)))}if(_.length===1)throw _[0];if(_.length>1)throw new AggregateError(_,`Multiple hook errors: ${_.map(b=>b.message).join("; ")}`)},g=async(w,...m)=>{const y=[];for(const _ of w)if(_)try{await _(...m)}catch(b){y.push(b instanceof Error?b:new Error(String(b)))}if(y.length===1)throw y[0];if(y.length>1)throw new AggregateError(y,`Multiple hook errors: ${y.map(_=>_.message).join("; ")}`)},h={...n,resourceServers:r?{...n==null?void 0:n.resourceServers,afterCreate:async(w,m)=>{var y;await p((y=n==null?void 0:n.resourceServers)==null?void 0:y.afterCreate,r==null?void 0:r.afterCreate,w,m)},afterUpdate:async(w,m,y)=>{var _;await p((_=n==null?void 0:n.resourceServers)==null?void 0:_.afterUpdate,r==null?void 0:r.afterUpdate,w,m,y)},afterDelete:async(w,m)=>{var y;await p((y=n==null?void 0:n.resourceServers)==null?void 0:y.afterDelete,r==null?void 0:r.afterDelete,w,m)}}:n==null?void 0:n.resourceServers,roles:d?{...n==null?void 0:n.roles,afterCreate:async(w,m)=>{var y;await p((y=n==null?void 0:n.roles)==null?void 0:y.afterCreate,d==null?void 0:d.afterCreate,w,m)},afterUpdate:async(w,m,y)=>{var _;await p((_=n==null?void 0:n.roles)==null?void 0:_.afterUpdate,d==null?void 0:d.afterUpdate,w,m,y)},afterDelete:async(w,m)=>{var y;await p((y=n==null?void 0:n.roles)==null?void 0:y.afterDelete,d==null?void 0:d.afterDelete,w,m)}}:n==null?void 0:n.roles,tenants:f||o?{...n==null?void 0:n.tenants,afterCreate:async(w,m)=>{var y;await g([(y=n==null?void 0:n.tenants)==null?void 0:y.afterCreate,f==null?void 0:f.afterCreate,o==null?void 0:o.afterCreate],w,m)}}:n==null?void 0:n.tenants},A={...c,tenants:f||o?{...c.tenants,afterCreate:async(w,m)=>{var y;(y=c.tenants)!=null&&y.afterCreate&&await c.tenants.afterCreate(w,m),await g([f==null?void 0:f.afterCreate,o==null?void 0:o.afterCreate],w,m)}}:c.tenants},S=O(l,A),q=T.init({...u,entityHooks:h,managementApiExtensions:[...u.managementApiExtensions||[],{path:"/tenants",router:S}]}),{app:R,managementApp:$,...D}=q,P=new N.Hono;return P.onError((w,m)=>w instanceof v?w.getResponse():(console.error(w),m.json({message:"Internal Server Error"},500))),P.use("/api/v2/*",V()),P.route("/",R),{app:P,managementApp:$,...D,multiTenancyConfig:l,multiTenancyHooks:c}}Object.defineProperty(exports,"MANAGEMENT_API_SCOPES",{enumerable:!0,get:()=>T.MANAGEMENT_API_SCOPES});Object.defineProperty(exports,"fetchAll",{enumerable:!0,get:()=>T.fetchAll});Object.defineProperty(exports,"seed",{enumerable:!0,get:()=>T.seed});exports.createAccessControlHooks=U;exports.createAccessControlMiddleware=k;exports.createDatabaseHooks=K;exports.createDatabaseMiddleware=X;exports.createMultiTenancy=Y;exports.createMultiTenancyHooks=z;exports.createMultiTenancyMiddleware=j;exports.createMultiTenancyPlugin=ie;exports.createProtectSyncedMiddleware=V;exports.createProvisioningHooks=G;exports.createResourceServerSyncHooks=B;exports.createRoleSyncHooks=L;exports.createSubdomainMiddleware=J;exports.createTenantResourceServerSyncHooks=W;exports.createTenantRoleSyncHooks=Q;exports.createTenantsOpenAPIRouter=O;exports.init=ce;exports.setupMultiTenancy=oe;exports.validateTenantAccess=E;
@@ -1458,6 +1458,7 @@ declare const legacyClientSchema: z.ZodObject<{
1458
1458
  revoke_refresh_token_grant: z.ZodOptional<z.ZodBoolean>;
1459
1459
  trust_azure_adfs_email_verified_connection_property: z.ZodOptional<z.ZodBoolean>;
1460
1460
  use_scope_descriptions_for_consent: z.ZodOptional<z.ZodBoolean>;
1461
+ inherit_global_permissions_in_organizations: z.ZodOptional<z.ZodBoolean>;
1461
1462
  }, "strip", z.ZodTypeAny, {
1462
1463
  allow_changing_enable_sso?: boolean | undefined;
1463
1464
  allow_legacy_delegation_grant_types?: boolean | undefined;
@@ -1491,6 +1492,7 @@ declare const legacyClientSchema: z.ZodObject<{
1491
1492
  revoke_refresh_token_grant?: boolean | undefined;
1492
1493
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
1493
1494
  use_scope_descriptions_for_consent?: boolean | undefined;
1495
+ inherit_global_permissions_in_organizations?: boolean | undefined;
1494
1496
  }, {
1495
1497
  allow_changing_enable_sso?: boolean | undefined;
1496
1498
  allow_legacy_delegation_grant_types?: boolean | undefined;
@@ -1524,6 +1526,7 @@ declare const legacyClientSchema: z.ZodObject<{
1524
1526
  revoke_refresh_token_grant?: boolean | undefined;
1525
1527
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
1526
1528
  use_scope_descriptions_for_consent?: boolean | undefined;
1529
+ inherit_global_permissions_in_organizations?: boolean | undefined;
1527
1530
  }>>;
1528
1531
  sandbox_version: z.ZodOptional<z.ZodString>;
1529
1532
  legacy_sandbox_version: z.ZodOptional<z.ZodString>;
@@ -1685,6 +1688,7 @@ declare const legacyClientSchema: z.ZodObject<{
1685
1688
  revoke_refresh_token_grant?: boolean | undefined;
1686
1689
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
1687
1690
  use_scope_descriptions_for_consent?: boolean | undefined;
1691
+ inherit_global_permissions_in_organizations?: boolean | undefined;
1688
1692
  } | undefined;
1689
1693
  sandbox_version?: string | undefined;
1690
1694
  legacy_sandbox_version?: string | undefined;
@@ -1785,6 +1789,7 @@ declare const legacyClientSchema: z.ZodObject<{
1785
1789
  revoke_refresh_token_grant?: boolean | undefined;
1786
1790
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
1787
1791
  use_scope_descriptions_for_consent?: boolean | undefined;
1792
+ inherit_global_permissions_in_organizations?: boolean | undefined;
1788
1793
  } | undefined;
1789
1794
  sandbox_version?: string | undefined;
1790
1795
  legacy_sandbox_version?: string | undefined;
@@ -2175,6 +2180,7 @@ declare const legacyClientSchema: z.ZodObject<{
2175
2180
  revoke_refresh_token_grant?: boolean | undefined;
2176
2181
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
2177
2182
  use_scope_descriptions_for_consent?: boolean | undefined;
2183
+ inherit_global_permissions_in_organizations?: boolean | undefined;
2178
2184
  } | undefined;
2179
2185
  sandbox_version?: string | undefined;
2180
2186
  legacy_sandbox_version?: string | undefined;
@@ -2352,6 +2358,7 @@ declare const legacyClientSchema: z.ZodObject<{
2352
2358
  revoke_refresh_token_grant?: boolean | undefined;
2353
2359
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
2354
2360
  use_scope_descriptions_for_consent?: boolean | undefined;
2361
+ inherit_global_permissions_in_organizations?: boolean | undefined;
2355
2362
  } | undefined;
2356
2363
  sandbox_version?: string | undefined;
2357
2364
  legacy_sandbox_version?: string | undefined;
@@ -12062,6 +12069,7 @@ declare const tenantSchema: z.ZodObject<{
12062
12069
  revoke_refresh_token_grant: z.ZodOptional<z.ZodBoolean>;
12063
12070
  trust_azure_adfs_email_verified_connection_property: z.ZodOptional<z.ZodBoolean>;
12064
12071
  use_scope_descriptions_for_consent: z.ZodOptional<z.ZodBoolean>;
12072
+ inherit_global_permissions_in_organizations: z.ZodOptional<z.ZodBoolean>;
12065
12073
  }, "strip", z.ZodTypeAny, {
12066
12074
  allow_changing_enable_sso?: boolean | undefined;
12067
12075
  allow_legacy_delegation_grant_types?: boolean | undefined;
@@ -12095,6 +12103,7 @@ declare const tenantSchema: z.ZodObject<{
12095
12103
  revoke_refresh_token_grant?: boolean | undefined;
12096
12104
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
12097
12105
  use_scope_descriptions_for_consent?: boolean | undefined;
12106
+ inherit_global_permissions_in_organizations?: boolean | undefined;
12098
12107
  }, {
12099
12108
  allow_changing_enable_sso?: boolean | undefined;
12100
12109
  allow_legacy_delegation_grant_types?: boolean | undefined;
@@ -12128,6 +12137,7 @@ declare const tenantSchema: z.ZodObject<{
12128
12137
  revoke_refresh_token_grant?: boolean | undefined;
12129
12138
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
12130
12139
  use_scope_descriptions_for_consent?: boolean | undefined;
12140
+ inherit_global_permissions_in_organizations?: boolean | undefined;
12131
12141
  }>>;
12132
12142
  sandbox_version: z.ZodOptional<z.ZodString>;
12133
12143
  legacy_sandbox_version: z.ZodOptional<z.ZodString>;
@@ -12289,6 +12299,7 @@ declare const tenantSchema: z.ZodObject<{
12289
12299
  revoke_refresh_token_grant?: boolean | undefined;
12290
12300
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
12291
12301
  use_scope_descriptions_for_consent?: boolean | undefined;
12302
+ inherit_global_permissions_in_organizations?: boolean | undefined;
12292
12303
  } | undefined;
12293
12304
  sandbox_version?: string | undefined;
12294
12305
  legacy_sandbox_version?: string | undefined;
@@ -12389,6 +12400,7 @@ declare const tenantSchema: z.ZodObject<{
12389
12400
  revoke_refresh_token_grant?: boolean | undefined;
12390
12401
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
12391
12402
  use_scope_descriptions_for_consent?: boolean | undefined;
12403
+ inherit_global_permissions_in_organizations?: boolean | undefined;
12392
12404
  } | undefined;
12393
12405
  sandbox_version?: string | undefined;
12394
12406
  legacy_sandbox_version?: string | undefined;
@@ -16700,6 +16712,7 @@ declare const legacyClientSchema$1: z.ZodObject<{
16700
16712
  revoke_refresh_token_grant: z.ZodOptional<z.ZodBoolean>;
16701
16713
  trust_azure_adfs_email_verified_connection_property: z.ZodOptional<z.ZodBoolean>;
16702
16714
  use_scope_descriptions_for_consent: z.ZodOptional<z.ZodBoolean>;
16715
+ inherit_global_permissions_in_organizations: z.ZodOptional<z.ZodBoolean>;
16703
16716
  }, "strip", z.ZodTypeAny, {
16704
16717
  allow_changing_enable_sso?: boolean | undefined;
16705
16718
  allow_legacy_delegation_grant_types?: boolean | undefined;
@@ -16733,6 +16746,7 @@ declare const legacyClientSchema$1: z.ZodObject<{
16733
16746
  revoke_refresh_token_grant?: boolean | undefined;
16734
16747
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
16735
16748
  use_scope_descriptions_for_consent?: boolean | undefined;
16749
+ inherit_global_permissions_in_organizations?: boolean | undefined;
16736
16750
  }, {
16737
16751
  allow_changing_enable_sso?: boolean | undefined;
16738
16752
  allow_legacy_delegation_grant_types?: boolean | undefined;
@@ -16766,6 +16780,7 @@ declare const legacyClientSchema$1: z.ZodObject<{
16766
16780
  revoke_refresh_token_grant?: boolean | undefined;
16767
16781
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
16768
16782
  use_scope_descriptions_for_consent?: boolean | undefined;
16783
+ inherit_global_permissions_in_organizations?: boolean | undefined;
16769
16784
  }>>;
16770
16785
  sandbox_version: z.ZodOptional<z.ZodString>;
16771
16786
  legacy_sandbox_version: z.ZodOptional<z.ZodString>;
@@ -16927,6 +16942,7 @@ declare const legacyClientSchema$1: z.ZodObject<{
16927
16942
  revoke_refresh_token_grant?: boolean | undefined;
16928
16943
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
16929
16944
  use_scope_descriptions_for_consent?: boolean | undefined;
16945
+ inherit_global_permissions_in_organizations?: boolean | undefined;
16930
16946
  } | undefined;
16931
16947
  sandbox_version?: string | undefined;
16932
16948
  legacy_sandbox_version?: string | undefined;
@@ -17027,6 +17043,7 @@ declare const legacyClientSchema$1: z.ZodObject<{
17027
17043
  revoke_refresh_token_grant?: boolean | undefined;
17028
17044
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
17029
17045
  use_scope_descriptions_for_consent?: boolean | undefined;
17046
+ inherit_global_permissions_in_organizations?: boolean | undefined;
17030
17047
  } | undefined;
17031
17048
  sandbox_version?: string | undefined;
17032
17049
  legacy_sandbox_version?: string | undefined;
@@ -17417,6 +17434,7 @@ declare const legacyClientSchema$1: z.ZodObject<{
17417
17434
  revoke_refresh_token_grant?: boolean | undefined;
17418
17435
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
17419
17436
  use_scope_descriptions_for_consent?: boolean | undefined;
17437
+ inherit_global_permissions_in_organizations?: boolean | undefined;
17420
17438
  } | undefined;
17421
17439
  sandbox_version?: string | undefined;
17422
17440
  legacy_sandbox_version?: string | undefined;
@@ -17594,6 +17612,7 @@ declare const legacyClientSchema$1: z.ZodObject<{
17594
17612
  revoke_refresh_token_grant?: boolean | undefined;
17595
17613
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
17596
17614
  use_scope_descriptions_for_consent?: boolean | undefined;
17615
+ inherit_global_permissions_in_organizations?: boolean | undefined;
17597
17616
  } | undefined;
17598
17617
  sandbox_version?: string | undefined;
17599
17618
  legacy_sandbox_version?: string | undefined;
@@ -27304,6 +27323,7 @@ declare const tenantSchema$1: z.ZodObject<{
27304
27323
  revoke_refresh_token_grant: z.ZodOptional<z.ZodBoolean>;
27305
27324
  trust_azure_adfs_email_verified_connection_property: z.ZodOptional<z.ZodBoolean>;
27306
27325
  use_scope_descriptions_for_consent: z.ZodOptional<z.ZodBoolean>;
27326
+ inherit_global_permissions_in_organizations: z.ZodOptional<z.ZodBoolean>;
27307
27327
  }, "strip", z.ZodTypeAny, {
27308
27328
  allow_changing_enable_sso?: boolean | undefined;
27309
27329
  allow_legacy_delegation_grant_types?: boolean | undefined;
@@ -27337,6 +27357,7 @@ declare const tenantSchema$1: z.ZodObject<{
27337
27357
  revoke_refresh_token_grant?: boolean | undefined;
27338
27358
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
27339
27359
  use_scope_descriptions_for_consent?: boolean | undefined;
27360
+ inherit_global_permissions_in_organizations?: boolean | undefined;
27340
27361
  }, {
27341
27362
  allow_changing_enable_sso?: boolean | undefined;
27342
27363
  allow_legacy_delegation_grant_types?: boolean | undefined;
@@ -27370,6 +27391,7 @@ declare const tenantSchema$1: z.ZodObject<{
27370
27391
  revoke_refresh_token_grant?: boolean | undefined;
27371
27392
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
27372
27393
  use_scope_descriptions_for_consent?: boolean | undefined;
27394
+ inherit_global_permissions_in_organizations?: boolean | undefined;
27373
27395
  }>>;
27374
27396
  sandbox_version: z.ZodOptional<z.ZodString>;
27375
27397
  legacy_sandbox_version: z.ZodOptional<z.ZodString>;
@@ -27531,6 +27553,7 @@ declare const tenantSchema$1: z.ZodObject<{
27531
27553
  revoke_refresh_token_grant?: boolean | undefined;
27532
27554
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
27533
27555
  use_scope_descriptions_for_consent?: boolean | undefined;
27556
+ inherit_global_permissions_in_organizations?: boolean | undefined;
27534
27557
  } | undefined;
27535
27558
  sandbox_version?: string | undefined;
27536
27559
  legacy_sandbox_version?: string | undefined;
@@ -27631,6 +27654,7 @@ declare const tenantSchema$1: z.ZodObject<{
27631
27654
  revoke_refresh_token_grant?: boolean | undefined;
27632
27655
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
27633
27656
  use_scope_descriptions_for_consent?: boolean | undefined;
27657
+ inherit_global_permissions_in_organizations?: boolean | undefined;
27634
27658
  } | undefined;
27635
27659
  sandbox_version?: string | undefined;
27636
27660
  legacy_sandbox_version?: string | undefined;
@@ -30532,21 +30556,20 @@ export interface TenantRoleSyncConfig {
30532
30556
  */
30533
30557
  export declare function createTenantRoleSyncHooks(config: TenantRoleSyncConfig): TenantEntityHooks;
30534
30558
  /**
30535
- * Creates the tenant management routes.
30559
+ * Creates OpenAPI-based tenant management routes.
30536
30560
  *
30537
- * These routes handle CRUD operations for tenants and should be mounted
30538
- * on a management API path (e.g., /management/tenants).
30539
- *
30540
- * Access to these routes should be restricted to the control plane.
30561
+ * These routes handle CRUD operations for tenants and are designed to be
30562
+ * mounted on authhero's management API so they get the same authentication
30563
+ * middleware.
30541
30564
  *
30542
30565
  * @param config - Multi-tenancy configuration
30543
30566
  * @param hooks - Multi-tenancy hooks for lifecycle events
30544
- * @returns Hono router with tenant routes
30567
+ * @returns OpenAPIHono router with tenant routes
30545
30568
  */
30546
- export declare function createTenantsRouter(config: MultiTenancyConfig, hooks: MultiTenancyHooks): Hono<{
30569
+ export declare function createTenantsOpenAPIRouter(config: MultiTenancyConfig, hooks: MultiTenancyHooks): OpenAPIHono<{
30547
30570
  Bindings: MultiTenancyBindings;
30548
30571
  Variables: MultiTenancyVariables;
30549
- }, import("hono/types").BlankSchema, "/">;
30572
+ }, {}, "/">;
30550
30573
  /**
30551
30574
  * Bindings for the protect system middleware
30552
30575
  */
@@ -38910,6 +38933,7 @@ export declare function init(config: MultiTenantAuthHeroConfig): {
38910
38933
  revoke_refresh_token_grant?: boolean | undefined | undefined;
38911
38934
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined | undefined;
38912
38935
  use_scope_descriptions_for_consent?: boolean | undefined | undefined;
38936
+ inherit_global_permissions_in_organizations?: boolean | undefined | undefined;
38913
38937
  } | undefined;
38914
38938
  sandbox_version?: string | undefined | undefined;
38915
38939
  legacy_sandbox_version?: string | undefined | undefined;
@@ -39028,6 +39052,7 @@ export declare function init(config: MultiTenantAuthHeroConfig): {
39028
39052
  revoke_refresh_token_grant?: boolean | undefined;
39029
39053
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined;
39030
39054
  use_scope_descriptions_for_consent?: boolean | undefined;
39055
+ inherit_global_permissions_in_organizations?: boolean | undefined;
39031
39056
  } | undefined;
39032
39057
  sandbox_version?: string | undefined;
39033
39058
  legacy_sandbox_version?: string | undefined;
@@ -39127,6 +39152,7 @@ export declare function init(config: MultiTenantAuthHeroConfig): {
39127
39152
  revoke_refresh_token_grant?: boolean | undefined | undefined;
39128
39153
  trust_azure_adfs_email_verified_connection_property?: boolean | undefined | undefined;
39129
39154
  use_scope_descriptions_for_consent?: boolean | undefined | undefined;
39155
+ inherit_global_permissions_in_organizations?: boolean | undefined | undefined;
39130
39156
  } | undefined;
39131
39157
  sandbox_version?: string | undefined | undefined;
39132
39158
  legacy_sandbox_version?: string | undefined | undefined;