@authhero/multi-tenancy 13.11.0 → 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 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 j=(e,t,s)=>H(e,typeof t!="symbol"?t+"":t,s);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const N=require("hono"),b=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});j(this,"res");j(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 B(e){return{async beforeCreate(t,s){return!s.audience&&s.id?{...s,audience:b.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 te(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 ee(e,a,l,c)),r&&e.ctx){const o=e.ctx.var.user;if(o!=null&&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(p){console.warn(`Failed to add creator ${o.sub} to organization ${f.id}:`,p)}}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,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=b.MANAGEMENT_API_AUDIENCE,c=b.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 te(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 W(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 G(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 b.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 b.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 D(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,M=(await b.fetchAll(R=>a.env.data.userOrganizations.listUserOrganizations(S,r.sub,R),"organizations")).map(R=>R.name);if(M.length===0)return l?a.json({tenants:[],start:0,limit:u??50,length:0}):a.json({tenants:[]});const $=M.length,F=n??0,P=u??50,w=F*P,m=M.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(R=>`id:${R}`).join(" OR "),_=c?`(${y}) AND (${c})`:y,T=await a.env.data.tenants.list({q:_,per_page:P,include_totals:!1});return l?a.json({tenants:T.tenants,start:w,limit:P,length:$}):a.json({tenants:T.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 b.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 ae(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 ne(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 re(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=ae(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 ne(e.env.data,a,s))throw new v(403,{message:`This ${re(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 q(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 se(e){const t=z(e);return{name:"multi-tenancy",middleware:q(e),hooks:t,routes:[{path:"/management",handler:D(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=B(e);return{...t,...s,tenants:a}}function Y(e){const t=new N.Hono,s=z(e);return t.route("/tenants",D(e,s)),t}function ie(e){return{hooks:z(e),middleware:q(e),app:Y(e),config:e}}function oe(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=W({controlPlaneTenantId:t,getChildTenantIds:async()=>(await b.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=G({controlPlaneTenantId:t,getControlPlaneAdapters:async()=>e.dataAdapter,getAdapters:async w=>e.dataAdapter}));let d,o;a&&(d=L({controlPlaneTenantId:t,getChildTenantIds:async()=>(await b.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(T){_.push(T instanceof Error?T:new Error(String(T)))}if(m)try{await m(...y)}catch(T){_.push(T instanceof Error?T:new Error(String(T)))}if(_.length===1)throw _[0];if(_.length>1)throw new AggregateError(_,`Multiple hook errors: ${_.map(T=>T.message).join("; ")}`)},g=async(w,...m)=>{const y=[];for(const _ of w)if(_)try{await _(...m)}catch(T){y.push(T instanceof Error?T:new Error(String(T)))}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=D(l,A),O=b.init({...u,entityHooks:h,managementApiExtensions:[...u.managementApiExtensions||[],{path:"/tenants",router:S}]}),{app:M,managementApp:$,...F}=O,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("/",M),{app:P,managementApp:$,...F,multiTenancyConfig:l,multiTenancyHooks:c}}Object.defineProperty(exports,"MANAGEMENT_API_SCOPES",{enumerable:!0,get:()=>b.MANAGEMENT_API_SCOPES});Object.defineProperty(exports,"fetchAll",{enumerable:!0,get:()=>b.fetchAll});Object.defineProperty(exports,"seed",{enumerable:!0,get:()=>b.seed});exports.createAccessControlHooks=U;exports.createAccessControlMiddleware=k;exports.createDatabaseHooks=K;exports.createDatabaseMiddleware=X;exports.createMultiTenancy=Y;exports.createMultiTenancyHooks=z;exports.createMultiTenancyMiddleware=q;exports.createMultiTenancyPlugin=se;exports.createProtectSyncedMiddleware=V;exports.createProvisioningHooks=B;exports.createResourceServerSyncHooks=W;exports.createRoleSyncHooks=L;exports.createSubdomainMiddleware=J;exports.createTenantResourceServerSyncHooks=G;exports.createTenantRoleSyncHooks=Q;exports.createTenantsOpenAPIRouter=D;exports.init=oe;exports.setupMultiTenancy=ie;exports.validateTenantAccess=E;
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;
@@ -2,11 +2,11 @@ var K = Object.defineProperty;
2
2
  var E = (e, t, s) => t in e ? K(e, t, { enumerable: !0, configurable: !0, writable: !0, value: s }) : e[t] = s;
3
3
  var D = (e, t, s) => E(e, typeof t != "symbol" ? t + "" : t, s);
4
4
  import { Hono as U } from "hono";
5
- import { getTenantAudience as B, MANAGEMENT_API_SCOPES as W, MANAGEMENT_API_AUDIENCE as G, fetchAll as S, init as L } from "authhero";
6
- import { MANAGEMENT_API_SCOPES as ve, fetchAll as be, seed as Pe } from "authhero";
5
+ import { getTenantAudience as G, MANAGEMENT_API_SCOPES as B, MANAGEMENT_API_AUDIENCE as W, fetchAll as S, init as L } from "authhero";
6
+ import { MANAGEMENT_API_SCOPES as Ce, fetchAll as Pe, seed as Se } from "authhero";
7
7
  import { OpenAPIHono as Q, createRoute as M, z as P } from "@hono/zod-openapi";
8
- import { auth0QuerySchema as V, tenantSchema as O, tenantInsertSchema as J } from "@authhero/adapter-interfaces";
9
- var C = class extends Error {
8
+ import { auth0QuerySchema as V, tenantSchema as q, tenantInsertSchema as J } from "@authhero/adapter-interfaces";
9
+ var T = class extends Error {
10
10
  /**
11
11
  * Creates an instance of `HTTPException`.
12
12
  * @param status - HTTP status code for the exception. Defaults to 500.
@@ -72,12 +72,12 @@ function k(e) {
72
72
  async beforeCreate(t, s) {
73
73
  return !s.audience && s.id ? {
74
74
  ...s,
75
- audience: B(s.id)
75
+ audience: G(s.id)
76
76
  } : s;
77
77
  },
78
78
  async afterCreate(t, s) {
79
79
  const { accessControl: a, databaseIsolation: i, settingsInheritance: n } = e;
80
- a && t.ctx && await H(t, s, a), i != null && i.onProvision && await i.onProvision(s.id), (n == null ? void 0 : n.inheritFromControlPlane) !== !1 && t.ctx && await ee(t, s, e);
80
+ a && t.ctx && await H(t, s, a), i != null && i.onProvision && await i.onProvision(s.id), (n == null ? void 0 : n.inheritFromControlPlane) !== !1 && t.ctx && await te(t, s, e);
81
81
  },
82
82
  async beforeDelete(t, s) {
83
83
  const { accessControl: a, databaseIsolation: i } = e;
@@ -125,14 +125,18 @@ async function H(e, t, s) {
125
125
  }
126
126
  );
127
127
  let d;
128
- if (u && (d = await x(
128
+ if (u && (d = await ee(
129
129
  e,
130
130
  a,
131
131
  l,
132
132
  c
133
133
  )), r && e.ctx) {
134
134
  const o = e.ctx.var.user;
135
- if (o != null && o.sub)
135
+ if (o != null && o.sub && !await x(
136
+ e,
137
+ a,
138
+ o.sub
139
+ ))
136
140
  try {
137
141
  await e.adapters.userOrganizations.create(a, {
138
142
  user_id: o.sub,
@@ -144,10 +148,10 @@ async function H(e, t, s) {
144
148
  f.id
145
149
  // organizationId
146
150
  );
147
- } catch (p) {
151
+ } catch (g) {
148
152
  console.warn(
149
153
  `Failed to add creator ${o.sub} to organization ${f.id}:`,
150
- p
154
+ g
151
155
  );
152
156
  }
153
157
  }
@@ -157,14 +161,33 @@ async function H(e, t, s) {
157
161
  `Would grant permissions ${i.join(", ")} to organization ${f.id}`
158
162
  );
159
163
  }
160
- async function x(e, t, s, a) {
164
+ async function x(e, t, s) {
165
+ const a = await e.adapters.userRoles.list(
166
+ t,
167
+ s,
168
+ void 0,
169
+ ""
170
+ // Empty string for global roles
171
+ );
172
+ for (const i of a)
173
+ if ((await e.adapters.rolePermissions.list(
174
+ t,
175
+ i.id,
176
+ { per_page: 1e3 }
177
+ )).some(
178
+ (l) => l.permission_name === "admin:organizations"
179
+ ))
180
+ return !0;
181
+ return !1;
182
+ }
183
+ async function ee(e, t, s, a) {
161
184
  const n = (await e.adapters.roles.list(t, {})).roles.find((r) => r.name === s);
162
185
  if (n)
163
186
  return n.id;
164
187
  const u = await e.adapters.roles.create(t, {
165
188
  name: s,
166
189
  description: a
167
- }), l = G, c = W.map((r) => ({
190
+ }), l = W, c = B.map((r) => ({
168
191
  role_id: u.id,
169
192
  resource_server_identifier: l,
170
193
  permission_name: r.value
@@ -175,7 +198,7 @@ async function x(e, t, s, a) {
175
198
  c
176
199
  ), u.id;
177
200
  }
178
- async function ee(e, t, s) {
201
+ async function te(e, t, s) {
179
202
  const { accessControl: a, settingsInheritance: i } = s;
180
203
  if (!a)
181
204
  return;
@@ -211,7 +234,7 @@ async function ee(e, t, s) {
211
234
  t.id
212
235
  )), Object.keys(u).length > 0 && await e.adapters.tenants.update(t.id, u);
213
236
  }
214
- function te(e) {
237
+ function ae(e) {
215
238
  const {
216
239
  controlPlaneTenantId: t,
217
240
  getChildTenantIds: s,
@@ -244,25 +267,25 @@ function te(e) {
244
267
  options: r.options
245
268
  }, is_system: !0 };
246
269
  if (f === "create") {
247
- const T = await u(
270
+ const A = await u(
248
271
  p,
249
272
  o,
250
273
  r.identifier
251
274
  );
252
- T && T.id ? await p.resourceServers.update(
275
+ A && A.id ? await p.resourceServers.update(
253
276
  o,
254
- T.id,
277
+ A.id,
255
278
  h
256
279
  ) : await p.resourceServers.create(o, h);
257
280
  } else {
258
- const T = await u(
281
+ const A = await u(
259
282
  p,
260
283
  o,
261
284
  r.identifier
262
285
  );
263
- T && T.id ? await p.resourceServers.update(
286
+ A && A.id ? await p.resourceServers.update(
264
287
  o,
265
- T.id,
288
+ A.id,
266
289
  h
267
290
  ) : await p.resourceServers.create(o, h);
268
291
  }
@@ -307,7 +330,7 @@ function te(e) {
307
330
  }
308
331
  };
309
332
  }
310
- function ae(e) {
333
+ function ne(e) {
311
334
  const {
312
335
  controlPlaneTenantId: t,
313
336
  getControlPlaneAdapters: s,
@@ -365,7 +388,7 @@ function ae(e) {
365
388
  }
366
389
  };
367
390
  }
368
- function ne(e) {
391
+ function re(e) {
369
392
  const {
370
393
  controlPlaneTenantId: t,
371
394
  getChildTenantIds: s,
@@ -426,7 +449,7 @@ function ne(e) {
426
449
  }
427
450
  };
428
451
  }
429
- function re(e) {
452
+ function se(e) {
430
453
  const {
431
454
  controlPlaneTenantId: t,
432
455
  getControlPlaneAdapters: s,
@@ -451,11 +474,11 @@ function re(e) {
451
474
  const h = n ? n(g, c.id) : {
452
475
  name: g.name,
453
476
  description: g.description
454
- }, T = await f.roles.create(c.id, {
477
+ }, A = await f.roles.create(c.id, {
455
478
  ...h,
456
479
  is_system: !0
457
480
  });
458
- o.set(g.id, T.id);
481
+ o.set(g.id, A.id);
459
482
  } catch (h) {
460
483
  console.error(
461
484
  `Failed to sync role "${g.name}" to new tenant "${c.id}":`,
@@ -474,10 +497,10 @@ function re(e) {
474
497
  h.length > 0 && await f.rolePermissions.assign(
475
498
  c.id,
476
499
  g,
477
- h.map((T) => ({
500
+ h.map((A) => ({
478
501
  role_id: g,
479
- resource_server_identifier: T.resource_server_identifier,
480
- permission_name: T.permission_name
502
+ resource_server_identifier: A.resource_server_identifier,
503
+ permission_name: A.permission_name
481
504
  }))
482
505
  );
483
506
  } catch (h) {
@@ -495,7 +518,7 @@ function re(e) {
495
518
  }
496
519
  };
497
520
  }
498
- function j(e, t) {
521
+ function O(e, t) {
499
522
  const s = new Q();
500
523
  return s.openapi(
501
524
  M({
@@ -515,7 +538,7 @@ function j(e, t) {
515
538
  content: {
516
539
  "application/json": {
517
540
  schema: P.object({
518
- tenants: P.array(O),
541
+ tenants: P.array(q),
519
542
  start: P.number().optional(),
520
543
  limit: P.number().optional(),
521
544
  length: P.number().optional()
@@ -527,26 +550,26 @@ function j(e, t) {
527
550
  }
528
551
  }),
529
552
  async (a) => {
530
- var p, g, h, T;
553
+ var p, g, h, A;
531
554
  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");
532
555
  if (console.log("User scopes:", f, "hasAuthRead:", d), d) {
533
- const b = await a.env.data.tenants.list({
556
+ const C = await a.env.data.tenants.list({
534
557
  page: n,
535
558
  per_page: u,
536
559
  include_totals: l,
537
560
  q: c
538
561
  });
539
562
  return l ? a.json({
540
- tenants: b.tenants,
541
- start: ((p = b.totals) == null ? void 0 : p.start) ?? 0,
542
- limit: ((g = b.totals) == null ? void 0 : g.limit) ?? u,
543
- length: b.tenants.length
544
- }) : a.json({ tenants: b.tenants });
563
+ tenants: C.tenants,
564
+ start: ((p = C.totals) == null ? void 0 : p.start) ?? 0,
565
+ limit: ((g = C.totals) == null ? void 0 : g.limit) ?? u,
566
+ length: C.tenants.length
567
+ }) : a.json({ tenants: C.tenants });
545
568
  }
546
569
  if (e.accessControl && (r != null && r.sub)) {
547
- const b = e.accessControl.controlPlaneTenantId, $ = (await S(
570
+ const C = e.accessControl.controlPlaneTenantId, $ = (await S(
548
571
  (R) => a.env.data.userOrganizations.listUserOrganizations(
549
- b,
572
+ C,
550
573
  r.sub,
551
574
  R
552
575
  ),
@@ -567,18 +590,18 @@ function j(e, t) {
567
590
  limit: v,
568
591
  length: z
569
592
  }) : a.json({ tenants: [] });
570
- const y = m.map((R) => `id:${R}`).join(" OR "), _ = c ? `(${y}) AND (${c})` : y, A = await a.env.data.tenants.list({
593
+ const y = m.map((R) => `id:${R}`).join(" OR "), _ = c ? `(${y}) AND (${c})` : y, b = await a.env.data.tenants.list({
571
594
  q: _,
572
595
  per_page: v,
573
596
  include_totals: !1
574
597
  // We calculate totals from accessibleTenantIds
575
598
  });
576
599
  return l ? a.json({
577
- tenants: A.tenants,
600
+ tenants: b.tenants,
578
601
  start: w,
579
602
  limit: v,
580
603
  length: z
581
- }) : a.json({ tenants: A.tenants });
604
+ }) : a.json({ tenants: b.tenants });
582
605
  }
583
606
  const o = await a.env.data.tenants.list({
584
607
  page: n,
@@ -589,7 +612,7 @@ function j(e, t) {
589
612
  return l ? a.json({
590
613
  tenants: o.tenants,
591
614
  start: ((h = o.totals) == null ? void 0 : h.start) ?? 0,
592
- limit: ((T = o.totals) == null ? void 0 : T.limit) ?? u,
615
+ limit: ((A = o.totals) == null ? void 0 : A.limit) ?? u,
593
616
  length: o.tenants.length
594
617
  }) : a.json({ tenants: o.tenants });
595
618
  }
@@ -616,7 +639,7 @@ function j(e, t) {
616
639
  201: {
617
640
  content: {
618
641
  "application/json": {
619
- schema: O
642
+ schema: q
620
643
  }
621
644
  },
622
645
  description: "Tenant created"
@@ -633,7 +656,7 @@ function j(e, t) {
633
656
  var c, r;
634
657
  const i = a.var.user;
635
658
  if (!(i != null && i.sub))
636
- throw new C(401, {
659
+ throw new T(401, {
637
660
  message: "Authentication required to create tenants"
638
661
  });
639
662
  let n = a.req.valid("json");
@@ -678,11 +701,11 @@ function j(e, t) {
678
701
  if (e.accessControl) {
679
702
  const r = a.var.user, f = e.accessControl.controlPlaneTenantId;
680
703
  if (!(r != null && r.sub))
681
- throw new C(401, {
704
+ throw new T(401, {
682
705
  message: "Authentication required"
683
706
  });
684
707
  if (i === f)
685
- throw new C(403, {
708
+ throw new T(403, {
686
709
  message: "Cannot delete the control plane"
687
710
  });
688
711
  if (!(await S(
@@ -693,12 +716,12 @@ function j(e, t) {
693
716
  ),
694
717
  "organizations"
695
718
  )).some((p) => p.name === i))
696
- throw new C(403, {
719
+ throw new T(403, {
697
720
  message: "Access denied to this tenant"
698
721
  });
699
722
  }
700
723
  if (!await a.env.data.tenants.get(i))
701
- throw new C(404, {
724
+ throw new T(404, {
702
725
  message: "Tenant not found"
703
726
  });
704
727
  const u = {
@@ -709,7 +732,7 @@ function j(e, t) {
709
732
  }
710
733
  ), s;
711
734
  }
712
- function se(e) {
735
+ function ie(e) {
713
736
  const t = [
714
737
  {
715
738
  pattern: /\/api\/v2\/resource-servers\/([^/]+)$/,
@@ -725,7 +748,7 @@ function se(e) {
725
748
  }
726
749
  return null;
727
750
  }
728
- async function ie(e, t, s) {
751
+ async function oe(e, t, s) {
729
752
  try {
730
753
  switch (s.type) {
731
754
  case "resource_server": {
@@ -747,37 +770,37 @@ async function ie(e, t, s) {
747
770
  return !1;
748
771
  }
749
772
  }
750
- function oe(e) {
773
+ function ce(e) {
751
774
  return {
752
775
  resource_server: "resource server",
753
776
  role: "role",
754
777
  connection: "connection"
755
778
  }[e];
756
779
  }
757
- function ce() {
780
+ function le() {
758
781
  return async (e, t) => {
759
782
  if (!["PATCH", "PUT", "DELETE"].includes(e.req.method))
760
783
  return t();
761
- const s = se(e.req.path);
784
+ const s = ie(e.req.path);
762
785
  if (!s)
763
786
  return t();
764
787
  const a = e.var.tenant_id || e.req.header("x-tenant-id") || e.req.header("tenant-id");
765
788
  if (!a)
766
789
  return t();
767
- if (await ie(e.env.data, a, s))
768
- throw new C(403, {
769
- message: `This ${oe(s.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`
790
+ if (await oe(e.env.data, a, s))
791
+ throw new T(403, {
792
+ message: `This ${ce(s.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`
770
793
  });
771
794
  return t();
772
795
  };
773
796
  }
774
- function le(e) {
797
+ function de(e) {
775
798
  return async (t, s) => {
776
799
  if (!e.accessControl)
777
800
  return s();
778
801
  const a = t.var.tenant_id, i = t.var.organization_id;
779
802
  if (!a)
780
- throw new C(400, {
803
+ throw new T(400, {
781
804
  message: "Tenant ID not found in request"
782
805
  });
783
806
  if (!Y(
@@ -785,13 +808,13 @@ function le(e) {
785
808
  a,
786
809
  e.accessControl.controlPlaneTenantId
787
810
  ))
788
- throw new C(403, {
811
+ throw new T(403, {
789
812
  message: `Access denied to tenant ${a}`
790
813
  });
791
814
  return s();
792
815
  };
793
816
  }
794
- function de(e) {
817
+ function ue(e) {
795
818
  return async (t, s) => {
796
819
  if (!e.subdomainRouting)
797
820
  return s();
@@ -820,19 +843,19 @@ function de(e) {
820
843
  } catch {
821
844
  }
822
845
  if (!c)
823
- throw new C(404, {
846
+ throw new T(404, {
824
847
  message: `Tenant not found for subdomain: ${l}`
825
848
  });
826
849
  return t.set("tenant_id", c), s();
827
850
  };
828
851
  }
829
- function ue(e) {
852
+ function fe(e) {
830
853
  return async (t, s) => {
831
854
  if (!e.databaseIsolation)
832
855
  return s();
833
856
  const a = t.var.tenant_id;
834
857
  if (!a)
835
- throw new C(400, {
858
+ throw new T(400, {
836
859
  message: "Tenant ID not found in request"
837
860
  });
838
861
  try {
@@ -842,7 +865,7 @@ function ue(e) {
842
865
  throw console.error(
843
866
  `Failed to resolve database for tenant ${a}:`,
844
867
  i
845
- ), new C(500, {
868
+ ), new T(500, {
846
869
  message: "Failed to resolve tenant database"
847
870
  });
848
871
  }
@@ -850,13 +873,13 @@ function ue(e) {
850
873
  };
851
874
  }
852
875
  function N(e) {
853
- const t = de(e), s = le(e), a = ue(e);
876
+ const t = ue(e), s = de(e), a = fe(e);
854
877
  return async (i, n) => (await t(i, async () => {
855
878
  }), await s(i, async () => {
856
879
  }), await a(i, async () => {
857
880
  }), n());
858
881
  }
859
- function ge(e) {
882
+ function _e(e) {
860
883
  const t = I(e);
861
884
  return {
862
885
  name: "multi-tenancy",
@@ -868,7 +891,7 @@ function ge(e) {
868
891
  routes: [
869
892
  {
870
893
  path: "/management",
871
- handler: j(e, t)
894
+ handler: O(e, t)
872
895
  }
873
896
  ],
874
897
  // Called when plugin is registered
@@ -889,19 +912,19 @@ function I(e) {
889
912
  tenants: a
890
913
  };
891
914
  }
892
- function fe(e) {
915
+ function pe(e) {
893
916
  const t = new U(), s = I(e);
894
- return t.route("/tenants", j(e, s)), t;
917
+ return t.route("/tenants", O(e, s)), t;
895
918
  }
896
- function _e(e) {
919
+ function Ae(e) {
897
920
  return {
898
921
  hooks: I(e),
899
922
  middleware: N(e),
900
- app: fe(e),
923
+ app: pe(e),
901
924
  config: e
902
925
  };
903
926
  }
904
- function Te(e) {
927
+ function be(e) {
905
928
  const {
906
929
  controlPlaneTenantId: t = "control_plane",
907
930
  syncResourceServers: s = !0,
@@ -919,7 +942,7 @@ function Te(e) {
919
942
  }
920
943
  }, c = I(l);
921
944
  let r, f;
922
- s && (r = te({
945
+ s && (r = ae({
923
946
  controlPlaneTenantId: t,
924
947
  getChildTenantIds: async () => (await S(
925
948
  (m) => e.dataAdapter.tenants.list(m),
@@ -927,13 +950,13 @@ function Te(e) {
927
950
  { cursorField: "id", pageSize: 100 }
928
951
  )).filter((m) => m.id !== t).map((m) => m.id),
929
952
  getAdapters: async (w) => e.dataAdapter
930
- }), f = ae({
953
+ }), f = ne({
931
954
  controlPlaneTenantId: t,
932
955
  getControlPlaneAdapters: async () => e.dataAdapter,
933
956
  getAdapters: async (w) => e.dataAdapter
934
957
  }));
935
958
  let d, o;
936
- a && (d = ne({
959
+ a && (d = re({
937
960
  controlPlaneTenantId: t,
938
961
  getChildTenantIds: async () => (await S(
939
962
  (m) => e.dataAdapter.tenants.list(m),
@@ -941,7 +964,7 @@ function Te(e) {
941
964
  { cursorField: "id", pageSize: 100 }
942
965
  )).filter((m) => m.id !== t).map((m) => m.id),
943
966
  getAdapters: async (w) => e.dataAdapter
944
- }), o = re({
967
+ }), o = se({
945
968
  controlPlaneTenantId: t,
946
969
  getControlPlaneAdapters: async () => e.dataAdapter,
947
970
  getAdapters: async (w) => e.dataAdapter,
@@ -952,21 +975,21 @@ function Te(e) {
952
975
  if (w)
953
976
  try {
954
977
  await w(...y);
955
- } catch (A) {
956
- _.push(A instanceof Error ? A : new Error(String(A)));
978
+ } catch (b) {
979
+ _.push(b instanceof Error ? b : new Error(String(b)));
957
980
  }
958
981
  if (m)
959
982
  try {
960
983
  await m(...y);
961
- } catch (A) {
962
- _.push(A instanceof Error ? A : new Error(String(A)));
984
+ } catch (b) {
985
+ _.push(b instanceof Error ? b : new Error(String(b)));
963
986
  }
964
987
  if (_.length === 1)
965
988
  throw _[0];
966
989
  if (_.length > 1)
967
990
  throw new AggregateError(
968
991
  _,
969
- `Multiple hook errors: ${_.map((A) => A.message).join("; ")}`
992
+ `Multiple hook errors: ${_.map((b) => b.message).join("; ")}`
970
993
  );
971
994
  }, g = async (w, ...m) => {
972
995
  const y = [];
@@ -974,9 +997,9 @@ function Te(e) {
974
997
  if (_)
975
998
  try {
976
999
  await _(...m);
977
- } catch (A) {
1000
+ } catch (b) {
978
1001
  y.push(
979
- A instanceof Error ? A : new Error(String(A))
1002
+ b instanceof Error ? b : new Error(String(b))
980
1003
  );
981
1004
  }
982
1005
  if (y.length === 1)
@@ -1065,7 +1088,7 @@ function Te(e) {
1065
1088
  );
1066
1089
  }
1067
1090
  } : n == null ? void 0 : n.tenants
1068
- }, T = {
1091
+ }, A = {
1069
1092
  ...c,
1070
1093
  tenants: f || o ? {
1071
1094
  ...c.tenants,
@@ -1081,20 +1104,20 @@ function Te(e) {
1081
1104
  );
1082
1105
  }
1083
1106
  } : c.tenants
1084
- }, b = j(
1107
+ }, C = O(
1085
1108
  l,
1086
- T
1087
- ), q = L({
1109
+ A
1110
+ ), j = L({
1088
1111
  ...u,
1089
1112
  entityHooks: h,
1090
1113
  // Register tenant routes via the extension mechanism
1091
1114
  // This ensures they go through the full middleware chain (caching, tenant, auth, entity hooks)
1092
1115
  managementApiExtensions: [
1093
1116
  ...u.managementApiExtensions || [],
1094
- { path: "/tenants", router: b }
1117
+ { path: "/tenants", router: C }
1095
1118
  ]
1096
- }), { app: $, managementApp: z, ...F } = q, v = new U();
1097
- return v.onError((w, m) => w instanceof C ? w.getResponse() : (console.error(w), m.json({ message: "Internal Server Error" }, 500))), v.use("/api/v2/*", ce()), v.route("/", $), {
1119
+ }), { app: $, managementApp: z, ...F } = j, v = new U();
1120
+ return v.onError((w, m) => w instanceof T ? w.getResponse() : (console.error(w), m.json({ message: "Internal Server Error" }, 500))), v.use("/api/v2/*", le()), v.route("/", $), {
1098
1121
  app: v,
1099
1122
  managementApp: z,
1100
1123
  ...F,
@@ -1103,26 +1126,26 @@ function Te(e) {
1103
1126
  };
1104
1127
  }
1105
1128
  export {
1106
- ve as MANAGEMENT_API_SCOPES,
1129
+ Ce as MANAGEMENT_API_SCOPES,
1107
1130
  X as createAccessControlHooks,
1108
- le as createAccessControlMiddleware,
1131
+ de as createAccessControlMiddleware,
1109
1132
  Z as createDatabaseHooks,
1110
- ue as createDatabaseMiddleware,
1111
- fe as createMultiTenancy,
1133
+ fe as createDatabaseMiddleware,
1134
+ pe as createMultiTenancy,
1112
1135
  I as createMultiTenancyHooks,
1113
1136
  N as createMultiTenancyMiddleware,
1114
- ge as createMultiTenancyPlugin,
1115
- ce as createProtectSyncedMiddleware,
1137
+ _e as createMultiTenancyPlugin,
1138
+ le as createProtectSyncedMiddleware,
1116
1139
  k as createProvisioningHooks,
1117
- te as createResourceServerSyncHooks,
1118
- ne as createRoleSyncHooks,
1119
- de as createSubdomainMiddleware,
1120
- ae as createTenantResourceServerSyncHooks,
1121
- re as createTenantRoleSyncHooks,
1122
- j as createTenantsOpenAPIRouter,
1123
- be as fetchAll,
1124
- Te as init,
1125
- Pe as seed,
1126
- _e as setupMultiTenancy,
1140
+ ae as createResourceServerSyncHooks,
1141
+ re as createRoleSyncHooks,
1142
+ ue as createSubdomainMiddleware,
1143
+ ne as createTenantResourceServerSyncHooks,
1144
+ se as createTenantRoleSyncHooks,
1145
+ O as createTenantsOpenAPIRouter,
1146
+ Pe as fetchAll,
1147
+ be as init,
1148
+ Se as seed,
1149
+ Ae as setupMultiTenancy,
1127
1150
  Y as validateTenantAccess
1128
1151
  };
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "type": "git",
12
12
  "url": "https://github.com/markusahlstrand/authhero"
13
13
  },
14
- "version": "13.11.0",
14
+ "version": "13.12.0",
15
15
  "description": "Multi-tenancy support for AuthHero with organization-based access control and per-tenant database isolation",
16
16
  "files": [
17
17
  "dist"
@@ -42,7 +42,7 @@
42
42
  "dependencies": {
43
43
  "zod": "^3.24.0",
44
44
  "@authhero/adapter-interfaces": "0.114.0",
45
- "authhero": "1.1.0"
45
+ "authhero": "1.2.0"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "@hono/zod-openapi": "^0.19.10",