@ionite/core 0.0.24-beta.20260922.9 → 0.0.24-beta.20260927.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.js CHANGED
@@ -1 +1 @@
1
- import{E,o,h,S,b,r,i,U,u,e,d,A,I,v,j,x,n,c,_,O,z,te,w,N,L,l,a,t,D,C,p,P,m,T,Z,le,s,f,g,q,K}from"./shared/core-j5xhxcmq.js";var Er="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.",Yn=["user","customer","workload"],Mr={user:async(y,k)=>k.sso?.getUser(y),customer:async(y,k)=>k.ciam?.getCustomer(y),workload:async(y,k)=>{let R=await k.workload?.getWorkloadIdentity?.(y);if(!R)return;let W=R.clientId??R.workloadId??R.claims.sub;return W?{...R,id:W}:void 0}};function jr(y){if(y==="any")return Yn;let k=Array.isArray(y)?y:[y];return Yn.filter((R)=>k.includes(R))}function _r(y){let k=y.headers.get("cookie");if(!k)return[];return k.split(";").map((R)=>R.slice(0,R.indexOf("=")===-1?R.length:R.indexOf("=")).trim()).filter(Boolean)}function Or(y,k){let R=y.headers.get("authorization")?.toLowerCase().startsWith("bearer ")??!1,W=_r(y),V=new Set;for(let H of W){if(H.startsWith("ion.sso"))V.add("user");if(H.startsWith("ion.ciam"))V.add("customer")}let G=W.length>0&&!V.has("user")&&!V.has("customer");return k.filter((H)=>{if(H==="workload")return R;if(W.length===0)return!1;return V.has(H)||G})}function Be(y){return typeof y==="string"?y:y.id}function Xn(y){let{subject:k,subjectType:R}=y,W;if(R==="user")W=k.sso?.scope;else if(R==="customer")W=k.ciam?.scope;else if(R==="workload")W=k.scope;return new Set((W??"").split(/\s+/).filter(Boolean))}function fn(y,k,R){let W=Xn(y),V=k.filter((H)=>W.has(H));return{allow:R==="any"?V.length>0:k.length>0&&V.length===k.length,metadata:{reason:"scope",wantedScopes:k,matchedScopes:V}}}function Mt(y,k){return(R)=>{if(y.length===0)return;let W=Xn(R),V=y.filter((H)=>W.has(H));return(k==="any"?V.length>0:V.length===y.length)?V:void 0}}function Xt(y,k,R){return(W)=>{if(k.length===0||W.subjectType!=="workload")return;let V=E(y.config?.authz,W.subject);if(!V)return;let G=k.filter((Y)=>V.has(Y));return(R==="any"?G.length>0:G.length===k.length)?G:void 0}}function Dr(y,k){if(y.subjectType==="workload"){let R=y.subject.scopesAsEntitlements;if(typeof R==="boolean")return R}return k.config?.authz?.scopesAsEntitlements===!0}function mn(y,k,R,W,V){return{allow:R==="ok",subject:k?.subject,subjectType:k?.subjectType,reason:R,decision:W,response(){if(R==="ok")return new Response(null,{status:204});if(R==="unauthenticated")return y.log.warn("authz.denied",{reason:R,...V()}),Response.json({error:"Unauthorized"},{status:401});if(R==="not_configured")return y.log.warn("authz.denied",{reason:R,subject:k?.subject?.id,subjectType:k?.subjectType,...V()}),Response.json({error:"not_configured"},{status:503});return y.log.warn("authz.denied",{reason:R,subject:k?.subject?.id,subjectType:k?.subjectType,...V()}),Response.json({error:"Forbidden"},{status:403})}}}function Lr(y,k,R){return new Promise((W)=>{let V=[],G=y.length,H=!1,Y=()=>{if(G-=1,G===0&&!H)H=!0,W({outcomes:V})};for(let Q of y)k(Q).then((X)=>{if(V.push({principal:Q,decision:X}),!H&&X.allow){H=!0,W({matched:{principal:Q,decision:X},outcomes:V});return}Y()},(X)=>{R?.(Q,X),V.push({principal:Q,decision:{allow:!1,metadata:{reason:"error"}}}),Y()})})}async function pt(y,k,R,W,V,G,H){t(k,Er);let Y=Or(y,jr(R)),X=(await Promise.all(Y.map(async(ye)=>{let _e=await Mr[ye](y,k);return _e?.id?{subject:_e,subjectType:ye,subjectId:_e.id}:void 0}))).filter((ye)=>ye!==void 0);if(X.length===0)return mn(k,void 0,"unauthenticated",void 0,V);let Pe=async(ye)=>{let _e=k.authz.accessIndex;if(!_e?.isSubjectDisabled)return!1;return _e.isSubjectDisabled(ye.subjectId,ye.subjectType)},xe=async(ye)=>{if(H){let _e=H(ye);if(_e&&_e.length>0){if(await Pe(ye))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"trusted-client",matchedPermissions:_e}}}}if(G&&Dr(ye,k)){let _e=G(ye);if(_e&&_e.length>0){if(await Pe(ye))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"scope",matchedScopes:_e}}}}return W(ye)},{matched:je,outcomes:De}=await Lr(X,xe,(ye,_e)=>{k.log.warn("authz.check_error",{"ion.operation":"authz.check","ion.outcome":"error",subject:ye.subjectId,subjectType:ye.subjectType,error:_e instanceof Error?_e.message:String(_e),...V()})});if(je){if(je.decision.metadata?.reason==="scope")k.log.info("authz.scope_honor",{"ion.operation":"authz.scope_honor","ion.outcome":"allow",subject:je.principal.subjectId,subjectType:je.principal.subjectType,matchedScopes:je.decision.metadata.matchedScopes,...V()});return mn(k,je.principal,"ok",je.decision,V)}let We=De.length>0&&De.every((ye)=>{let _e=ye.decision.metadata?.reason;return _e==="access_index_not_configured"||_e==="error"}),ke=De[0],Le=We?"not_configured":"forbidden";return mn(k,ke?.principal,Le,ke?.decision,V)}async function Nr(y,k,R,W,V,G="any"){return pt(y,k,G,(H)=>k.authz.has(H.subjectId,R,W,V,H.subjectType),()=>({targetType:R,target:Be(W),resource:V?Be(V):void 0}),V?void 0:Mt([Be(W)],"any"),R==="permission"&&!V?Xt(k,[Be(W)],"any"):void 0)}async function Wr(y,k,R,W,V="any"){return pt(y,k,V,(G)=>k.authz.hasPermission(G.subjectId,R,W,G.subjectType),()=>({targetType:"permission",target:Be(R),resource:W?Be(W):void 0}),W?void 0:Mt([Be(R)],"any"),W?void 0:Xt(k,[Be(R)],"any"))}async function Vr(y,k,R,W,V="any"){return pt(y,k,V,(G)=>k.authz.hasRole(G.subjectId,R,W,G.subjectType),()=>({targetType:"role",target:Be(R),resource:W?Be(W):void 0}),W?void 0:Mt([Be(R)],"any"))}async function qr(y,k,R,W,V="any"){return pt(y,k,V,(G)=>k.authz.hasGroup(G.subjectId,R,W,G.subjectType),()=>({targetType:"group",target:Be(R),resource:W?Be(W):void 0}),W?void 0:Mt([Be(R)],"any"))}async function $r(y,k,R,W="any"){let V=R.filter((H)=>!H.resource).map((H)=>Be(H.target)),G=R.filter((H)=>!H.resource&&H.targetType==="permission").map((H)=>Be(H.target));return pt(y,k,W,(H)=>k.authz.hasAny(H.subjectId,R,H.subjectType),()=>({targets:R.map((H)=>`${H.targetType}:${Be(H.target)}`)}),V.length>0?Mt(V,"any"):void 0,G.length>0?Xt(k,G,"any"):void 0)}async function zr(y,k,R,W="any"){let V=R.length>0&&R.every((Y)=>!Y.resource),G=R.length>0&&R.every((Y)=>!Y.resource&&Y.targetType==="permission"),H=R.map((Y)=>Be(Y.target));return pt(y,k,W,(Y)=>k.authz.hasAll(Y.subjectId,R,Y.subjectType),()=>({targets:R.map((Y)=>`${Y.targetType}:${Be(Y.target)}`)}),V?Mt(H,"all"):void 0,G?Xt(k,H,"all"):void 0)}async function Br(y,k,R,W="any"){return pt(y,k,W,(V)=>Promise.resolve(fn(V,[R],"any")),()=>({scope:R}))}async function Gr(y,k,R,W="any"){return pt(y,k,W,(V)=>Promise.resolve(fn(V,R,"any")),()=>({scopes:R}))}async function Kr(y,k,R,W="any"){return pt(y,k,W,(V)=>Promise.resolve(fn(V,R,"all")),()=>({scopes:R}))}function Fe(y){return typeof y==="string"&&y.length>0?y:void 0}function Zn(y){let k=Fe(y.email);return{sub:String(y.sub??""),email:k,name:Fe(y.name),userName:Fe(y.preferred_username)??k,avatar:Fe(y.picture)}}var Qn={oidc:{flow:"id_token",scope:"openid profile email",branding:{displayName:"Single sign-on"},mapClaims:Zn},google:{flow:"id_token",authorizationUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",jwksUri:"https://www.googleapis.com/oauth2/v3/certs",scope:"openid email profile",branding:{displayName:"Google",iconUrl:"https://www.gstatic.com/firebasejs/ui/2.0.0/images/auth/google.svg",colors:{light:"#ffffff",dark:"#131314",secondary:"#4285F4"},url:"https://accounts.google.com"},mapClaims:Zn},microsoft:{flow:"id_token",authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",jwksUri:"https://login.microsoftonline.com/common/discovery/v2.0/keys",scope:"openid email profile",branding:{displayName:"Microsoft",colors:{light:"#ffffff",dark:"#2f2f2f",secondary:"#0067b8"},url:"https://login.microsoftonline.com"},mapClaims:(y)=>{let k=Fe(y.email)??Fe(y.preferred_username);return{sub:String(y.sub??y.oid??""),email:k,name:Fe(y.name),userName:Fe(y.preferred_username)??k,avatar:Fe(y.picture)}}},apple:{flow:"id_token",authorizationUrl:"https://appleid.apple.com/auth/authorize",tokenUrl:"https://appleid.apple.com/auth/token",jwksUri:"https://appleid.apple.com/auth/keys",scope:"openid email name",extraAuthParams:{response_mode:"form_post"},branding:{displayName:"Apple",colors:{light:"#000000",dark:"#ffffff"},url:"https://appleid.apple.com"},mapClaims:(y)=>{let k=Fe(y.email);return{sub:String(y.sub??""),email:k,name:Fe(y.name),userName:k}}},github:{flow:"userinfo",authorizationUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",userInfoUrl:"https://api.github.com/user",scope:"read:user user:email",branding:{displayName:"GitHub",colors:{light:"#24292f",dark:"#ffffff"},url:"https://github.com"},mapClaims:(y)=>({sub:String(y.id??y.node_id??""),email:Fe(y.email),name:Fe(y.name)??Fe(y.login),userName:Fe(y.login),avatar:Fe(y.avatar_url)})}};function gn(y){if(y==="magic-link")return;return Qn[y]}function Zt(y,k){if(k.type==="magic-link")return;let R=gn(k.type);if(!R)return;return{name:y,type:k.type,flow:R.flow,authorizationUrl:k.authorizationUrl??R.authorizationUrl,tokenUrl:k.tokenUrl??R.tokenUrl,jwksUri:k.jwksUri??R.jwksUri,userInfoUrl:k.userInfoUrl??R.userInfoUrl,scope:k.scope??R.scope,clientId:k.clientId,clientSecret:k.clientSecret,extraAuthParams:R.extraAuthParams,branding:{...R.branding,...k.branding},mapClaims:R.mapClaims,config:k}}function yn(y){return{...gn(y.type)?.branding??{displayName:y.type},...y.branding}}function hn(y){if(!y)return[];return Object.entries(y).filter(([,k])=>k.enabled!==!1).map(([k,R],W)=>({name:k,config:R,index:W})).sort((k,R)=>{let W=k.config.order??Number.MAX_SAFE_INTEGER,V=R.config.order??Number.MAX_SAFE_INTEGER;if(W!==V)return W-V;return k.index-R.index}).map(({name:k,config:R})=>({name:k,config:R}))}var tr=600000,kn=256,et=new Map;function Jr(y){if(typeof y?.ttlMs==="number"&&Number.isFinite(y.ttlMs))tr=Math.min(Math.max(y.ttlMs,60000),86400000);if(typeof y?.maxEntries==="number"&&Number.isFinite(y.maxEntries)){kn=Math.max(1,Math.floor(y.maxEntries));while(et.size>kn){let k=et.keys().next().value;if(k===void 0)break;et.delete(k)}}}function er(y,k){et.delete(y),et.set(y,k);while(et.size>kn){let R=et.keys().next().value;if(R===void 0)break;et.delete(R)}}var Nt=new Map,wn=()=>Date.now();function Hr(y){wn=y??(()=>Date.now())}var bn={};function Fr(y){bn=y??{}}function Yr(y){if(!y)return;if(/\bno-store\b/i.test(y))return 60000;let k=/max-age\s*=\s*(\d+)/i.exec(y);if(!k)return;let R=Number(k[1]);return Number.isFinite(R)?R*1000:void 0}function Xr(y){let R=Yr(y)??tr;return Math.min(Math.max(R,60000),86400000)}async function Cn(y,k=3,R=1000,W=30000,V){let G=Error("Placeholder Error");for(let H=0;H<=k;H++)try{return await y()}catch(Y){if(G=Y instanceof Error?Y:Error(String(Y)),Y instanceof Error&&Y.message.includes("400"))throw Y;if(H===k)throw G;let Q=Math.min(R*2**H,W),X=Math.random()*0.1*Q;await new Promise((Pe)=>setTimeout(Pe,Q+X)),V?.warn(`Retry attempt ${H+1} after ${Q+X}ms delay`)}throw G}async function Wt(y,k,R){let W=et.get(y);if(!R?.forceRefresh&&W&&W.expiresAt>wn())return er(y,W),W.jwks;let V=Nt.get(y);if(V)return V;let G=(async()=>{try{return await Cn(async()=>{let H=await fetch(y);if(!H.ok)throw Error("Failed to fetch JWKS");let Y=await H.json(),Q=Xr(H.headers.get("cache-control"));return er(y,{jwks:Y,expiresAt:wn()+Q,importedKeys:new Map}),Y},bn.maxRetries,bn.baseDelayMs,void 0,k)}catch(H){let Y=et.get(y);if(Y)return k?.warn("JWKS refresh failed; serving last-known-good keys",{"ion.operation":"jwks.refresh","ion.outcome":"degraded"}),Y.jwks;throw H}finally{Nt.delete(y)}})();return Nt.set(y,G),G}function Zr(y){if(y){et.delete(y),Nt.delete(y);return}et.clear(),Nt.clear()}async function Qr(y,k,R){return(await nr(y,k,R)).jwk}async function nr(y,k,R){if(!k?.trim())throw Error("JWT header missing kid");await Wt(y,R);let W=et.get(y),V=W?.jwks.keys.find((G)=>G.kid===k);if(!V)await Wt(y,R,{forceRefresh:!0}),W=et.get(y),V=W?.jwks.keys.find((G)=>G.kid===k);if(!W||!V)throw Error("Public key not found");return{jwk:V,entry:W}}async function Rn(y,k,R,W,V){let{jwk:G,entry:H}=await nr(y,k,V),Y=`${k}\x00${R}`,Q=H.importedKeys.get(Y);if(Q)return Q;let X=W(G);return X.catch(()=>{if(H.importedKeys.get(Y)===X)H.importedKeys.delete(Y)}),H.importedKeys.set(Y,X),X}async function es(y,k){let R=y.keys.find((W)=>W.kid===k);if(!R)throw Error("Public key not found");return rr(R)}function rr(y){return crypto.subtle.importKey("jwk",{kty:y.kty,n:y.n,e:y.e},{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},!1,["verify"])}async function ts(y,k,R){return Rn(y,k,"rs256",rr,R)}var Sn={RS256:{kty:"RSA",importParams:{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},verifyParams:{name:"RSASSA-PKCS1-v1_5"}},ES256:{kty:"EC",crv:"P-256",importParams:{name:"ECDSA",namedCurve:"P-256"},verifyParams:{name:"ECDSA",hash:"SHA-256"}}};async function vn(y,k,R,W){if(typeof R!=="string"||!(R in Sn))throw Error(`Unsupported JWT alg "${String(R)}" (allowed: ${Object.keys(Sn).join(", ")})`);let V=Sn[R];return{key:await Rn(y,k,`oidc:${R}`,(H)=>{if(H.kty!==V.kty)throw Error(`JWK type "${H.kty}" does not match token alg "${R}"`);if(V.kty==="EC"){let Y=H;if(Y.crv!==V.crv)throw Error(`JWK curve "${String(Y.crv)}" does not match token alg "${R}"`);return crypto.subtle.importKey("jwk",{kty:"EC",crv:Y.crv,x:Y.x,y:Y.y},V.importParams,!1,["verify"])}return crypto.subtle.importKey("jwk",{kty:H.kty,n:H.n,e:H.e},V.importParams,!1,["verify"])},W),algorithm:V.verifyParams}}function st(y=32){let k=new Uint8Array(y);return crypto.getRandomValues(k),Array.from(k,(R)=>R.toString(16).padStart(2,"0")).join("").substring(0,y)}function Qt(y){let k="";return y.forEach((R)=>{k+=String.fromCharCode(R)}),btoa(k).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function or(y){let k=y.replace(/-/g,"+").replace(/_/g,"/"),R=k.padEnd(k.length+(4-k.length%4)%4,"="),W=atob(R),V=new Uint8Array(W.length);for(let G=0;G<W.length;G++)V[G]=W.charCodeAt(G);return V}function sr(y){let k=new TextDecoder().decode(or(y));return JSON.parse(k)}async function $t(y){let k=new TextEncoder().encode(y),R=await crypto.subtle.digest("SHA-256",k);return Qt(new Uint8Array(R))}function An(y){let k=new URL(y.authorizationUrl);if(k.searchParams.set("client_id",y.clientId),k.searchParams.set("redirect_uri",y.redirectUri),k.searchParams.set("response_type","code"),k.searchParams.set("scope",y.scope),k.searchParams.set("state",y.state),y.codeChallenge)k.searchParams.set("code_challenge",y.codeChallenge),k.searchParams.set("code_challenge_method","S256");if(y.nonce)k.searchParams.set("nonce",y.nonce);for(let[R,W]of Object.entries(y.extraParams??{}))k.searchParams.set(R,W);return k.toString()}async function Tn(y){let k=new URLSearchParams;if(k.append("grant_type","authorization_code"),k.append("code",y.code),k.append("redirect_uri",y.redirectUri),k.append("client_id",y.clientId),y.clientSecret)k.append("client_secret",y.clientSecret);if(y.codeVerifier)k.append("code_verifier",y.codeVerifier);let R=await fetch(y.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:k.toString()}),W=await R.json();if(!R.ok){let V=W,G=V.error==="invalid_client"&&!y.clientSecret;throw y.log?.error(G?"OIDC authorization-code exchange failed: no client_secret was configured; the provider may require a confidential client":"OIDC authorization-code exchange failed",{"ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":R.status,oidc_error:V.error,...G?{client_auth:"none"}:{}}),Error(`Token exchange failed: ${V.error||R.statusText} - ${V.error_description||""}`.trim())}if(typeof W.access_token!=="string")throw Error("Token exchange response missing access_token");return W}var ar=60;function qt(y){return y.trim().replace(/\/$/,"")}function cr(y){let{claims:k,audience:R}=y,W=qt(y.issuer),V=y.nowSec??Math.floor(Date.now()/1000),G=y.clockSkewSec??ar,H=k.iss;if(typeof H!=="string"||qt(H)!==W)throw Error("ID token issuer mismatch");let Y=k.aud,Q=Array.isArray(Y)?Y.includes(R):typeof Y==="string"&&Y===R,X=typeof k.azp==="string"&&k.azp===R;if(!Q&&!X)throw Error("ID token audience mismatch");if(typeof k.exp!=="number")throw Error("ID token missing exp");if(k.exp<V-G)throw Error("ID token expired");if(y.expectedNonce!==void 0){if(k.nonce!==y.expectedNonce)throw Error("ID token nonce mismatch")}}async function ur(y,k,R){let W=y.split(".");if(W.length!==3)throw Error("Invalid JWT");let V=sr(W[0]),G=sr(W[1]),H=or(W[2]),{key:Y,algorithm:Q}=await vn(k,V.kid,V.alg,R),X=new TextEncoder().encode(`${W[0]}.${W[1]}`);if(!await crypto.subtle.verify(Q,Y,H,X))throw Error("Invalid JWT signature");return{header:V,payload:G}}async function kt(y){let{payload:k}=await ur(y.idToken,y.jwksUri,y.log);return cr({claims:k,issuer:y.issuer,audience:y.audience,clockSkewSec:y.clockSkewSec,expectedNonce:y.expectedNonce}),k}var ns="http://schemas.openid.net/event/backchannel-logout";async function Pn(y){let{payload:k}=await ur(y.logoutToken,y.jwksUri,y.log),R=qt(y.issuer),W=k.iss;if(typeof W!=="string"||qt(W)!==R)throw Error("Logout token issuer mismatch");let V=k.aud,G=Array.isArray(V)?V.includes(y.audience):typeof V==="string"&&V===y.audience,H=typeof k.azp==="string"&&k.azp===y.audience;if(!G&&!H)throw Error("Logout token audience mismatch");if(k.nonce!=null)throw Error("Logout token must not contain a nonce");let Y=k.events;if(!(typeof Y==="object"&&Y!==null&&!Array.isArray(Y)&&Object.hasOwn(Y,ns)))throw Error("Logout token missing back-channel logout event");let X=typeof k.sid==="string"&&k.sid.length>0,Pe=typeof k.sub==="string"&&k.sub.length>0;if(!X&&!Pe)throw Error("Logout token missing sid and sub");if(typeof k.exp==="number"){let xe=Math.floor(Date.now()/1000),je=y.clockSkewSec??ar;if(k.exp<xe-je)throw Error("Logout token expired")}return k}var rs=3600000,ss=60000,is=86400000,os=256,mt=new Map,Vt=new Map;function ir(y,k){mt.delete(y),mt.set(y,k);while(mt.size>os){let R=mt.keys().next().value;if(R===void 0)break;mt.delete(R)}}var In=()=>Date.now();function as(y){In=y??(()=>Date.now())}function cs(y){if(y){mt.delete(y),Vt.delete(y);return}mt.clear(),Vt.clear()}function us(y){let k=y?/max-age\s*=\s*(\d+)/i.exec(y):null,R=k?Number(k[1]):Number.NaN,W=Number.isFinite(R)?R*1000:rs;return Math.min(Math.max(W,ss),is)}async function xn(y){let k=mt.get(y);if(k&&k.expiresAt>In())return ir(y,k),k.endpoints;let R=Vt.get(y);if(R)return R;let W=(async()=>{try{let V=y.replace(/\/$/,""),G=await fetch(`${V}/.well-known/openid-configuration`,{headers:{Accept:"application/json"}});if(!G.ok)throw Error(`OIDC discovery failed for ${y} with status ${G.status}`);let H=await G.json(),Y={authorizationUrl:typeof H.authorization_endpoint==="string"?H.authorization_endpoint:void 0,tokenUrl:typeof H.token_endpoint==="string"?H.token_endpoint:void 0,jwksUri:typeof H.jwks_uri==="string"?H.jwks_uri:void 0,userInfoUrl:typeof H.userinfo_endpoint==="string"?H.userinfo_endpoint:void 0};return ir(y,{endpoints:Y,expiresAt:In()+us(G.headers.get("cache-control"))}),Y}catch(V){let G=mt.get(y);if(G)return G.endpoints;throw V}finally{Vt.delete(y)}})();return Vt.set(y,W),W}async function Un(y,k){let R=await fetch(y,{headers:{Authorization:`Bearer ${k}`,Accept:"application/json","User-Agent":"ionite-ciam"}});if(!R.ok)throw Error(`UserInfo request failed with status ${R.status}`);return await R.json()}function ds(y){let k=y.replace(/-----BEGIN [^-]+-----/g,"").replace(/-----END [^-]+-----/g,"").replace(/\s+/g,""),R=atob(k),W=new Uint8Array(R.length);for(let V=0;V<R.length;V++)W[V]=R.charCodeAt(V);return W}async function En(y){let k=Math.floor(Date.now()/1000),R={alg:"ES256",kid:y.keyId,typ:"JWT"},W={iss:y.teamId,iat:k,exp:k+(y.expiresInSeconds??3600),aud:"https://appleid.apple.com",sub:y.clientId},V=Qt(new TextEncoder().encode(JSON.stringify(R))),G=Qt(new TextEncoder().encode(JSON.stringify(W))),H=`${V}.${G}`,Y=await crypto.subtle.importKey("pkcs8",ds(y.privateKey),{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),Q=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},Y,new TextEncoder().encode(H));return`${H}.${Qt(new Uint8Array(Q))}`}function ls(y){for(let k=0;k<y.length;k++){let R=y.charCodeAt(k);if(R<=31||R===127)return!0}return!1}function ps(y,k){let R=null;try{R=new URL(y,k)}catch{R=null}let W="";try{W=new URL(k).origin}catch{W=""}return{candidate:y,url:R,requestOrigin:W}}function dr(y,k,R){let W=ps(y,R),V=!1;for(let G of k){let H=G(W);if(H==="deny")return!1;if(H==="allow")V=!0}return V}function lr(){return({candidate:y,url:k})=>{if(ls(y))return"deny";if(y.includes("\\"))return"deny";if(y.startsWith("//"))return"deny";if(!k)return"deny";if(k.protocol!=="http:"&&k.protocol!=="https:")return"deny";if(k.username||k.password)return"deny";return"abstain"}}function pr(){return({candidate:y})=>y.startsWith("/")&&!y.startsWith("//")&&!y.startsWith("/\\")?"allow":"abstain"}function mr(){return({url:y,requestOrigin:k})=>y&&k&&y.origin===k?"allow":"abstain"}function ms(...y){let k=new Set(y.map((R)=>{try{return new URL(R).origin}catch{return R}}));return({url:R})=>R&&k.has(R.origin)?"allow":"abstain"}function fs(...y){let k=y.map((R)=>R.toLowerCase());return({url:R})=>{if(!R)return"abstain";let W=R.hostname.toLowerCase();for(let V of k)if(V.startsWith(".")){if(W===V.slice(1)||W.endsWith(V))return"allow"}else if(W===V)return"allow";return"abstain"}}function Mn(){return[lr(),pr(),mr()]}function fr(y,k,R){if(!y)return!1;return dr(y,k,R)}function jn(y,k){if(!y)return k.fallback;return dr(y,k.rules,k.requestUrl)?y:k.fallback}var gs={rules:Mn(),fallback:"/"};function ys(y,k,R="redirect"){let W=new URL(y.url).searchParams.get(R)??void 0;return fr(W,k.rules,y.url)?{redirect:W}:void 0}function hs(y,k){let R=y.context;return jn(R?.redirect,{rules:k.rules,fallback:k.fallback,requestUrl:y.request.url})}function wt(y,k,R){if(y instanceof Response)return{response:y};if(typeof y==="string")return{location:jn(y,{rules:Mn(),fallback:k,requestUrl:R})};return{location:k}}function At(y,k){if(k.length===0)return y;let R=new Headers(y.headers);for(let W of k)R.append("Set-Cookie",W);return new Response(y.body,{status:y.status,statusText:y.statusText,headers:R})}var en="ciam",Ss="id_token",ks="access_token";function ws(y,k,R,W,V,G){if(!R&&!W)return;let H=new WeakMap,Y={...R,...W},Q={...Y,magicLinkTtl:Y.magicLinkTtl??3600,sessionTtl:Y.sessionTtl??86400,cookiesSecure:Y.cookiesSecure!==void 0?Y.cookiesSecure:!0,cookiesSameSite:Y.cookiesSameSite!==void 0?Y.cookiesSameSite:"Strict",cookiesPrefix:Y.cookiesPrefix??(Y.ciamId?`ion.ciam.${Y.ciamId}`:"ion.ciam"),cookiesPath:Y.cookiesPath??"/"};function X(){if(!Q.sessionStore)throw Error("Missing CIAM configuration field: sessionStore. CIAM sessionStore is required for server-side session tracking and first-party logout.");return Q.sessionStore}function Pe(){X()}let xe=y.callbackParams??a(N("ionite.ciam")),je=y.idTokenClaims??a(l("ionite.ciam")),De=y.tokenResponse??a(L("ionite.ciam"));function We(M=32){let B=new Uint8Array(M);return crypto.getRandomValues(B),Array.from(B,(J)=>J.toString(16).padStart(2,"0")).join("").substring(0,M)}function ke(M,B,J,F=Q.cookiesSameSite??"Strict"){if(!Q)throw Error("ionite CIAM Manager not initialized");if(M=`${Q.cookiesPrefix}.${M}`,typeof B!=="string")B=btoa(JSON.stringify(B));let ne;if(J instanceof Date)ne=`Expires=${J.toUTCString()}`;else if(typeof J==="number")ne=`Max-Age=${J}`;else throw Error("Invalid expires type",J);if(B.length>4000)throw Error(`Error setting cookie: ${M}. Cookie length is: ${B.length}`);return`${M}=${B}; ${ne}; Path=${Q.cookiesPath}; HttpOnly;${Q.cookiesSecure?" Secure;":""} SameSite=${F};`}function Le(M){if(!Q)throw Error("ionite CIAM Manager not initialized");return`${Q.cookiesPrefix}.${M}=; Max-Age=0; Path=${Q.cookiesPath}; HttpOnly;${Q.cookiesSecure?" Secure;":""} SameSite=${Q.cookiesSameSite};`}function ye(M,B,J=!1){if(!Q)throw Error("ionite CIAM Manager not initialized");let F=B.headers.get("cookie");if(!F)return null;let ne=`${Q.cookiesPrefix}.${M}`,pe=F.split(";").find((se)=>se.trim().startsWith(`${ne}=`));if(!pe)return null;let de=pe.indexOf("="),re=pe.substring(de+1).trim();if(!J)return re;try{let se=atob(re);return JSON.parse(se)}catch(se){return k.error("[CIAM] Failed to parse cookie",{"ion.operation":"cookie.parse","ion.outcome":"failure",cookieName:ne},se),null}}function _e(M){return`cstate_${M}`}async function Ne(M,B,J,F){let ne=await Q.afterLogin?.({...B,request:M,context:J}),pe=wt(ne,"/",M.url);if(pe.response)return At(pe.response,F.map(([,de])=>de));return new Response(B.ok?"Authentication successful, redirecting":"Authentication failed, redirecting",{status:302,headers:[["Location",pe.location],...F]})}function $e(M,B){return["Set-Cookie",ke("session",M,B)]}function tt(M){if(!M)return;if(M instanceof Date)return M;let B=new Date(M);return Number.isNaN(B.getTime())?void 0:B}async function Ge(M){let B=ye("session",M);if(!B)return;let J=await X().get(B);if(J&&Q.tenantId&&J.tenantId&&J.tenantId!==Q.tenantId)return;if(J?.authType!=="ciam")return;let F=tt(J.expiresAt);if(F&&Date.now()>F.getTime()){await X().delete(B);return}return J}async function Je(M){if(!Q)throw Error("ionite CIAM Manager not initialized");Pe();let B=H.get(M);if(B)return B;let J=nt(M);return H.set(M,J),J}async function nt(M){try{let B=await Ge(M);if(!B?.claims?.sub)return{status:"unauthenticated"};return{status:"authenticated",value:ot(B.claims)}}catch(B){return k.error("CIAM session resolution failed",{"ion.operation":"ciam.session","ion.outcome":"degraded"},B),{status:"degraded",error:B instanceof Error?B:void 0}}}async function Ut(M){let B=await Je(M);return B.status==="authenticated"?B.value:void 0}async function Rt(M){if(!Q)throw Error("ionite CIAM Manager not initialized");Pe();let B;try{B=await Ut(M)}catch{B=void 0}let J=await Q.beforeLogout?.({request:M,user:B});try{let fe=ye("session",M);if(fe)await X().delete(fe)}catch(fe){k.warn("Failed to delete CIAM session",{"ion.operation":"session.delete","ion.outcome":"degraded"},fe)}let F=[["Set-Cookie",Le("session")]],ne=await Q.afterLogout?.({request:M,context:J}),pe=wt(ne,"/",M.url);if(pe.response)return At(pe.response,F.map(([,fe])=>fe));let de=pe.location??"/",re=M.headers.get("accept");if(re?.includes("application/json")||re?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:de}),{status:200,headers:[["Content-Type","application/json"],...F]});return new Response("Logged out",{status:302,headers:[["Location",de],...F]})}function Et(M){return M.id||M.email||`ciam-${M.userName}`}function Dt(M,B,J){return{sub:Et(M),iss:en,aud:en,typ:Ss,exp:Math.floor(J.getTime()/1000),iat:Math.floor(Date.now()/1000),email:M.email,name:M.name,preferred_username:M.userName,picture:M.avatar,sid:B}}function Lt(M,B,J){return{sub:M,iss:en,aud:en,typ:ks,exp:Math.floor(J.getTime()/1000),iat:Math.floor(Date.now()/1000),sid:B,scope:"openid profile email"}}function ot(M){let B=M.exp?new Date(M.exp*1000):new Date;return{id:M.sub,userName:M.preferred_username??"",name:M.name??"",email:M.email??"",avatar:M.picture,userType:"customer",ciam:{profile:M,scope:"openid profile email",tokenType:"Bearer",expires:B}}}async function vt(M){if(!Q)throw Error("ionite CIAM Manager not initialized");if(!V)return new Response(JSON.stringify({error:"Workload authentication required"}),{status:401,headers:{"Content-Type":"application/json"}});if(!await V.getWorkloadIdentity(M))return new Response(JSON.stringify({error:"Unauthorized: Valid workload token required"}),{status:401,headers:{"Content-Type":"application/json"}});let J,F;try{if(!M.headers.get("content-type")?.includes("application/json"))return new Response(JSON.stringify({error:"Content-Type must be application/json"}),{status:400,headers:{"Content-Type":"application/json"}});let Oe=await M.text(),Ee=JSON.parse(Oe);F=typeof Ee?.redirect==="string"&&Ee.redirect.length>0?Ee.redirect:void 0;let ae={userName:Ee.userName,name:Ee.name,email:Ee.email,avatar:Ee.avatar},ee=await y.customer.validate(ae);if(ee.issues)return new Response(JSON.stringify({error:"Missing required fields: userName, name, email"}),{status:400,headers:{"Content-Type":"application/json"}});J=ee.value}catch(Ie){return new Response(JSON.stringify({error:"Invalid JSON in request body"}),{status:400,headers:{"Content-Type":"application/json"}})}let pe=new URL(M.url).searchParams.get("ttl"),de=pe?parseInt(pe,10):Q.magicLinkTtl??3600;if(Number.isNaN(de)||de<=0)return new Response(JSON.stringify({error:"Invalid TTL parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let re=We(32),se=new Date(Date.now()+de*1000);if(!Q.magicLinkStore)return new Response(JSON.stringify({error:"Magic link store not configured"}),{status:501,headers:{"Content-Type":"application/json"}});try{await Q.magicLinkStore.create(re,J,se)}catch(Ie){return k.error("Error creating magic link",{"ion.operation":"magic_link.create","ion.outcome":"failure"},Ie),new Response(JSON.stringify({error:"Failed to create magic link"}),{status:500,headers:{"Content-Type":"application/json"}})}let fe=new URL(M.url),be=Q.magicLinkLoginUrl||"/magic-link/login",me=new URL(be,fe.origin);if(me.searchParams.set("token",re),F)me.searchParams.set("redirect",F);return new Response(JSON.stringify({magicLink:me.toString(),expiresAt:se.toISOString()}),{status:200,headers:{"Content-Type":"application/json"}})}async function gt(M){if(!Q)throw Error("ionite CIAM Manager not initialized");Pe();let J=new URL(M.url).searchParams.get("token");if(!J)return Ne(M,{ok:!1,error:Error("Missing magic-link token")},void 0,[]);if(!Q.magicLinkStore)return Ne(M,{ok:!1,error:Error("Magic link store not configured")},void 0,[]);let F=await Q.magicLinkStore.getAndDelete(J);if(!F)return Ne(M,{ok:!1,error:Error("Magic link invalid, expired, or already used")},void 0,[]);let ne=new Date(Date.now()+(Q.sessionTtl??86400)*1000),pe=We(32),de=Et(F.customer),re=Dt(F.customer,pe,ne),se=Lt(de,pe,ne),fe=ot(re),be;try{let Ie={sid:pe,sub:de,authType:"ciam",tenantId:Q.tenantId,expiresAt:ne,claims:re,accessClaims:se,createdAt:new Date};await X().create(Ie),be=Ie}catch(Ie){throw k.warn("Failed to create session",{"ion.operation":"session.create","ion.outcome":"degraded"},Ie),Ie}if(Q.customerStore)try{let Ie=fe.id;if(Ie){let Oe=new Date,Ee=await Q.customerStore.get(Ie);if(Ee||Q.enableJitUserProvisioning){let ae={...Ee??{},...fe,id:Ie,tenantId:Ee?.tenantId,createdAt:Ee?.createdAt??Oe,updatedAt:Oe,userType:Ee?.userType??"customer"};await Q.customerStore.upsert(ae)}}}catch(Ie){k.warn("Failed to store customer",{"ion.operation":"customer.store","ion.outcome":"degraded"},Ie)}let me=[$e(pe,ne)];return Ne(M,{ok:!0,user:fe,session:be},void 0,me)}function at(M,B=200,J=[]){return new Response(JSON.stringify(M),{status:B,headers:[["Content-Type","application/json"],...J]})}function It(M,B){try{return new URL(M).toString()}catch{let J=new URL(B).origin,F=Q.cookiesSecure?J.replace(/^http:\/\//,"https://"):J;return new URL(M,F).toString()}}function lt(){let M=Q.customerLoginUrl||"/auth/customer/login",B=M.includes("?")?"&":"?";return hn(Q.providers).map(({name:J,config:F})=>{let ne=yn(F);return{name:J,type:F.type,displayName:ne.displayName,loginUrl:`${M}${B}provider=${encodeURIComponent(J)}`,iconUrl:ne.iconUrl,colors:ne.colors,url:ne.url}})}async function Ze(M){if(!M)return{};let{authorizationUrl:B,tokenUrl:J,jwksUri:F,userInfoUrl:ne}=M,pe=M.config.authority;if(pe&&(!B||!J||M.flow==="id_token"&&!F))try{let re=await xn(pe);B=B??re.authorizationUrl,J=J??re.tokenUrl,F=F??re.jwksUri,ne=ne??re.userInfoUrl}catch(re){k.error("CIAM provider OIDC discovery failed",{"ion.operation":"ciam.oidc.discovery","ion.outcome":"failure"},re)}return{authorizationUrl:B,tokenUrl:J,jwksUri:F,userInfoUrl:ne}}async function yt(M){if(M.type==="apple"){let{teamId:B,keyId:J,privateKey:F,clientId:ne}=M.config;if(B&&J&&F&&ne)return En({teamId:B,keyId:J,privateKey:F,clientId:ne})}return M.clientSecret}async function ct(M){X();let J=new URL(M.url).searchParams.get("provider");if(!J)return at({error:"Missing required query parameter: provider"},400);let F=Q.providers?.[J];if(!F||F.enabled===!1||F.type==="magic-link")return at({error:`Unknown or disabled CIAM provider: ${J}`},404);let ne=Zt(J,F);if(!ne?.clientId)return at({error:`CIAM provider ${J} is not fully configured`},500);let pe=await Ze(ne);if(!pe.authorizationUrl)return at({error:`CIAM provider ${J} is missing an authorization endpoint`},500);let de=Q.customerCallbackUrl||"/auth/customer/callback",re=It(de,M.url),se=st(),fe=st(64),be=st(),me=ne.flow==="id_token",Ie=me?await $t(fe):void 0,Oe=await Q.beforeLogin?.({request:M}),Ee=An({authorizationUrl:pe.authorizationUrl,clientId:ne.clientId,redirectUri:re,scope:ne.scope,state:se,codeChallenge:Ie,nonce:be,extraParams:ne.extraAuthParams}),ae={provider:J,state:se,codeVerifier:me?fe:void 0,nonce:be,redirectUri:re,...Oe===void 0?{}:{context:Oe}};return new Response("Redirecting to CIAM provider",{status:302,headers:[["Location",Ee],["Set-Cookie",ke(_e(se),ae,Q.loginStateTtl??600,"Lax")]]})}async function rt(M){if(M.method==="POST"){if((M.headers.get("content-type")??"").includes("application/x-www-form-urlencoded")){let J=await M.text();return Object.fromEntries(new URLSearchParams(J).entries())}}return Object.fromEntries(new URL(M.url).searchParams.entries())}async function ht(M,B){let J=M.mapClaims(B);if(!J.sub)return{ok:!1};let F=`${M.name}:${J.sub}`,ne={id:F,userName:J.userName||J.email||F,name:J.name||"",email:J.email||"",avatar:J.avatar,userType:"customer"},pe=F;if(Q.customerStore){let me=await Q.customerStore.lookup(ne)??await Q.customerStore.get(F);if(pe=me?.id??F,!me&&!Q.enableJitUserProvisioning)return k.warn("CIAM JIT customer provisioning disabled: unknown customer rejected",{"ion.operation":"customer.store","ion.outcome":"skipped"}),{ok:!1};let Ie=new Date,Oe={...me??{},...ne,id:pe,tenantId:me?.tenantId,createdAt:me?.createdAt??Ie,updatedAt:Ie,userType:me?.userType??"customer"};await Q.customerStore.upsert(Oe)}let de=new Date(Date.now()+(Q.sessionTtl??86400)*1000),re=st(32),se={sub:pe,iss:M.name,aud:M.clientId,exp:Math.floor(de.getTime()/1000),iat:Math.floor(Date.now()/1000),email:J.email,name:J.name,preferred_username:J.userName??J.email,picture:J.avatar,sid:re},fe={sid:re,sub:pe,authType:"ciam",tenantId:Q.tenantId,expiresAt:de,claims:se,accessClaims:{sub:pe,sid:re,scope:M.scope},createdAt:new Date},be=X();try{await be.create(fe)}catch(me){if(!await be.get(re))throw me;await be.update(re,fe)}return{ok:!0,claims:se,sid:re,expires:de}}async function Se(M){X();let B,J,F=(ne)=>{let pe=B?[["Set-Cookie",Le(B)]]:[];return Ne(M,{ok:!1,error:ne},J,pe)};try{let ne=await rt(M),pe=await xe.validate(ne);if(pe.issues||!pe.value)return F(Error("Invalid CIAM callback parameters"));let{code:de,state:re}=pe.value;if(!re)return F(Error("Missing CIAM callback state"));B=_e(re);let se=ye(B,M,!0);if(J=se?.context,!se?.provider||!se.state||se.state!==re)return k.warn("CIAM callback state verification failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),F(Error("CIAM callback state verification failed"));let fe=Q.providers?.[se.provider];if(!fe)return F(Error("Unknown CIAM provider"));let be=Zt(se.provider,fe);if(!be?.clientId)return F(Error("CIAM provider not configured"));let me=await Ze(be);if(!me.tokenUrl)return F(Error("CIAM provider missing token endpoint"));let Ie=await yt(be),Oe=await Tn({tokenUrl:me.tokenUrl,clientId:be.clientId,clientSecret:Ie,redirectUri:se.redirectUri||It(Q.customerCallbackUrl||"/auth/customer/callback",M.url),code:de,codeVerifier:be.flow==="id_token"?se.codeVerifier:void 0,log:k}),Ee;if(be.flow==="id_token"){let ue=be.config.authority;if(!Oe.id_token||!me.jwksUri||!ue)return F(Error("CIAM id_token flow misconfigured"));if(!se.nonce)return F(Error("CIAM callback state cookie missing nonce"));if((await De.validate(Oe)).issues)return k.warn("CIAM token response validation failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),F(Error("CIAM token response validation failed"));Ee=await kt({idToken:Oe.id_token,jwksUri:me.jwksUri,issuer:ue,audience:be.clientId,expectedNonce:se.nonce,log:k});let he=await je.validate(Ee);if(!he.issues)Ee=he.value}else{if(!me.userInfoUrl)return F(Error("CIAM provider missing userinfo endpoint"));Ee=await Un(me.userInfoUrl,Oe.access_token);let ue=be.config.authority;if(Oe.id_token&&me.jwksUri&&ue){let ce=await kt({idToken:Oe.id_token,jwksUri:me.jwksUri,issuer:ue,audience:be.clientId,expectedNonce:se.nonce||void 0,log:k}),he=typeof ce.sub==="string"?ce.sub:"";if(he){if(typeof Ee.sub==="string"&&Ee.sub.length>0&&Ee.sub!==he)return k.warn("CIAM UserInfo sub does not match verified id_token sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),F(Error("CIAM UserInfo sub mismatch"));Ee.sub=he}}if(typeof Ee.sub!=="string"||Ee.sub.length===0)return k.warn("CIAM UserInfo response missing sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),F(Error("CIAM UserInfo response missing sub"))}let ae=await ht(be,Ee);if(!ae.ok)return F(Error("Failed to persist CIAM customer"));let ee=ot(ae.claims);k.info("CIAM third-party sign-in succeeded",{"ion.operation":"ciam.oidc.callback","ion.outcome":"success",provider:be.name});let oe=[["Set-Cookie",Le(B)],$e(ae.sid,ae.expires)];return Ne(M,{ok:!0,user:ee,session:void 0},J,oe)}catch(ne){return k.error("Error during CIAM third-party sign-in callback",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"},ne),F(ne)}}async function ve(M){if(!Q)throw Error("ionite CIAM Manager not initialized");Pe();let B=Q.magicLinkUrl||"/magic-link",J=Q.magicLinkLoginUrl||"/magic-link/login",F=Q.logoutUrl||"/auth/customer/logout",ne=Q.customerLoginUrl||"/auth/customer/login",pe=Q.customerCallbackUrl||"/auth/customer/callback",de=Q.customerProvidersUrl||"/auth/customer/providers",re=new URL(M.url).pathname,se=(ae)=>{if(!ae)return;try{return new URL(ae).pathname}catch{return ae.startsWith("/")?ae:`/${ae}`}};if(se(B)===re&&M.method==="POST")return vt(M);if(se(J)===re&&M.method==="GET")return gt(M);if(se(F)===re&&M.method==="GET")return Rt(M);if(se(de)===re&&M.method==="GET")return at({providers:lt()});if(se(ne)===re&&M.method==="GET")return ct(M);if(se(pe)===re&&(M.method==="GET"||M.method==="POST"))return Se(M);return new Response("Not Found",{status:404})}return{...Q,getCustomer:Ut,resolveCustomer:Je,logout:Rt,handler:ve,listCustomerProviders:lt}}async function bs(y,k){return t(k,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),k.ciam?.getCustomer(y)}async function Cs(y,k){return t(k,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),await k.ciam?.resolveCustomer(y)??{status:"unauthenticated"}}var Rs="urn:ietf:params:scim:schemas:core:2.0:User",gr="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",vs="urn:ietf:params:scim:schemas:core:2.0:Group";function _n(y,k,R){let V=(k==="group"?y.resources:void 0)?.map((G)=>typeof G==="string"?G:G.id).filter(Boolean);return{schemas:[vs,e],id:y.id,externalId:y.providerId,displayName:y.displayName??y.name,members:R,[e]:{type:k,requestable:y.requestable,riskLevel:y.riskLevel??u,providerId:y.providerId,requestUrl:y.requestUrl,source:y.source,deprecated:y.deprecated,description:y.description,resources:V&&V.length>0?V:void 0,assignableSubjectTypes:y.assignableSubjectTypes,recommendedSubjectTypes:y.recommendedSubjectTypes,attributes:r(y,o)}}}function Is(y){if(y.scimName)return y.scimName;if(!y.name)return;let[k,...R]=y.name.split(" ");return{givenName:k,familyName:R.join(" ")||void 0}}function As(y){let k={attributes:r(y,h)};if(y.ecid!==void 0)k.ecid=y.ecid;if(y.accountClass!==void 0)k.accountClass=y.accountClass;return k.ecid!==void 0||k.accountClass!==void 0||k.attributes!==void 0?k:void 0}function Ts(y){return Object.keys(y.scimSchemaExtensions??{}).filter((k)=>k.startsWith("urn:")&&y.scimSchemaExtensions?.[k]!==void 0)}function On(y){let k=y.userName||y.email||y.id||"",R=y.emails??(y.email?[{value:y.email,primary:!0}]:[]),W=new Set([Rs]);if(y.scimEnterprise!==void 0)W.add(gr);let V=As(y);if(V!==void 0)W.add(s);for(let H of Ts(y))W.add(H);let G={};if(y.scimEnterprise!==void 0)G[gr]=y.scimEnterprise;if(V!==void 0)G[s]=V;for(let[H,Y]of Object.entries(y.scimSchemaExtensions??{}))if(H.startsWith("urn:")&&H!==s&&Y!==void 0)G[H]=Y;return{schemas:Array.from(W),id:y.id,externalId:y.externalId,userName:k,displayName:y.displayName??y.name??k,name:Is(y),nickName:y.nickName,profileUrl:y.avatar,title:y.title,userType:y.userType,preferredLanguage:y.preferredLanguage,locale:y.locale,timezone:y.timezone,active:y.active??!0,emails:R,phoneNumbers:y.phoneNumbers,ims:y.ims,photos:y.photos,addresses:y.addresses,groups:y.groups,entitlements:y.entitlements,roles:y.roles,x509Certificates:y.x509Certificates,meta:{resourceType:"User",created:(y.createdAt??y.updatedAt??new Date).toISOString(),lastModified:(y.updatedAt??y.createdAt??new Date).toISOString()},...G}}function Dn(y){return{schemas:[f],id:y.id,externalId:y.externalId,userName:y.clientId??y.id,displayName:y.displayName??y.clientId??y.id,description:y.description,active:y.active??!0,ecid:y.ecid,providerId:y.providerId,requestUrl:y.requestUrl,attributes:r(y,b),meta:{resourceType:"Workload",created:(y.createdAt??y.updatedAt??new Date).toISOString(),lastModified:(y.updatedAt??y.createdAt??new Date).toISOString()}}}function Ln(y){return{schemas:[g],id:y.id,externalId:y.externalId??y.id,userName:y.userName??y.email??y.id,displayName:y.displayName??y.name??y.userName??y.id,active:y.active??!0,emails:y.emails??(y.email?[{value:y.email,primary:!0}]:void 0),providerId:y.providerId,requestUrl:y.requestUrl,attributes:r(y,S),meta:{resourceType:"Customer",created:(y.createdAt??y.updatedAt??new Date).toISOString(),lastModified:(y.updatedAt??y.createdAt??new Date).toISOString()}}}function Nn(y){return{enabled:y?.enabled!==!1,assignment:y?.assignment??"app",delta:y?.delta}}var Kt="application/scim+json",Ps="urn:ietf:params:scim:api:messages:2.0:ListResponse",Bn="urn:ietf:params:scim:api:messages:2.0:Error",Gn="urn:ietf:params:scim:schemas:core:2.0:User",Jt="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",Kn="urn:ietf:params:scim:schemas:core:2.0:Group",xs="urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig",tn="urn:ietf:params:scim:schemas:core:2.0:ResourceType",Tt="urn:ietf:params:scim:schemas:core:2.0:Schema",Us="00000000000000000000000000000000";function Es(y){let k={timestamp:new Date().toISOString()};if(y)k.actor=y;try{let V=globalThis[Symbol.for("opentelemetry.js.api.1")]?.trace?.getActiveSpan?.()?.spanContext?.(),G=V?.traceId;if(G&&G!==Us){if(k.traceId=G,V?.spanId)k.spanId=V.spanId}}catch{}return k}class Ht extends Error{constructor(y){super(y);this.name="SubjectTypeNotAssignableError",Object.setPrototypeOf(this,Ht.prototype)}}async function Cr(y,k,R,W){let V=R.subjectType;if(!d.includes(V))throw new Ht(`Cannot grant ${R.targetType} "${n(R.target)}" to a "${V}" principal: only [${d.join(", ")}] principals are assignable on this platform.`);let G=x(k,y);if(!G&&!W)return;let H=n(R.target),Y;if(W)Y=await W.getNode(R.targetType,H);else if(G)Y=await(R.targetType==="group"?G.groups:R.targetType==="role"?G.roles:G.permissions).get(H);if(!Y)return;let Q=Y.assignableSubjectTypes;if(!Q||Q.length===0||!Q.includes(V))throw new Ht(`Cannot grant ${R.targetType} "${H}" to a "${V}" principal: this entitlement restricts assignment to [${(Q??[]).join(", ")||"none"}].`)}async function Ms(y,k){let R=A(y.codeCatalog,n(k.target));if(!R)return;if(R.kind!==k.targetType)throw Error(`Cannot grant ${k.targetType} "${R.entity.id}": code declares that id as ${R.kind}.`);if(!y.catalogStore)throw Error(`Cannot grant code entitlement "${R.entity.id}": no AccessCatalogStore is wired for materialization.`);await v(R.kind,R.entity,I(y.catalogStore,R.kind))}async function js(y,k,R,W){await Ms(y,k),await Cr(y.catalogStore,y.codeCatalog,k,W);let V={...k,status:k.status??"active",provenance:k.provenance??Es()};if(V.id=c(V),await y.accessStore?.grant(V),y.accessIndex&&(y.catalogStore||y.codeCatalog)){let G=await O(V,{catalog:y.catalogStore,code:y.codeCatalog,resources:y.resources,cache:W});await y.accessIndex.materialize(V.id,G)}return R?.push({op:"add",change:V}),V}async function Bt(y,k,R){let W=k.id??c(k);await y.accessStore?.revoke(k),await y.accessIndex?.removeByRoot(W),R?.push({op:"delete",change:{...k,id:W}})}async function sn(y,k){let R=await _s(y,k),W=await Ds(y,k);return{oaa:R,delta:W}}async function _s(y,k){if(k.length===0||!y.authz.oaa.isReady())return{status:"skipped"};return Ct(y,"authz.oaa.push","OAA incremental access push failed after SCIM mutation; full sync will reconcile",()=>y.authz.oaa.pushAccessChanges(k),{count:k.length})}async function Ct(y,k,R,W,V){try{return await W(),{status:"ok"}}catch(G){return y.log?.warn(R,{"ion.operation":k,"ion.outcome":"degraded",...V,error:dt(G)}),{status:"degraded",reason:dt(G)}}}var Os=6;async function Ds(y,k){let R=y.iamDelta;if(!R?.isReady()||k.length===0)return{status:"skipped"};let W=new Map;for(let Q of k){let X=`${Q.change.subjectType}:${n(Q.change.subject)}\x00${Q.change.targetType}:${n(Q.change.target)}`;W.set(X,Q)}let V=[...W.values()],G=V.map(({op:Q,change:X})=>()=>Q==="add"?R.onGrant(X):R.onRevoke(X)),Y=(await Ls(G,Os)).filter((Q)=>Q.status==="rejected");if(Y.length>0)return y.log?.warn("IAM delta egress degraded after SCIM mutation; IAM server reconcile/aggregation will recover",{"ion.operation":"iam.delta.egress","ion.outcome":"degraded",failed:Y.length,total:V.length,error:dt(Y[0]?.reason)}),{status:"degraded",reason:dt(Y[0]?.reason)};return{status:"ok"}}async function Ls(y,k){let R=Array(y.length),W=0,V=async()=>{while(!0){let H=W++;if(H>=y.length)return;let Y=y[H];if(!Y)continue;try{R[H]={status:"fulfilled",value:await Y()}}catch(Q){R[H]={status:"rejected",reason:Q}}}},G=Array.from({length:Math.min(k,y.length)},V);return await Promise.all(G),R}class an extends Error{constructor(y){super(y);this.name="DerivedRevokeError",Object.setPrototypeOf(this,an.prototype)}}class Ot extends Error{constructor(y,k,R=!1){super(y);this.name="ScimMutationError",this.summary=k,this.clientError=R,Object.setPrototypeOf(this,Ot.prototype)}}function Re(y,k,R){return new Response(JSON.stringify({schemas:[Bn],status:String(y),scimType:R,detail:k}),{status:y,headers:{"Content-Type":Kt}})}function ft(y,k){let R=k?.totalResults??y.length,W=k?.startIndex??1,V=k?.itemsPerPage??y.length;return new Response(JSON.stringify({schemas:[Ps],totalResults:R,startIndex:W,itemsPerPage:V,Resources:y}),{status:200,headers:{"Content-Type":Kt}})}function Xe(y,k=200,R){let W=new Headers({"Content-Type":Kt});if(R)W.set("Location",R);return new Response(JSON.stringify(y),{status:k,headers:W})}function yr(y){return Re(y.clientError?409:500,`${y.message}; authz mutation summary: ${JSON.stringify(y.summary)}`,y.clientError?"mutability":"invalidValue")}function Gt(y){return c(y)}function Wn(y,k){return on(hr(y),hr(k))}function hr(y){let k=new Map;if(!y?.id)return k;for(let R of y.groups??[]){let W={subject:y.id,subjectType:"user",targetType:"group",target:R.value,metadata:R.display||R.type?{display:R.display,type:R.type}:void 0};k.set(Gt(W),W)}for(let R of y.roles??[]){let W={subject:y.id,subjectType:"user",targetType:"role",target:R.value,metadata:R.display||R.type?{display:R.display,type:R.type,primary:R.primary}:void 0};k.set(Gt(W),W)}for(let R of y.entitlements??[]){let W={subject:y.id,subjectType:"user",targetType:"permission",target:R.value,metadata:R.display||R.type?{display:R.display,type:R.type,primary:R.primary}:void 0};k.set(Gt(W),W)}return k}class cn extends Error{constructor(y){super(y);this.name="AmbiguousMemberSubjectTypeError",Object.setPrototypeOf(this,cn.prototype)}}function Ns(y,k,R){if(y.type==="Group")return;if(y.type==="Workload")return"workload";if(y.type==="User")return"user";if(y.type==="Customer")return"customer";let W=k??[];if(W.length===1)return W[0];throw new cn(`SCIM Group member "${y.value}" of entitlement "${R}" omits type, and the entitlement is assignable to more than one principal kind [${W.join(", ")||"none"}]. Set members[].type to User, Workload, or Customer.`)}function nn(y,k,R,W,V){let G=new Map,H=W&&W.length>0?W:void 0;for(let Y of y??[]){let Q=Ns(Y,V,R);if(!Q)continue;let X={subject:Y.value,subjectType:Q,targetType:k,target:R,resources:H,metadata:Y.display||Y.type?{display:Y.display,type:Y.type}:void 0};G.set(Gt(X),X)}return G}function Vn(y){let k=y[e]?.resources;return k&&k.length>0?k:void 0}function Ws(y,k){let R=(V,G)=>[...V??[]].sort().join(",")===[...G??[]].sort().join(","),W=y[e];if(W?.type!==void 0&&W.type!==k.kind)return!0;if(W?.requestable!==void 0&&W.requestable!==k.entity.requestable)return!0;if(W?.resources!==void 0&&!R(W.resources,Jn(k.entity)))return!0;if(W?.assignableSubjectTypes!==void 0&&!R(W.assignableSubjectTypes,k.entity.assignableSubjectTypes))return!0;if(W?.recommendedSubjectTypes!==void 0&&!R(W.recommendedSubjectTypes,k.entity.recommendedSubjectTypes))return!0;return!1}function Vs(y,k){let R=(G,H)=>[...G??[]].sort().join(",")===[...H??[]].sort().join(","),W=y[e],V=k[e];if(W?.type!==void 0&&W.type!==V?.type)return!0;if(W?.requestable!==void 0&&W.requestable!==V?.requestable)return!0;if(W?.resources!==void 0&&!R(W.resources,V?.resources))return!0;if(W?.assignableSubjectTypes!==void 0&&!R(W.assignableSubjectTypes,V?.assignableSubjectTypes))return!0;if(W?.recommendedSubjectTypes!==void 0&&!R(W.recommendedSubjectTypes,V?.recommendedSubjectTypes))return!0;return!1}function qs(y){let k=new Map;for(let R of y)k.set(Gt(R),R);return k}async function Pt(y,k,R,W,V,G){let H=[],Y=new Set,Q=(Pe,xe)=>`${xe}\x00${Pe}`,X=G?G.get(`${R}:${W}`)??[]:k?(await k.listByTarget(R,W)).items:[];for(let Pe of X){let xe=n(Pe.subject),je=Pe.metadata,De=Pe.subjectType==="workload"?"Workload":Pe.subjectType==="customer"?"Customer":je?.type??"User",We=Q(xe,De);if(Y.has(We))continue;Y.add(We),H.push({value:xe,...je?.display?{display:je.display}:{},type:De})}for(let Pe of V??[]){if(Pe.targetType!==R||n(Pe.target)!==W)continue;let xe=n(Pe.subject),je=Q(xe,"Workload");if(Y.has(je))continue;Y.add(je),H.push({value:xe,type:"Workload"})}if(R==="group"){let Pe=await y.groups.get(W);for(let xe of Pe?.groups??[]){let je=n(xe),De=Q(je,"Group");if(!je||Y.has(De))continue;Y.add(De),H.push({value:je,type:"Group"})}}return H.length>0?H:void 0}function on(y,k){let R=[];for(let[W,V]of k)if(!y.has(W))R.push({action:"grant",change:V});for(let[W,V]of y)if(!k.has(W))R.push({action:"revoke",change:V});return R}async function qn(y,k){if(y.oaa.isReady())await y.oaa.pushUser(k)}async function Sr(y,k,R){if(k?.externalId&&k.externalId!==R.externalId)await y?.onUserDelete(k.externalId);await y?.onUserUpsert(R)}async function jt(y,k,R,W){let V={metadataApplied:!1,access:[]},G={status:"skipped"},H=[],Y=new _(y.catalogStore,y.resources,y.codeCatalog);try{try{await k(),V.metadataApplied=!0}catch(Q){for(let X of R)V.access.push({change:X.change,status:"rolled_back"});throw V.metadataApplied=!1,new Ot(`SCIM metadata write failed: ${dt(Q)}`,V,!1)}if(W?.oaa)await Ct(y,"authz.oaa.metadata","OAA metadata projection failed after SCIM write; full sync will reconcile",W.oaa);if(W?.delta&&y.iamDelta?.isReady())G=await Ct(y,"iam.delta.egress","IAM delta metadata projection failed after SCIM write; full aggregation will reconcile",W.delta);for(let Q=0;Q<R.length;Q++){let X=R[Q];try{if(X.action==="grant")await js(y,X.change,H,Y);else await Ks(y,X.change,H);V.access.push({change:X.change,status:"applied"})}catch(Pe){V.access.push({change:X.change,status:"failed",error:Pe});for(let je=Q+1;je<R.length;je++)V.access.push({change:R[je].change,status:"rolled_back"});let xe=Pe instanceof an||Pe instanceof Ht;if(!xe)await Bs(y,X.change,Y);throw new Ot(xe?dt(Pe):`SCIM access mutation failed: ${dt(Pe)}`,V,xe)}}return V}finally{await zs(y),V.egress=await sn(y,H),V.egress.delta=$s(G,V.egress.delta),Gs(y,V)}}function $s(y,k){if(y.status==="degraded")return y;if(k.status==="degraded")return k;return y.status==="ok"||k.status==="ok"?{status:"ok"}:{status:"skipped"}}function dt(y){return y instanceof Error?y.message:String(y)}async function zs(y){try{await y.settleAuthz?.()}catch{}}async function Bs(y,k,R){if(!y.accessIndex||!y.catalogStore&&!y.codeCatalog||!y.accessStore)return;let W=n(k.subject);if(!W)return;let V=k.subjectType;try{await z(W,V,{accessStore:y.accessStore,accessIndex:y.accessIndex,catalogStore:y.catalogStore,code:y.codeCatalog,resources:y.resources},R)}catch(G){y.log?.warn("Per-subject reconcile after failed SCIM access mutation failed",{"ion.operation":"authz.reconcile.subject.repair","ion.outcome":"degraded",subject:W,subjectType:V,error:dt(G)})}}function Gs(y,k){if(!y.onAccessMutation)return;try{y.onAccessMutation(k)}catch{}}async function Ks(y,k,R){if(y.accessStore){let W=k.id??c(k);if(!await y.accessStore.get(W)){if((y.accessIndex?await y.accessIndex.has(k.subject,k.targetType,k.target,k.resources?.[0],k.subjectType):{allow:!1}).allow)throw new an(`Cannot revoke ${k.targetType} "${n(k.target)}" for "${n(k.subject)}": it is not a directly granted root (it is derived from group/role membership). Remove the granting group/role instead.`);await Bt(y,k,R);return}}await Bt(y,k,R)}function _t(y){let k=y[e]?.type??"group";if(k==="group"||k==="role"||k==="permission")return k;throw Error(`Unsupported ionite SCIM Group authz type "${String(k)}"`)}async function $n(y,k,R){if(!y.oaa.isReady())return;if(R==="role"){await y.oaa.pushRole(k);return}if(R==="permission"){await y.oaa.pushPermission(k);return}await y.oaa.pushGroup(k)}function Jn(y){let k=y.resources;if(!k||k.length===0)return;let R=k.map((W)=>typeof W==="string"?W:W.id).filter(Boolean);return R.length>0?R:void 0}function xt(y,k,R){return _n(y,k,R)}function Js(y,k){let R=y[e],V={...r(R?.attributes??{},o),id:k,name:y.displayName,displayName:y.displayName,description:R?.description??y.displayName,requestable:R?.requestable,riskLevel:R?.riskLevel??u,providerId:R?.providerId??y.externalId,requestUrl:R?.requestUrl,assignableSubjectTypes:["user"]};if(R?.resources!==void 0)V.resources=R.resources;return V}function Hs(y){if(!y)return;let k=y.trim().match(/^requestable\s+eq\s+(true|false)$/i);if(!k)return;return{requestable:k[1]?.toLowerCase()==="true"}}function kr(y){if(!y)return;let k=y.trim().match(/^externalId\s+eq\s+"([^"]*)"$/i);return k?k[1]:void 0}function Fs(y){if(!y)return;let k=y.trim(),R=k.match(/^userName\s+eq\s+"([^"]*)"$/i);if(R)return{userName:R[1]};let W=k.match(/^externalId\s+eq\s+"([^"]*)"$/i);if(W)return{externalId:W[1]};let V=k.match(/^meta\.lastModified\s+gt\s+"([^"]*)"$/i);if(V)return{updatedAfter:V[1]};return}function Ys(y,k,R){let W=new Set(["id","schemas"]),V={...y};if(k){let G=new Set(k.split(",").map((H)=>H.trim()).filter(Boolean));for(let H of Object.keys(V))if(!W.has(H)&&!G.has(H))delete V[H]}if(R){for(let G of R.split(",").map((H)=>H.trim()).filter(Boolean))if(!W.has(G))delete V[G]}return V}function wr(y,k){let R=async(G,H,Y)=>{let Q=await y.toScim(G),X=G.id;return{...Q,id:X,meta:{...Q.meta??{},resourceType:y.resourceType,location:X?He(H,`${Y}/${encodeURIComponent(X)}`):void 0}}},W=(G,H)=>{let Y=H.op.toLowerCase();if(!H.path){if(Y!=="remove"&&H.value&&typeof H.value==="object"&&!Array.isArray(H.value))Object.assign(G,H.value);return}if(Y==="remove"){delete G[H.path];return}G[H.path]=H.value};return{handler:async(G,H)=>{if(!await k.validateAuth(G))return Re(401,"Authorization required");let Y=new URL(G.url),Q=H?.basePath??`/${y.resourceType}s`,X=Y.pathname;if(X.startsWith(Q))X=X.substring(Q.length);let Pe=X.match(/^\/([^/]+)$/),xe=Pe?.[1]?decodeURIComponent(Pe[1]):void 0,je=Y.searchParams.get("attributes"),De=Y.searchParams.get("excludedAttributes"),We=(ke)=>Ys(ke,je,De);try{if(xe){if(G.method==="GET"){let ke=await y.store.get(xe);if(!ke)return Re(404,`${y.resourceType} not found`);return Xe(We(await R(ke,G,Q)))}if(G.method==="PUT"||G.method==="PATCH"){let ke=await y.store.get(xe);if(!ke)return Re(404,`${y.resourceType} not found`);let Le=await G.json(),ye=Le;if(G.method==="PATCH"){let Ge=Le.Operations;if(!Array.isArray(Ge))return Re(400,"PATCH requires Operations","invalidSyntax");let Je=await y.toScim(ke);for(let nt of Ge)W(Je,nt);ye=Je}let _e=await bt(y.validator,ye);if(_e.issues)return Re(400,_e.issues.map((Ge)=>Ge.message).join("; "),"invalidValue");let Ne=G.method==="PATCH"?"patch":"replace",$e=await y.store.upsert({...await y.fromScim(_e.value,{existing:ke,mode:Ne}),id:ke.id??xe});if(ke.active!==$e.active)await k.accessIndex?.setSubjectDisabled?.($e.id,y.subjectType,$e.active===!1);let tt=$e.id?He(G,`${Q}/${encodeURIComponent($e.id)}`):void 0;for(let Ge of y.projections??[])await Ct(k,`${Ge.channel}.${y.subjectType}.upsert`,`${y.resourceType} projection degraded after SCIM upsert; aggregation will reconcile`,()=>Ge.upsert($e,ke));return Xe(We(await R($e,G,Q)),200,tt)}if(G.method==="DELETE"){let ke=await y.store.get(xe);if(!ke)return Re(404,`${y.resourceType} not found`);if(k.revokeSubjectAccess)await k.revokeSubjectAccess(xe,y.subjectType);await y.store.delete(xe),await k.accessIndex?.setSubjectDisabled?.(xe,y.subjectType,!1);for(let Le of y.projections??[])await Ct(k,`${Le.channel}.${y.subjectType}.delete`,`${y.resourceType} projection degraded after SCIM delete; aggregation will reconcile`,()=>Le.delete(ke));return new Response(null,{status:204})}return Re(405,"Method not allowed")}if(G.method==="GET"){let ke=parseInt(Y.searchParams.get("startIndex")??"",10),Le=parseInt(Y.searchParams.get("count")??"",10),ye=ke!=null&&!Number.isNaN(ke)?Math.max(0,ke-1):0,_e=Le!=null&&!Number.isNaN(Le)?Le:void 0,Ne=Fs(Y.searchParams.get("filter"));if(Ne?.externalId!==void 0){let Ge=y.store.getByExternalId?await y.store.getByExternalId(Ne.externalId):await y.store.lookup({externalId:Ne.externalId}),Je=Ge?[We(await R(Ge,G,Q))]:[];return ft(Je,{totalResults:Je.length,startIndex:1,itemsPerPage:Je.length})}let $e=await y.store.list({start:ye,limit:_e,filter:Ne}),tt=await Promise.all($e.items.map(async(Ge)=>We(await R(Ge,G,Q))));return ft(tt,{totalResults:$e.total,startIndex:ye+1,itemsPerPage:$e.count})}if(G.method==="POST"){let ke=await G.json(),Le=await bt(y.validator,ke);if(Le.issues)return Re(400,Le.issues.map((Ne)=>Ne.message).join("; "),"invalidValue");let ye=await y.store.upsert(await y.fromScim(Le.value,{mode:"create"}));if(ye.active===!1)await k.accessIndex?.setSubjectDisabled?.(ye.id,y.subjectType,!0);for(let Ne of y.projections??[])await Ct(k,`${Ne.channel}.${y.subjectType}.upsert`,`${y.resourceType} projection degraded after SCIM create; aggregation will reconcile`,()=>Ne.upsert(ye,void 0));let _e=ye.id?He(G,`${Q}/${encodeURIComponent(ye.id)}`):void 0;return Xe(We(await R(ye,G,Q)),201,_e)}return Re(405,"Method not allowed")}catch(ke){if(T(ke))return Re(409,ke.message,"uniqueness");return Re(500,ke instanceof Error?ke.message:"Internal error")}}}}async function Xs(y,k,R,W){let V=[],G=[["group",y.groups],["role",y.roles],["permission",y.permissions]];for(let[Y,Q]of G)for await(let X of i((Pe,xe)=>Q.list({start:Pe,limit:xe,filter:{requestable:!0}})))if(X.providerId===R)V.push({entity:X,type:Y});if(V.length>1)throw new m(`Ambiguous providerId "${R}": ${V.length} entitlements share it (${V.map((Y)=>`${Y.type}:${Y.entity.id}`).join(", ")})`,"unique_violation","providerId");let H=V[0];if(H?.entity.requestable!==!0)return;return xt(H.entity,H.type,await Pt(y,k,H.type,H.entity.id,W))}async function Zs(y,k,R,W){let V=Math.max(0,R.start),G=R.limit!=null?V+R.limit:void 0,H={start:0,limit:G,filter:R.filter},[Y,Q,X]=await Promise.all([y.groups.list(H),y.roles.list(H),y.permissions.list(H)]),Pe=[...Y.items.map((ke)=>({entity:ke,type:"group"})),...Q.items.map((ke)=>({entity:ke,type:"role"})),...X.items.map((ke)=>({entity:ke,type:"permission"}))],xe=Y.total+Q.total+X.total,je=Pe.slice(V,G),De=k?.listByTargets?await k.listByTargets(je.map(({entity:ke,type:Le})=>({targetType:Le,target:ke.id}))):void 0,We=await Promise.all(je.map(async({entity:ke,type:Le})=>xt(ke,Le,await Pt(y,k,Le,ke.id,W,De))));return{resources:We,total:xe,count:We.length}}async function zt(y,k,R,W){let[V,G,H]=await Promise.all([y.groups.get(R),y.roles.get(R),y.permissions.get(R)]);if(V)return xt(V,"group",await Pt(y,k,"group",R,W));if(G)return xt(G,"role",await Pt(y,k,"role",R,W));if(H)return xt(H,"permission",await Pt(y,k,"permission",R,W));return}async function zn(y,k,R,W){let V=_t(k),G=V==="role"?await y.roles.get(R):V==="permission"?await y.permissions.get(R):await y.groups.get(R),H=Js(k,R),Y=G?.assignableSubjectTypes&&G.assignableSubjectTypes.length>0?G.assignableSubjectTypes:["user"],Q={...G??{},...H,source:G?.source??"scim",assignableSubjectTypes:Y},X=W?W.displayName??W.name:G?.name;if(H.displayName===X)delete Q.displayName;if(H.riskLevel===(W?.riskLevel??u))delete Q.riskLevel;let Pe=r(H,o),xe=W?r(W,o):void 0;if(k[e]?.attributes!==void 0){for(let De of Object.keys(r(G??{},o)??{}))if(!(De in(Pe??{})))delete Q[De]}for(let[De,We]of Object.entries(Pe??{}))if(p(We,xe?.[De]))delete Q[De];if(W)Q.name=W.name;let je=V==="role"?y.roles.set(Q):V==="permission"?y.permissions.set(Q):y.groups.set(Q);return await je.ready(),je}async function Qs(y,k){await Promise.all([y.groups.delete(k),y.roles.delete(k),y.permissions.delete(k)])}function rn(){return crypto.randomUUID()}function bt(y,k){let R=y;if(typeof R.validate==="function")return R.validate(k);return Promise.resolve(y["~standard"].validate(k))}function ei(y){if(!y)return;try{return new URL(y).pathname}catch{return y.startsWith("/")?y:`/${y}`}}function ut(y){let k=ei(y);return k?C(k):void 0}function br(...y){for(let k of y){let R=ut(k);if(!R)continue;for(let W of["/Users","/Groups","/Workloads","/Customers"])if(R.endsWith(W))return R.slice(0,-W.length)}return}function He(y,k){return new URL(k,y.url).toString()}function ie(y,k,R,W){let{multiValued:V=!1,...G}=W??{};return{name:y,type:k,description:R,multiValued:V,...G}}function ti(y,k){return{schemas:[xs],documentationUri:k?.documentationUri,patch:{supported:!0},bulk:{supported:!1},filter:{supported:!0,maxResults:1000},changePassword:{supported:!1},sort:{supported:!1},etag:{supported:!1},authenticationSchemes:[{type:"oauthbearertoken",name:"OAuth Bearer Token",description:"Use an ionite workload bearer token for IAM discovery and provisioning requests.",primary:!0}],meta:{resourceType:"ServiceProviderConfig",location:He(y.request,`${y.basePath}/ServiceProviderConfig`)}}}function ni(y){let k=[];if(y.supportsUsers)k.push({schemas:[tn],id:"User",name:"User",description:"User Account",endpoint:y.usersUrl,schema:Gn,schemaExtensions:[{schema:Jt,required:!1},{schema:s,required:!1}],meta:{resourceType:"ResourceType",location:He(y.request,`${y.basePath}/ResourceTypes/User`)}});if(y.supportsGroups)k.push({schemas:[tn],id:"Group",name:"Group",description:"Group",endpoint:y.groupsUrl,schema:Kn,schemaExtensions:[{schema:e,required:!1}],meta:{resourceType:"ResourceType",location:He(y.request,`${y.basePath}/ResourceTypes/Group`)}});if(y.supportsWorkloads)k.push({schemas:[tn],id:"Workload",name:"Workload",description:"Workload (machine) principal",endpoint:y.workloadsUrl,schema:f,meta:{resourceType:"ResourceType",location:He(y.request,`${y.basePath}/ResourceTypes/Workload`)}});if(y.supportsCustomers)k.push({schemas:[tn],id:"Customer",name:"Customer",description:"Customer (CIAM) principal",endpoint:y.customersUrl,schema:g,meta:{resourceType:"ResourceType",location:He(y.request,`${y.basePath}/ResourceTypes/Customer`)}});return k}function ri(y){let k=[];if(y.supportsUsers)k.push({schemas:[Tt],id:Gn,name:"User",description:"User Account",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(Gn)}`)},attributes:[ie("id","string","Unique identifier for the User.",{multiValued:!1,required:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),ie("externalId","string","External identifier from the provisioning client.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",uniqueness:"none"}),ie("userName","string","Unique identifier typically used for login.",{multiValued:!1,required:!0,caseExact:!1,mutability:"readWrite",returned:"default",uniqueness:"server"}),ie("name","complex","The components of the user name.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",subAttributes:[ie("formatted","string","The full name, including titles and suffixes.",{multiValued:!1}),ie("familyName","string","The family name of the User.",{multiValued:!1}),ie("givenName","string","The given name of the User.",{multiValued:!1}),ie("middleName","string","The middle name(s) of the User.",{multiValued:!1}),ie("honorificPrefix","string","The honorific prefix(es) of the User.",{multiValued:!1}),ie("honorificSuffix","string","The honorific suffix(es) of the User.",{multiValued:!1})]}),ie("displayName","string","The name of the User, suitable for display.",{multiValued:!1}),ie("nickName","string","The casual way to address the user.",{multiValued:!1}),ie("profileUrl","reference","A URL pointing to the User profile.",{multiValued:!1,referenceTypes:["external"]}),ie("title","string","The user title, such as Vice President.",{multiValued:!1}),ie("userType","string","The relationship between the organization and the User.",{multiValued:!1}),ie("preferredLanguage","string","Preferred written or spoken language.",{multiValued:!1}),ie("locale","string","Default location for localizing values.",{multiValued:!1}),ie("timezone","string","The User time zone.",{multiValued:!1}),ie("active","boolean","The User administrative status.",{multiValued:!1}),ie("emails","complex","Email addresses for the User.",{multiValued:!0,subAttributes:[ie("value","string","Email address value.",{multiValued:!1,required:!0}),ie("display","string","Display label for the email.",{multiValued:!1}),ie("type","string","Email type such as work or home.",{multiValued:!1}),ie("primary","boolean","Primary email indicator.",{multiValued:!1})]}),ie("phoneNumbers","complex","Phone numbers for the User.",{multiValued:!0,subAttributes:[ie("value","string","Phone number value.",{multiValued:!1,required:!0}),ie("display","string","Display label for the phone number.",{multiValued:!1}),ie("type","string","Phone number type.",{multiValued:!1}),ie("primary","boolean","Primary phone number indicator.",{multiValued:!1})]}),ie("photos","complex","Photo URLs for the User.",{multiValued:!0,subAttributes:[ie("value","reference","Photo URL.",{multiValued:!1,required:!0,referenceTypes:["external"]}),ie("display","string","Display label for the photo.",{multiValued:!1}),ie("type","string","Photo type.",{multiValued:!1}),ie("primary","boolean","Primary photo indicator.",{multiValued:!1})]}),ie("addresses","complex","Physical mailing addresses for the User.",{multiValued:!0,subAttributes:[ie("formatted","string","Formatted mailing address.",{multiValued:!1}),ie("streetAddress","string","Full street address component.",{multiValued:!1}),ie("locality","string","City or locality.",{multiValued:!1}),ie("region","string","State or region.",{multiValued:!1}),ie("postalCode","string","Postal code.",{multiValued:!1}),ie("country","string","Country.",{multiValued:!1}),ie("type","string","Address type.",{multiValued:!1}),ie("primary","boolean","Primary address indicator.",{multiValued:!1})]}),ie("groups","complex","Groups to which the User belongs.",{multiValued:!0,mutability:"readOnly",subAttributes:[ie("value","string","Group identifier.",{multiValued:!1,required:!0}),ie("$ref","reference","Reference to the Group resource.",{multiValued:!1,referenceTypes:["Group"]}),ie("display","string","Display name of the group.",{multiValued:!1}),ie("type","string","Relationship type.",{multiValued:!1})]}),ie("entitlements","complex","Entitlements for the User.",{multiValued:!0,subAttributes:[ie("value","string","Entitlement value.",{multiValued:!1,required:!0}),ie("display","string","Display value.",{multiValued:!1}),ie("type","string","Entitlement type.",{multiValued:!1}),ie("primary","boolean","Primary entitlement indicator.",{multiValued:!1})]}),ie("roles","complex","Roles for the User.",{multiValued:!0,subAttributes:[ie("value","string","Role value.",{multiValued:!1,required:!0}),ie("display","string","Display value.",{multiValued:!1}),ie("type","string","Role type.",{multiValued:!1}),ie("primary","boolean","Primary role indicator.",{multiValued:!1})]}),ie("x509Certificates","complex","Certificates issued to the User.",{multiValued:!0,subAttributes:[ie("value","string","Certificate value.",{multiValued:!1,required:!0}),ie("display","string","Display value.",{multiValued:!1}),ie("type","string","Certificate type.",{multiValued:!1}),ie("primary","boolean","Primary certificate indicator.",{multiValued:!1})]})]}),k.push({schemas:[Tt],id:Jt,name:"EnterpriseUser",description:"Enterprise User extension",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(Jt)}`)},attributes:[ie("employeeNumber","string","Numeric or alphanumeric identifier assigned to a person.",{multiValued:!1}),ie("costCenter","string","Name of a cost center.",{multiValued:!1}),ie("organization","string","Name of an organization.",{multiValued:!1}),ie("division","string","Name of a division.",{multiValued:!1}),ie("department","string","Name of a department.",{multiValued:!1}),ie("manager","complex","The User manager.",{multiValued:!1,subAttributes:[ie("value","string","Identifier of the manager User resource.",{multiValued:!1}),ie("$ref","reference","Reference to the manager User resource.",{multiValued:!1,referenceTypes:["User"]}),ie("displayName","string","Display name of the manager.",{multiValued:!1})]})]}),k.push({schemas:[Tt],id:s,name:"IoniteUser",description:"ionite User extension carrying ECID, account purpose, and AppDev custom attributes. See https://ionite.com/docs/llms-ecid.txt.",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(s)}`)},attributes:[ie("ecid","string","Enterprise Controlled ID formatted as 'ecid:<realm>:<opaque>' (realm = the minting authority's id). Correlates multiple accounts to one identity.",{multiValued:!1,caseExact:!0}),ie("accountClass","string","Account purpose (distinct from userType persona). Open value set: 'daily', 'privileged', 'break_glass', 'service'.",{multiValued:!1}),ie("attributes","complex","AppDev custom attributes. IAM may override seeded values.",{multiValued:!1,required:!1,mutability:"readWrite"})]});if(y.supportsGroups)k.push({schemas:[Tt],id:e,name:"IoniteAuthzGroup",description:"ionite authorization metadata for SCIM Group resources.",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(e)}`)},attributes:[ie("type","string","Authorization entity kind: group, role, or permission.",{multiValued:!1,required:!1}),ie("requestable","boolean","Whether this catalog entry is exposed as assignable access to IAM tooling. Only true entries are served.",{multiValued:!1,required:!1}),ie("riskLevel","string",`Advisory access-risk classification. Unset values project as ${u}; canonical values are suggestions, not a closed enum.`,{multiValued:!1,required:!1,mutability:"readWrite",canonicalValues:[...U]}),ie("providerId","string","IAM service-provider id captured when this entitlement is materialized at the destination.",{multiValued:!1,required:!1,mutability:"readWrite"}),ie("requestUrl","reference","IAM-owned deep link where a principal can request this entitlement.",{multiValued:!1,required:!1,mutability:"readWrite",referenceTypes:["external"]}),ie("source","string","Provenance of the catalog row.",{multiValued:!1,required:!1,mutability:"readOnly",canonicalValues:["code","app","scim"]}),ie("deprecated","boolean","Whether this retired entitlement may be deleted.",{multiValued:!1,required:!1,mutability:"readOnly"}),ie("description","string","Human-readable authorization entity description.",{multiValued:!1,required:!1}),ie("resources","string","Resource ids this entitlement is scoped to.",{multiValued:!0,required:!1}),ie("assignableSubjectTypes","string","AppDev-owned required audience of principal kinds (user, workload, customer) that may hold this entitlement. Read-only to IAM tooling.",{multiValued:!0,required:!1,mutability:"readOnly",canonicalValues:["user","customer","workload"]}),ie("recommendedSubjectTypes","string","AppDev advisory default principal kinds (subset of assignableSubjectTypes). Read-only to IAM tooling.",{multiValued:!0,required:!1,mutability:"readOnly",canonicalValues:["user","customer","workload"]}),ie("attributes","complex","AppDev custom attributes. IAM may override seeded values.",{multiValued:!1,required:!1,mutability:"readWrite"})]});if(y.supportsGroups)k.push({schemas:[Tt],id:Kn,name:"Group",description:"Group",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(Kn)}`)},attributes:[ie("id","string","Unique identifier for the Group.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),ie("externalId","string","External identifier from the provisioning client.",{multiValued:!1,uniqueness:"none"}),ie("displayName","string","Human-readable name for the Group.",{multiValued:!1,required:!0,uniqueness:"none"}),ie("members","complex","Members of the Group.",{multiValued:!0,subAttributes:[ie("value","string","Identifier of the member resource.",{multiValued:!1,required:!0}),ie("$ref","reference","Reference to the member resource.",{multiValued:!1,referenceTypes:["User","Group","Workload","Customer"]}),ie("display","string","Display name of the member.",{multiValued:!1}),ie("type","string","Member type.",{multiValued:!1})]})]});if(y.supportsWorkloads)k.push({schemas:[Tt],id:f,name:"Workload",description:"Workload (machine) principal",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(f)}`)},attributes:[ie("id","string","Unique identifier for the Workload.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),ie("externalId","string","External identifier from the provisioning client.",{multiValued:!1}),ie("userName","string","Login identifier, typically the OAuth clientId.",{multiValued:!1}),ie("displayName","string","Human-readable name for the Workload.",{multiValued:!1}),ie("description","string","Free-form description of the Workload.",{multiValued:!1}),ie("active","boolean","Administrative status of the Workload.",{multiValued:!1}),ie("attributes","complex","AppDev custom attributes.",{multiValued:!1,required:!1,mutability:"readWrite"})]});if(y.supportsCustomers)k.push({schemas:[Tt],id:g,name:"Customer",description:"Customer (CIAM) principal",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(g)}`)},attributes:[ie("id","string","Unique identifier for the Customer.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),ie("externalId","string","External identifier from the provisioning client.",{multiValued:!1}),ie("userName","string","Unique identifier typically used for login.",{multiValued:!1}),ie("displayName","string","Human-readable name for the Customer.",{multiValued:!1}),ie("active","boolean","Administrative status of the Customer.",{multiValued:!1}),ie("emails","complex","Email addresses for the Customer.",{multiValued:!0,subAttributes:[ie("value","string","Email address.",{multiValued:!1,required:!0}),ie("primary","boolean","Whether this is the primary email.",{multiValued:!1})]}),ie("attributes","complex","AppDev custom attributes.",{multiValued:!1,required:!1,mutability:"readWrite"})]});return k}function si(y,k,R,W,V,G,H,Y,Q,X,Pe,xe,je,De,We){let ke={authz:W,settleAuthz:We,accessStore:V,accessIndex:G,catalogStore:H,codeCatalog:Y,resources:Q,log:k,iamDelta:xe,onAccessMutation:je};if(!X&&!Pe)return;let ye={...X,...Pe},_e=ye.users?.enabled!==!1,Ne=ye.groups?.enabled!==!1,$e=ye.workloads?.enabled!==!1,tt=ye.customers?.enabled!==!1;if(Boolean(ye.url||ye.userStore||H||Y)&&!R)k.error("IAM requires workload identity for SCIM push/pull operations",{"ion.operation":"workload.require","ion.outcome":"failure"});function Je(){if(!R)throw k.error("IAM requires workload identity for SCIM push/pull operations",{"ion.operation":"workload.require","ion.outcome":"failure"}),Error("IAM requires workload identity for SCIM push/pull operations");return R}async function nt(Se){let ve=Je(),M=Se.headers.get("Authorization");if(!M?.startsWith("Bearer "))return!1;try{let B=M.substring(7);return(await ve.validateToken(B)).valid}catch{return!1}}async function Ut(){let Se=Je(),ve=typeof Se.getServerToken==="function"?await Se.getServerToken():await Se.getToken();return new Headers({"Content-Type":Kt,Accept:Kt,Authorization:`Bearer ${ve}`})}async function Rt(Se,ve,M,B){if(!ye.url)throw Error("IAM URL not configured for outgoing requests");let J=`${ye.url}${ve}`;try{let F=await Ut(),ne=await fetch(J,{method:Se,headers:F,body:M?JSON.stringify(M):void 0}),pe=await ne.json();if(!ne.ok)return{success:!1,error:pe,status:ne.status};let de=await B["~standard"].validate(pe);if(de.issues)return k.error("SCIM response validation failed",{"ion.operation":"scim.response.validate","ion.outcome":"failure",validationIssues:de.issues}),{success:!1,error:{schemas:[Bn],status:"400",scimType:"invalidValue",detail:`Response validation failed: ${de.issues.map((re)=>re.message).join("; ")}`},status:400};return{success:!0,data:de.value,status:ne.status}}catch(F){return{success:!1,error:{schemas:[Bn],status:"500",detail:F instanceof Error?F.message:"Unknown error occurred"},status:500}}}function Et(){return ye.url}function Dt(Se,ve){let M=ut(ve?.usersUrl??ye.usersUrl??"/api/iam/Users")??"/api/iam/Users",B=ut(ve?.groupsUrl??ye.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",J=ut(ve?.workloadsUrl??ye.workloadsUrl??"/api/iam/Workloads")??"/api/iam/Workloads",F=ut(ve?.customersUrl??ye.customersUrl??"/api/iam/Customers")??"/api/iam/Customers",ne=ut(ve?.discovery?.basePath??ye.discovery?.basePath)??br(M,B,J,F);if(!ne)return;return{request:Se,basePath:ne,usersUrl:M,groupsUrl:B,workloadsUrl:J,customersUrl:F,supportsUsers:_e&&Boolean(ye.userStore),supportsGroups:Ne&&Boolean(H||Y),supportsWorkloads:$e&&Boolean(ye.workloadIdentityStore),supportsCustomers:tt&&Boolean(ye.customerStore)}}async function Lt(Se){let ve=ti(Se,ye.discovery);return await ye.discovery?.buildServiceProviderConfig?.(Se,ve)??ve}async function ot(Se){let ve=ni(Se);return await ye.discovery?.buildResourceTypes?.(Se,ve)??ve}async function vt(Se){let ve=ri(Se);return await ye.discovery?.buildSchemas?.(Se,ve)??ve}async function gt(Se,ve){let M=Dt(Se,ve);if(!M)return;let B=C(new URL(Se.url).pathname),{basePath:J}=M;if(B!==J&&!B.startsWith(`${J}/`))return;let F=C(B.slice(J.length)||"/");if(!(F==="/ServiceProviderConfig"||F==="/ResourceTypes"||F.startsWith("/ResourceTypes/")||F==="/Schemas"||F.startsWith("/Schemas/")))return;if(Se.method!=="GET")return Re(405,"Method not allowed");if(!await nt(Se))return Re(401,"Authorization required");if(F==="/ServiceProviderConfig")return Xe(await Lt(M));if(F==="/ResourceTypes")return ft(await ot(M));if(F.startsWith("/ResourceTypes/")){let de=decodeURIComponent(F.slice(15)),re=(await ot(M)).find((se)=>se.id===de||se.name===de);return re?Xe(re):Re(404,"Resource not found")}if(F==="/Schemas")return ft(await vt(M));if(F.startsWith("/Schemas/")){let de=decodeURIComponent(F.slice(9)),re=(await vt(M)).find((se)=>se.id===de);return re?Xe(re):Re(404,"Resource not found")}return}let at,It;if(ye.url)It=async(ve,M)=>{let B={...ve,schemas:ve.schemas??["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"]};return Rt("POST","/Users",B,y.user)},at={createGroup:async(ve,M)=>{let B={schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],displayName:ve,externalId:M?.id,members:M?.members};return Rt("POST","/Groups",B,y.group)}};let lt;if(H||Y){let Se=x(Y,H),ve=(ae,ee,oe)=>{let ue=ae[e]??{},ce=_t(ae),he=ae.id,we=he?He(ee,`${oe}/${encodeURIComponent(he)}`):void 0,ge={id:he??ae.externalId??ae.displayName,name:ae.displayName,displayName:ae.displayName,description:ue.description??ae.displayName,requestable:ue.requestable,providerId:ue.providerId??ae.externalId,requestUrl:ue.requestUrl,source:ue.source,deprecated:ue.deprecated,riskLevel:ue.riskLevel,assignableSubjectTypes:ue.assignableSubjectTypes,recommendedSubjectTypes:ue.recommendedSubjectTypes},Ce=ue.requestUrl??ye.entitlementRequestUrl?.(ge,ce,{request:ee});return{...ae,meta:{...ae.meta,resourceType:"Group",location:we},[e]:{...ue,requestUrl:Ce}}},M=(ae)=>A(Y,ae),B=async(ae,ee)=>{if(!H){if(ee)throw Error(`Cannot persist access for code entitlement "${ae.entity.id}": no AccessCatalogStore is wired.`);return ae.entity}try{return await v(ae.kind,ae.entity,I(H,ae.kind))}catch(oe){if(ee)throw oe;return k.warn("Code entitlement discovery materialization failed; serving the code template",{"ion.operation":"iam.catalog.materialize","ion.outcome":"degraded",entitlementId:ae.entity.id,entitlementType:ae.kind,error:dt(oe)}),ae.entity}},J=async(ae)=>{if(!H)return;try{await j(Y,H,ae)}catch(ee){k.warn("Retired code entitlement deprecation failed; serving the last durable row",{"ion.operation":"iam.catalog.deprecate","ion.outcome":"degraded",entitlementId:ae,error:dt(ee)})}},F=(ae,ee)=>Re(403,`Entitlement "${ae}" is declared in application code; its structural definition cannot be ${ee} through SCIM. IAM may change presentation and receipts, while code continues to own structure.`,"mutability"),ne=(ae)=>ae.path==="members"||Boolean(ae.path?.startsWith("members[")),pe=(ae)=>ne(ae)||ae.path==="displayName"||ae.path===`${e}.description`||ae.path===`${e}.riskLevel`||ae.path===`${e}.providerId`||ae.path===`${e}.requestUrl`||ae.path===`${e}.attributes`||Boolean(ae.path?.startsWith(`${e}.attributes.`)),de=(ae)=>ae?.[e]?.requestable===!0,re=(ae)=>Re(404,`Requestable Group ${ae} not found`,"invalidValue"),se=async(ae,ee)=>{if(!await nt(ae))return Re(401,"Authorization required");let ue=new URL(ae.url),ce=ee?.basePath??"/Groups",he=ue.pathname;if(he.startsWith(ce))he=he.substring(ce.length);let ge=he.match(/^\/([^/]+)$/)?.[1],Ce=ae.method;try{if(ge)switch(Ce){case"GET":return await be(ae,ce,ge);case"PUT":return await Ie(ae,ce,ge);case"PATCH":return await Oe(ae,ce,ge);case"DELETE":return await Ee(ge);default:return Re(405,"Method not allowed")}else if(he===""||he==="/")switch(Ce){case"GET":return await fe(ae,ce);case"POST":return await me(ae,ce);default:return Re(405,"Method not allowed")}return Re(404,"Resource not found")}catch(Ae){if(Ae instanceof Ot)return yr(Ae);if(Ae instanceof cn)return Re(400,Ae.message,"invalidValue");if(T(Ae))return Re(409,Ae.message,"uniqueness");return k.error("Groups inbound handler error",{"ion.operation":"scim.groups.handler","ion.outcome":"failure"},Ae),Re(500,Ae instanceof Error?Ae.message:"Internal server error")}},fe=async(ae,ee)=>{let oe=new URL(ae.url),ue=oe.searchParams.get("startIndex"),ce=oe.searchParams.get("count"),he=ue!=null?parseInt(ue,10):void 0,we=ce!=null?parseInt(ce,10):void 0,ge=he!=null&&!Number.isNaN(he)?Math.max(0,he-1):0,Ce=we!=null&&!Number.isNaN(we)?we:void 0,Ae=oe.searchParams.get("filter"),Me=kr(Ae);if(Me!==void 0){await J();let Te=await Xs(Se,V,Me,De),Ke=Te?[ve(Te,ae,ee)]:[];return ft(Ke,{totalResults:Ke.length,startIndex:1,itemsPerPage:Ke.length})}if(Hs(Ae)?.requestable===!1)return ft([],{totalResults:0,startIndex:1,itemsPerPage:0});let Qe={requestable:!0};if(Y)await Promise.all([...Y.groups.list().filter((Te)=>Te.requestable===!0).map((Te)=>({entity:Te,kind:"group"})),...Y.roles.list().filter((Te)=>Te.requestable===!0).map((Te)=>({entity:Te,kind:"role"})),...Y.permissions.list().filter((Te)=>Te.requestable===!0).map((Te)=>({entity:Te,kind:"permission"}))].map((Te)=>B(Te,!1)));await J();let Ve=await Zs(Se,V,{start:ge,limit:Ce,filter:Qe},De);return ft(Ve.resources.map((Te)=>ve(Te,ae,ee)),{totalResults:Ve.total,startIndex:ge+1,itemsPerPage:Ve.count})},be=async(ae,ee,oe)=>{let ue=M(oe);if(ue&&ue.entity.requestable!==!0)return re(oe);if(ue)await B(ue,!1);await J(oe);let ce=await zt(Se,V,oe,De);if(!de(ce))return re(oe);return Xe(ve(ce,ae,ee))},me=async(ae,ee)=>{let oe=await ae.json(),ue=await bt(y.group,oe);if(ue.issues)return k.error("Group creation validation failed",{"ion.operation":"scim.group.create","ion.outcome":"failure",validationIssues:ue.issues}),Re(400,`Request validation failed: ${ue.issues.map((Ve)=>Ve.message).join("; ")}`,"invalidValue");let ce=ue.value;if(!ce.displayName)return Re(400,"displayName is required","invalidValue");if(ce[e]?.requestable===!1)return Re(400,"SCIM may create only requestable entitlements; non-requestable definitions are App-owned.","invalidValue");if(ce[e]={...ce[e],requestable:!0},!H)return Re(501,"Group creation is not supported: this application declares its catalog in code (authz.catalog) and wires no AccessCatalogStore for SCIM-authored definitions.","invalidValue");let we=_t(ce),ge=rn();if(M(ge))throw new m(`id "${ge}" is reserved by the code catalog`,"unique_violation","id");let Ce=Vn(ce),Ae=on(new Map,nn(ce.members,we,ge,Ce,ce[e]?.assignableSubjectTypes)),Me;await jt(ke,async()=>{Me=await zn(Se,ce,ge)},Ae,{oaa:()=>$n(W,Me,we)});let ze=await Pt(Se,V,we,ge),Qe=ve(xt(Me,we,ze),ae,ee);return Xe(Qe,201,Qe.meta?.location)},Ie=async(ae,ee,oe)=>{let ue=await ae.json(),ce=await bt(y.group,ue);if(ce.issues)return k.error("Group replacement validation failed",{"ion.operation":"scim.group.replace","ion.outcome":"failure",validationIssues:ce.issues}),Re(400,`Request validation failed: ${ce.issues.map((Ke)=>Ke.message).join("; ")}`,"invalidValue");let he=ce.value,we=_t(he),ge=M(oe);if(ge&&ge.entity.requestable!==!0)return re(oe);if(ge){if(await B(ge,!0),Ws(he,ge))return F(oe,"replaced")}let Ce=await zt(Se,V,oe);if(!de(Ce))return re(oe);if(!ge&&Ce[e]?.source==="code"&&Vs(he,Ce))return F(oe,"replaced");let Ae=ge?.kind??we,Me=ge?Jn(ge.entity):Vn(he),ze=V?(await V.listByTarget(Ae,oe)).items:[],Qe=on(qs(ze),nn(he.members,Ae,oe,Me,ge?.entity.assignableSubjectTypes??Ce[e]?.assignableSubjectTypes??he[e]?.assignableSubjectTypes)),Ve;await jt(ke,async()=>{Ve=await zn(Se,he,oe,ge?.entity)},Qe,{oaa:()=>$n(W,Ve,Ae)});let Te=await Pt(Se,V,Ae,oe);return Xe(ve(xt(Ve,Ae,Te),ae,ee))},Oe=async(ae,ee,oe)=>{let ue=M(oe);if(ue&&ue.entity.requestable!==!0)return re(oe);if(ue)await B(ue,!0);let ce=await zt(Se,V,oe);if(!de(ce))return re(oe);let he=await ae.json();if((ue!==void 0||ce[e]?.source==="code")&&(he.Operations??[]).some((Ue)=>!pe(Ue)))return F(oe,"patched");let ge={...ce};for(let Ue of he.Operations??[])if(Ue.op==="replace"&&Ue.path&&Ue.value!==void 0){if(Ue.path==="displayName")ge.displayName=Ue.value;else if(Ue.path===`${e}.requestable`)ge[e]={...ge[e],requestable:Boolean(Ue.value)};else if(Ue.path===`${e}.description`)ge[e]={...ge[e],description:String(Ue.value)};else if(Ue.path===`${e}.riskLevel`)ge[e]={...ge[e],riskLevel:String(Ue.value)};else if(Ue.path===`${e}.providerId`)ge[e]={...ge[e],providerId:String(Ue.value)};else if(Ue.path===`${e}.requestUrl`)ge[e]={...ge[e],requestUrl:String(Ue.value)};else if(Ue.path===`${e}.attributes`&&typeof Ue.value==="object"&&Ue.value!==null&&!Array.isArray(Ue.value))ge[e]={...ge[e],attributes:Ue.value};else if(Ue.path.startsWith(`${e}.attributes.`)){let qe=Ue.path.slice(`${e}.attributes.`.length);ge[e]={...ge[e],attributes:{...ge[e]?.attributes,[qe]:Ue.value}}}}else if(Ue.op==="add"&&Ue.path==="members"&&Ue.value!==void 0){let qe=Ue.value;ge.members=[...ge.members??[],...qe]}else if(Ue.op==="remove"&&Ue.path?.startsWith("members[")){let qe=Ue.path.match(/members\[value eq "([^"]+)"\]/);if(qe)ge.members=(ge.members??[]).filter((St)=>St.value!==qe[1])}else if(Ue.op==="remove"&&Ue.path?.startsWith(`${e}.attributes.`)){let qe=Ue.path.slice(`${e}.attributes.`.length),St={...ge[e]?.attributes};delete St[qe],ge[e]={...ge[e],attributes:St}}let Ce=await bt(y.group,ge);if(Ce.issues)return k.error("Group patch validation failed",{"ion.operation":"scim.group.patch","ion.outcome":"failure",validationIssues:Ce.issues}),Re(400,`Request validation failed: ${Ce.issues.map((Ue)=>Ue.message).join("; ")}`,"invalidValue");let Ae=ue?.kind??_t(ge),Me=ue?Jn(ue.entity):Vn(ge),ze=ue?.entity.assignableSubjectTypes??ce[e]?.assignableSubjectTypes??ge[e]?.assignableSubjectTypes,Qe=on(nn(ce.members,Ae,oe,Me,ze),nn(ge.members,Ae,oe,Me,ze)),Ve,Te=!ue||(he.Operations??[]).some((Ue)=>!ne(Ue));await jt(ke,async()=>{if(Te)Ve=await zn(Se,ge,oe,ue?.entity)},Qe,Te?{oaa:()=>$n(W,Ve,Ae)}:void 0);let Ke=await zt(Se,V,oe);return Xe(ve(Ke,ae,ee))},Ee=async(ae)=>{let ee=M(ae);if(ee&&ee.entity.requestable!==!0)return re(ae);if(ee)await B(ee,!0);let oe=await zt(Se,V,ae);if(!de(oe))return re(ae);let ue=oe[e];if((ee||ue?.source==="code")&&ue?.deprecated!==!0)return Re(403,`Code-owned entitlement "${ae}" can be deleted only after it is marked deprecated.`,"mutability");let ce=_t(oe);if(V){let he=await V.listByTarget(ce,ae),we=[];for(let ge of he.items)await Bt(ke,ge,we);await sn(ke,we)}return await Qs(Se,ae),new Response(null,{status:204})};lt={handler:se}}let Ze,yt,ct;if(ye.userStore){let{userStore:Se,inboundUsers:ve}=ye,M=(ee)=>ee?.find((oe)=>oe.primary)?.value||ee?.[0]?.value,B=async(ee)=>{if(ve?.mapBaseUserToScim)return await ve.mapBaseUserToScim(ee);return On(ee)},J=async(ee,oe,ue)=>{let ce=await B(ee),he=ce.id??ee.id;return{...ce,id:he,meta:{...ce.meta,resourceType:"User",location:he?He(oe,`${ue}/${encodeURIComponent(he)}`):void 0}}},F=async(ee,oe)=>{if(ve?.mapValidatedScimToBaseUser)return await ve.mapValidatedScimToBaseUser(ee,oe);let ue=new Date,ce=M(ee.emails),he=ee.name?.formatted||[ee.name?.givenName,ee.name?.middleName,ee.name?.familyName].filter(Boolean).join(" ").trim()||ee.displayName,we=ee.id||oe.existing?.id||rn(),ge=ee.userName||ce||oe.existing?.userName||we,Ce=he||ee.displayName||oe.existing?.name||ge,Ae=Object.fromEntries(Object.entries(ee).filter(([Ke,Ue])=>Ke.startsWith("urn:")&&Ke!==Jt&&Ke!==s&&Ue!==void 0)),Me=ee[s],ze=r(Me?.attributes??{},h),Qe=Me?.ecid!==void 0&&Me.ecid!==null?w(Me.ecid):oe.existing?.ecid,Ve=Me?.accountClass??oe.existing?.accountClass,Te=oe.existing?.sso;return{...oe.existing??{},id:we,userName:ge,name:Ce,email:ce||oe.existing?.email||ge,avatar:ee.profileUrl,sso:{...Te??{},profile:{...Te?.profile??{},sub:we,iss:Te?.profile.iss??"iam-provisioned",aud:Te?.profile.aud??"iam-provisioned",exp:Te?.profile.exp??Math.floor(Date.now()/1000)+3600,iat:Te?.profile.iat??Math.floor(Date.now()/1000),email:ce||oe.existing?.email||ge,email_verified:!0,name:Ce,preferred_username:ge},tenant:Te?.tenant??{id:"iam-provisioned",name:"IAM Provisioned"},scope:Te?.scope??"openid profile email",tokenType:Te?.tokenType??"Bearer",expires:Te?.expires??new Date(Date.now()+3600000)},externalId:ee.externalId,ecid:Qe,accountClass:Ve,displayName:ee.displayName,scimName:ee.name,emails:ee.emails,nickName:ee.nickName,title:ee.title,preferredLanguage:ee.preferredLanguage,locale:ee.locale,timezone:ee.timezone,active:ee.active,phoneNumbers:ee.phoneNumbers,ims:ee.ims,photos:ee.photos,addresses:ee.addresses,groups:ee.groups,entitlements:ee.entitlements,roles:ee.roles,x509Certificates:ee.x509Certificates,scimEnterprise:ee[Jt],scimSchemaExtensions:Object.keys(Ae).length>0?Ae:void 0,createdAt:oe.existing?.createdAt??(ee.meta?.created?new Date(ee.meta.created):ue),updatedAt:ee.meta?.lastModified?new Date(ee.meta.lastModified):ue,userType:ee.userType,...ze}},ne=(ee,oe,ue)=>{ee[oe]=ue},pe=(ee,oe,ue)=>{let ce=ee[oe];if(Array.isArray(ce)){ee[oe]=[...ce,...Array.isArray(ue)?ue:[ue]];return}if(ce&&typeof ce==="object"&&!Array.isArray(ce)&&ue&&typeof ue==="object"&&!Array.isArray(ue)){ee[oe]={...ce,...ue};return}ee[oe]=ue},de=(ee,oe,ue)=>{let ce=oe.match(/^(urn:.*:(?:User|Group))(?::(.+))?$/),he=ce?[ce[1],...ce[2]?.split(":")??[]]:oe.split("."),we=ee;for(let Ce of he.slice(0,-1)){let Ae=we[Ce];if(Ae===void 0){if(!ue)return null;we[Ce]={}}else if(Ae===null||typeof Ae!=="object"||Array.isArray(Ae)){if(!ue)return null;we[Ce]={}}we=we[Ce]}let ge=he.at(-1);if(!ge)return null;return{parent:we,key:ge}},re=(ee,oe)=>{let ue=oe.op.toLowerCase();if(!oe.path){if(ue!=="remove"&&oe.value&&typeof oe.value==="object"&&!Array.isArray(oe.value))Object.assign(ee,oe.value);return}let ce=oe.path.match(/^([A-Za-z0-9]+)\[value eq "([^"]+)"\]$/);if(ce&&ue==="remove"){let[,we,ge]=ce,Ce=ee[we];if(Array.isArray(Ce))ee[we]=Ce.filter((Ae)=>!(Ae&&typeof Ae==="object"&&("value"in Ae)&&Ae.value===ge));return}let he=de(ee,oe.path,ue!=="remove");if(!he)return;if(ue==="remove"){delete he.parent[he.key];return}if(ue==="add"){pe(he.parent,he.key,oe.value);return}ne(he.parent,he.key,oe.value)},se=async(ee,oe)=>{if(!await nt(ee))return Re(401,"Authorization required");let ce=new URL(ee.url),he=oe?.basePath??"/Users",we=ce.pathname;if(we.startsWith(he))we=we.substring(he.length);let Ce=we.match(/^\/([^/]+)$/)?.[1],Ae=ee.method;try{if(Ce)switch(Ae){case"GET":return await be(ee,he,Ce);case"PUT":return await Oe(ee,he,Ce);case"PATCH":return await Ee(ee,he,Ce);case"DELETE":return await ae(Ce);default:return Re(405,"Method not allowed")}else if(we===""||we==="/")switch(Ae){case"GET":return await fe(ee,he);case"POST":return await Ie(ee,he);default:return Re(405,"Method not allowed")}return Re(404,"Resource not found")}catch(Me){if(Me instanceof Ot)return yr(Me);if(T(Me))return Re(409,Me.message,"uniqueness");return k.error("Users inbound handler error",{"ion.operation":"scim.users.handler","ion.outcome":"failure"},Me),Re(500,Me instanceof Error?Me.message:"Internal server error")}},fe=async(ee,oe)=>{let ue=new URL(ee.url),ce=ue.searchParams.get("startIndex"),he=ue.searchParams.get("count"),we=ce!=null?parseInt(ce,10):void 0,ge=he!=null?parseInt(he,10):void 0,Ce=we!=null&&!Number.isNaN(we)?Math.max(0,we-1):0,Ae=ge!=null&&!Number.isNaN(ge)?ge:void 0,Me=kr(ue.searchParams.get("filter"));if(Me!==void 0){let Ve=await Se.lookup({externalId:Me}),Te=Ve?[await J(Ve,ee,oe)]:[];return ft(Te,{totalResults:Te.length,startIndex:1,itemsPerPage:Te.length})}let ze=await Se.list({start:Ce,limit:Ae}),Qe=await Promise.all(ze.items.map((Ve)=>J(Ve,ee,oe)));return ft(Qe,{totalResults:ze.total,startIndex:Ce+1,itemsPerPage:ze.count})},be=async(ee,oe,ue)=>{let ce=await Se.get(ue);if(!ce)return Re(404,`User ${ue} not found`,"invalidValue");return Xe(await J(ce,ee,oe))},me=async(ee,oe)=>{let ue=ke.accessIndex;if(!ue?.setSubjectDisabled||!oe.id)return;let ce=ee?ee.active??!0:!0,he=oe.active??!0;if(ee&&ce===he)return;if(!ee&&he)return;await ue.setSubjectDisabled(oe.id,"user",!he)},Ie=async(ee,oe)=>{let ue=await ee.json(),ce=await bt(y.user,ue);if(ce.issues)return k.error("User creation validation failed",{"ion.operation":"scim.user.create","ion.outcome":"failure",validationIssues:ce.issues}),Re(400,`Request validation failed: ${ce.issues.map((Ce)=>Ce.message).join("; ")}`,"invalidValue");let he=ce.value;if(!he.userName&&!he.emails?.[0]?.value)return Re(400,"userName or email is required","invalidValue");let we=await F(he,{mode:"create"});await jt(ke,async()=>{await Se.upsert(we),await me(void 0,we)},Wn(void 0,we),{oaa:async()=>{await qn(W,we)},delta:async()=>{await ke.iamDelta?.onUserUpsert(we)}});let ge=await J(we,ee,oe);return Xe(ge,201,ge.meta?.location)},Oe=async(ee,oe,ue)=>{let ce=await Se.get(ue);if(!ce)return Re(404,`User ${ue} not found`,"invalidValue");let he=await ee.json(),we=await bt(y.user,he);if(we.issues)return k.error("User replacement validation failed",{"ion.operation":"scim.user.replace","ion.outcome":"failure",validationIssues:we.issues}),Re(400,`Request validation failed: ${we.issues.map((Ae)=>Ae.message).join("; ")}`,"invalidValue");let ge=we.value,Ce=await F({...ge,id:ue},{existing:ce,mode:"replace"});return Ce.createdAt=ce.createdAt,Ce.updatedAt=new Date,await jt(ke,async()=>{await Se.upsert(Ce),await me(ce,Ce)},Wn(ce,Ce),{oaa:async()=>{await qn(W,Ce)},delta:async()=>{await Sr(ke.iamDelta,ce,Ce)}}),Xe(await J(Ce,ee,oe))},Ee=async(ee,oe,ue)=>{let ce=await Se.get(ue);if(!ce)return Re(404,`User ${ue} not found`,"invalidValue");let we=(await ee.json()).Operations??[],Ce={...await B(ce)};for(let ze of we)re(Ce,ze);let Ae=await bt(y.user,Ce);if(Ae.issues)return k.error("User patch validation failed",{"ion.operation":"scim.user.patch","ion.outcome":"failure",validationIssues:Ae.issues}),Re(400,`Request validation failed: ${Ae.issues.map((ze)=>ze.message).join("; ")}`,"invalidValue");let Me=await F(Ae.value,{existing:ce,mode:"patch"});return Me.updatedAt=new Date,await jt(ke,async()=>{await Se.upsert(Me),await me(ce,Me)},Wn(ce,Me),{oaa:async()=>{await qn(W,Me)},delta:async()=>{await Sr(ke.iamDelta,ce,Me)}}),Xe(await J(Me,ee,oe))},ae=async(ee)=>{let oe=await Se.get(ee);if(!oe)return Re(404,`User ${ee} not found`,"invalidValue");if(V){let ue=[];for await(let ce of i((he,we)=>V.listBySubject(ee,"user",{start:he,limit:we})))await Bt(ke,ce,ue);await sn(ke,ue)}if(await Se.delete(ee),await ke.accessIndex?.setSubjectDisabled?.(ee,"user",!1),oe.externalId&&ke.iamDelta?.isReady())await Ct(ke,"iam.delta.egress","IAM delta user delete failed after SCIM write; full aggregation will reconcile",()=>ke.iamDelta?.onUserDelete(oe.externalId)??Promise.resolve(),{id:ee,kind:"user"});else if(ke.iamDelta?.isReady())ke.log?.warn("IAM delta: deleted User has no externalId; destination delete skipped",{"ion.operation":"iam.delta.delete","ion.outcome":"skipped",id:ee,kind:"user"});if(ke.authz.oaa.isReady())await Ct(ke,"authz.oaa.delete","OAA incremental user delete failed; full sync will reconcile",()=>ke.authz.oaa.deleteUser(ee),{id:ee,kind:"user"});return new Response(null,{status:204})};Ze={handler:se}}let rt=async(Se,ve)=>{if(!V)return;let M=[];for await(let B of i((J,F)=>V.listBySubject(Se,ve,{start:J,limit:F})))await Bt(ke,B,M);await sn(ke,M)};if(ye.workloadIdentityStore){let{workloadIdentityStore:Se,inboundWorkloads:ve}=ye;yt=wr({resourceType:"Workload",subjectType:"workload",store:Se,validator:y.workload??q,toScim:async(M)=>await(ve?.mapBaseWorkloadToScim?.(M)??Dn(M)),fromScim:async(M,B)=>{if(ve?.mapValidatedScimToBaseWorkload)return ve.mapValidatedScimToBaseWorkload(M,B);let J=B.existing,F=M,ne=F.id?.trim()||J?.id||rn(),pe=r(F.attributes??{},b);return{...J??{},id:ne,externalId:F.externalId??J?.externalId,clientId:F.userName??J?.clientId??ne,displayName:F.displayName??J?.displayName,description:F.description??J?.description,active:F.active??J?.active??!0,providerId:J?.providerId,requestUrl:J?.requestUrl,...pe}},projections:[{channel:"oaa",upsert:async(M)=>{if(W.oaa.isReady())await W.oaa.pushWorkload(M)},delete:async(M)=>{if(W.oaa.isReady())await W.oaa.deleteWorkload(M.id)}},{channel:"delta",upsert:async(M,B)=>{let J=B?.externalId??B?.id,F=M.externalId??M.id;if(J&&J!==F)await xe?.onWorkloadDelete(J);await xe?.onWorkloadUpsert(M)},delete:async(M)=>{await xe?.onWorkloadDelete(M.externalId??M.id)}}]},{validateAuth:nt,accessStore:V,accessIndex:G,revokeSubjectAccess:rt,log:k})}if(ye.customerStore){let{customerStore:Se,inboundCustomers:ve}=ye;ct=wr({resourceType:"Customer",subjectType:"customer",store:Se,validator:y.customer??K,toScim:async(M)=>await(ve?.mapBaseCustomerToScim?.(M)??Ln(M)),fromScim:async(M,B)=>{if(ve?.mapValidatedScimToBaseCustomer)return ve.mapValidatedScimToBaseCustomer(M,B);let J=B.existing,F=M,ne=F.id?.trim()||J?.id||rn(),pe=r(F.attributes??{},S),de=F.emails?.find((re)=>re.primary)?.value??F.emails?.[0]?.value;return{...J??{},id:ne,externalId:F.externalId??J?.externalId??ne,userName:F.userName??J?.userName??ne,name:F.displayName??J?.name??F.userName??ne,email:de??J?.email??"",displayName:F.displayName??J?.displayName,emails:F.emails??J?.emails,active:F.active??J?.active??!0,providerId:J?.providerId,requestUrl:J?.requestUrl,...pe}},projections:[{channel:"oaa",upsert:async(M)=>{if(W.oaa.isReady())await W.oaa.pushCustomer(M)},delete:async(M)=>{if(W.oaa.isReady()&&M.id)await W.oaa.deleteCustomer(M.id)}},{channel:"delta",upsert:async(M,B)=>{let J=B?.externalId??B?.id,F=M.externalId??M.id;if(J&&J!==F)await xe?.onCustomerDelete(J);await xe?.onCustomerUpsert(M)},delete:async(M)=>{let B=M.externalId??M.id;if(B)await xe?.onCustomerDelete(B)}}]},{validateAuth:nt,accessStore:V,accessIndex:G,revokeSubjectAccess:rt,log:k})}async function ht(Se,ve){Je();let M=new URL(Se.url).pathname,B=ut(ve?.usersUrl??ye.usersUrl??"/api/iam/Users")??"/api/iam/Users",J=ut(ve?.groupsUrl??ye.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",F=ut(ve?.workloadsUrl??ye.workloadsUrl??"/api/iam/Workloads")??"/api/iam/Workloads",ne=ut(ve?.customersUrl??ye.customersUrl??"/api/iam/Customers")??"/api/iam/Customers",pe=`${br(B,J,F,ne)??"/api/iam"}/AccessRequests`,de=await gt(Se,ve);if(de)return de;let re=(se)=>M===se||M.startsWith(`${se}/`);if(re(B)){if(!_e)return Re(404,"SCIM Users endpoint is disabled by RemoteConfig");if(!Ze)return Re(501,"SCIM Users endpoint is enabled by RemoteConfig but no user store capability is wired by the application.");return Ze.handler(Se,{basePath:B})}if(re(J)){if(!Ne)return Re(404,"SCIM Groups endpoint is disabled by RemoteConfig");if(!lt)return Re(501,"SCIM Groups endpoint is enabled by RemoteConfig but no AccessCatalogStore capability is wired by the application.");return lt.handler(Se,{basePath:J})}if(re(F)){if(!$e)return Re(404,"SCIM Workloads endpoint is disabled by RemoteConfig");if(!yt)return Re(501,"SCIM Workloads endpoint is enabled by RemoteConfig but no workload identity store capability is wired by the application.");return yt.handler(Se,{basePath:F})}if(re(ne)){if(!tt)return Re(404,"SCIM Customers endpoint is disabled by RemoteConfig");if(!ct)return Re(501,"SCIM Customers endpoint is enabled by RemoteConfig but no customer store capability is wired by the application.");return ct.handler(Se,{basePath:ne})}if(re(pe)){if(!ye.accessRequests)return Re(404,"AccessRequests endpoint is not configured");if(Se.method!=="POST")return Re(405,"Method not allowed");if(!await nt(Se))return Re(401,"Authorization required");let se;try{se=await Se.json()}catch{return Re(400,"Request body must be valid JSON","invalidSyntax")}if(typeof se.subject!=="string"||!se.subject||typeof se.target!=="string"||!se.target||se.subjectType!=="user"&&se.subjectType!=="workload"&&se.subjectType!=="customer"||se.targetType!=="group"&&se.targetType!=="role"&&se.targetType!=="permission"||se.operation!=="grant"&&se.operation!=="revoke")return Re(400,"subject, subjectType, targetType, target, and operation are required","invalidValue");let fe=await ye.accessRequests.create({subject:se.subject,subjectType:se.subjectType,targetType:se.targetType,target:se.target,operation:se.operation,justification:typeof se.justification==="string"?se.justification:void 0});return Xe(fe.request,fe.created?201:200,fe.request.trackingUrl)}return Re(404,"Resource not found")}return{...ye,users:Nn(ye.users),workloads:Nn(ye.workloads),customers:Nn(ye.customers),groups:{enabled:Ne},createUser:It,getBaseUrl:Et,groups_outbound:at,groups_inbound:lt,users_inbound:Ze,workloads_inbound:yt,customers_inbound:ct,handler:ht,delta:xe}}function Hn(y,k){let R=new TextEncoder().encode(y),W=typeof k==="string"?new TextEncoder().encode(k):k,V=new Uint8Array(R.length+1+W.length);return V.set(R,0),V[R.length]=46,V.set(W,R.length+1),V}function ii(y){let k=y.replace(/-/g,"+").replace(/_/g,"/"),R=k.length%4===0?"":"=".repeat(4-k.length%4),W=atob(k+R),V=new Uint8Array(W.length);for(let G=0;G<W.length;G++)V[G]=W.charCodeAt(G);return V}function oi(y){let k="";for(let R of y)k+=String.fromCharCode(R);return btoa(k).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function Rr(y){let k=JSON.parse(y);if(!k||typeof k!=="object"||!Array.isArray(k.keys))throw Error("Invalid JWKS: expected { keys: [...] }");return k}function ai(y){return JSON.stringify(y)}async function ci(y){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:y.x},{name:"Ed25519"},!0,["verify"])}async function ui(y){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:y.x,d:y.d},{name:"Ed25519"},!0,["sign"])}async function di(y){let R=(typeof y.jwks==="string"?Rr(y.jwks):y.jwks).keys.find((W)=>W.kid===y.kid&&W.kty==="OKP"&&W.crv==="Ed25519");if(!R?.x)return!1;try{let W=await ci(R),V=Hn(y.requestId,y.rawBody),G=ii(y.signatureB64Url);return crypto.subtle.verify({name:"Ed25519"},W,G,V)}catch{return!1}}async function li(y){let k=await ui(y.privateKeyJwk),R=Hn(y.requestId,y.rawBody),W=await crypto.subtle.sign({name:"Ed25519"},k,R);return oi(new Uint8Array(W))}async function pi(y){let k=await crypto.subtle.generateKey({name:"Ed25519"},!0,["sign","verify"]),R=await crypto.subtle.exportKey("jwk",k.privateKey),V=(await crypto.subtle.exportKey("jwk",k.publicKey)).x,G=R.d;if(!V||!G)throw Error("Failed to export Ed25519 key material (missing x/d)");return{privateJwk:{kty:"OKP",crv:"Ed25519",x:V,d:G,kid:y,alg:"EdDSA",use:"sig"},publicJwks:{keys:[{kty:"OKP",crv:"Ed25519",x:V,kid:y,alg:"EdDSA",use:"sig"}]}}}var Ft={jwksTtlSeconds:{min:60,max:86400,default:600},jwksMaxEntries:{min:16,max:4096,default:256},sessionReadTtlSeconds:{min:1,max:300,default:30},sessionReadMaxEntries:{min:16,max:65536,default:1024}};function un(y,k){if(typeof y!=="number"||!Number.isFinite(y))return k.default;let R=Math.floor(y);if(R<k.min)return k.min;if(R>k.max)return k.max;return R}function vr(y){return{ttlMs:un(y?.ttlSeconds,Ft.jwksTtlSeconds)*1000,maxEntries:un(y?.maxEntries,Ft.jwksMaxEntries)}}function Ir(y){let k=y?.read;return{read:{enabled:k?.enabled===!0,ttlMs:un(k?.ttlSeconds,Ft.sessionReadTtlSeconds)*1000,maxEntries:un(k?.maxEntries,Ft.sessionReadMaxEntries)}}}function mi(y){return{jwks:vr(y?.jwks),session:Ir(y?.session)}}function fi(y){let k={};if(!y)return k;let R=y.split(";");for(let W of R){let V=W.trim();if(!V)continue;let G=V.indexOf("=");if(G===-1)continue;k[V.slice(0,G).trim()]=V.slice(G+1).trim()}return k}function Ar(y){if(!y.expiresAt)return!1;let k=y.expiresAt instanceof Date?y.expiresAt:new Date(y.expiresAt);return!Number.isNaN(k.getTime())&&Date.now()>k.getTime()}function gi(y){if(!y||typeof y!=="object"||Array.isArray(y))return;let{access_token:k,id_token:R,refresh_token:W,tokens:V,...G}=y;return G}function it(y,k){let R=y[k];return typeof R==="string"?R:""}function yi(y,k){let R=y.exp;if(typeof R==="number")return new Date(R*1000);if(typeof R==="string"&&R.trim()){let W=Number(R);if(!Number.isNaN(W))return new Date(W*1000)}if(k instanceof Date)return k;if(k){let W=new Date(k);if(!Number.isNaN(W.getTime()))return W}return new Date}function hi(y){let k=y.claims;if(!k?.sub||typeof k.sub!=="string")return;let R=yi(k,y.expiresAt);if(y.authType==="sso")return{id:k.sub,userName:it(k,"preferred_username"),name:it(k,"name"),email:it(k,"email"),avatar:it(k,"picture")||void 0,sso:{profile:k,tenant:{id:it(k,"idp")||it(k,"iss"),name:it(k,"iss")},tokenType:"Bearer",expires:R}};return{id:k.sub,userName:it(k,"preferred_username"),name:it(k,"name"),email:it(k,"email"),avatar:it(k,"picture")||void 0,userType:"customer",ciam:{profile:k,scope:"openid profile email",tokenType:"Bearer",expires:R}}}function Si(y){if(y.authType!=="sso"&&y.authType!=="ciam")return;if(Ar(y))return;return{sid:y.sid,authType:y.authType,tenantId:typeof y.tenantId==="string"?y.tenantId:void 0,sub:y.sub,expiresAt:y.expiresAt,createdAt:y.createdAt,claims:gi(y.claims)}}function ki(y,k){if(!y.endsWith(".session"))return!1;if(!k||k.length===0)return!0;return k.some((R)=>y===`${R}.session`)}function wi(y){if(y===void 0)return;let k=(Array.isArray(y)?y:[y]).map((R)=>R.trim()).filter((R)=>R.length>0);return k.length>0?k:void 0}async function Tr(y,k,R){return(await Pr(y,k,R)).map(Si).filter((V)=>Boolean(V))}async function Pr(y,k,R){let W=fi(y.headers.get("cookie")),V=wi(R?.cookiesPrefix),G=[],H=new Set;for(let[Y,Q]of Object.entries(W)){if(!ki(Y,V)||!Q)continue;if(H.has(Q))continue;H.add(Q);let X=await k.get(Q);if(!X)continue;if(X.authType!=="sso"&&X.authType!=="ciam")continue;if(Ar(X))continue;G.push(X)}return G}async function bi(y,k,R){return(await Tr(y,k,R)).map(hi).filter((V)=>Boolean(V))}var Ci="@ionite/core",Ri=a(l(Ci));async function vi(y,k){let R=await kt({idToken:y,jwksUri:k.jwksUri,issuer:k.issuer,audience:k.audience}),W=await Ri.validate(R);if(W.issues)throw Error(`ID token claims validation failed: ${W.issues.map((H)=>H.message).join("; ")}`);let V=W.value;if(V===void 0)throw Error("ID token claims missing");return P(V)}function Ye(y){return Date.now()-y}function Fn(y){if(y instanceof Error)return{"error.name":y.name,"error.message":y.message};return{"error.name":typeof y,"error.message":String(y)}}function dn(y,k){if(!y)return{};try{let R=new URL(y);return{[`${k}.origin`]:R.origin,[`${k}.path`]:R.pathname}}catch{return{[`${k}.path`]:y.startsWith("/")?y:`/${y}`}}}function ln(y,k=5){if(!Array.isArray(y))return[String(y)];return y.slice(0,k).map((R)=>{if(!R||typeof R!=="object")return String(R);let W=R,V=Array.isArray(W.path)?W.path.join("."):String(W.path??""),G=typeof W.message==="string"?W.message:String(W.message??"validation failed");return V?`${V}: ${G}`:G})}function Ii(y){if(!y||typeof y!=="object")return{};let k=y;return{oidc_error:typeof k.error==="string"?k.error:void 0,oidc_error_description:typeof k.error_description==="string"?k.error_description:void 0,oidc_error_uri:typeof k.error_uri==="string"?k.error_uri:void 0}}function Ai(y,k={}){let R=typeof y==="string"?y:y?.headers.get("cookie")??void 0;if(!R)return[];let V=`${k.cookiePrefix??"ion.sso"}.`,G=new Set;for(let H of Object.keys(Pi(R))){if(!H.startsWith(V))continue;let Y=H.slice(V.length),Q=Y.lastIndexOf(".");if(Q<=0)continue;let X=Y.slice(0,Q).trim();if(X)G.add(X)}return Array.from(G)}function Ti(y,k,R,W,V){if(!R&&!W)return;let G=new WeakMap,H=new Map,Y={...R,...W},Q=!!(Y.authority&&Y.tokenUrl&&Y.authorizationUrl&&Y.clientId&&Y.redirectUri&&Y.scope),X={...Y,authority:Q?t(Y.authority,"Missing 'authority' from SSO Config"):Y.authority,tokenUrl:Q?t(Y.tokenUrl,"Missing 'tokenUrl' from SSO Config"):Y.tokenUrl,authorizationUrl:Q?t(Y.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"):Y.authorizationUrl,clientId:Q?t(Y.clientId,"Missing 'clientId' from SSO Config"):Y.clientId,redirectUri:Q?t(Y.redirectUri,"Missing 'redirectUri' from SSO Config"):Y.redirectUri,scope:Q?t(Y.scope,"Missing 'scope' from SSO Config"):Y.scope,responseType:Y.responseType??"code",cookiesSecure:Y.cookiesSecure!==void 0?Y.cookiesSecure:!0,cookiesSameSite:Y.cookiesSameSite!==void 0?Y.cookiesSameSite:"Strict",cookiesPrefix:Y.cookiesPrefix??(Y.clientId?`ion.sso.${Y.clientId}`:"ion.sso"),cookiesPath:Y.cookiesPath??"/"},Pe=Math.min(600,Math.max(0,Math.floor(Number(X.rotationGraceSeconds??60))||0))*1000,xe=Math.floor(Number(X.sessionWindowSeconds??86400)),je=Number.isFinite(xe)&&xe>=1?xe:86400;function De(){let M=[];if(!X.authority)M.push("authority");if(!X.tokenUrl)M.push("tokenUrl");if(!X.authorizationUrl)M.push("authorizationUrl");if(!X.clientId)M.push("clientId");if(!X.redirectUri)M.push("redirectUri");if(!X.scope)M.push("scope");if(M.length>0)throw Error(`Missing OIDC configuration fields: ${M.join(", ")}. OIDC configuration is required for SSO operations. Please provide these fields either in your vault configuration or in the SSO config when initializing ionite.`)}async function We(M){if(!X)throw Error("ionite SSO Manager not initialized");let B=G.get(M);if(B)return B;let J=ke(M);return G.set(M,J),J}async function ke(M){try{let{tokens:B,session:J,refreshedUser:F}=await Ze(M);if(!B)return{status:"unauthenticated"};if(F)return{status:"authenticated",value:F};if(J?.claims)return{status:"authenticated",value:Je(J.claims,B,gt(J.expiresAt))};return{status:"unauthenticated"}}catch(B){if(xr(B))return{status:"unauthenticated"};return k.error("Error parsing user from cookies",{"ion.operation":"cookie.parse","ion.outcome":"degraded"},B),{status:"degraded",error:B instanceof Error?B:void 0}}}async function Le(M){let B=await We(M);return B.status==="authenticated"?B.value:void 0}async function ye(M){if(!X)throw Error("ionite SSO Manager not initialized");De();let B=t(X.redirectUri,"Missing 'redirectUri' from SSO Config"),J=t(X.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"),F=t(X.clientId,"Missing 'clientId' from SSO Config"),ne=t(X.scope,"Missing 'scope' from SSO Config"),pe=X.cookiesSecure?M.url.replace(/^http:\/\//,"https://"):M.url,de=st(),re=st(64),se=st(),fe=B;try{new URL(fe)}catch{if(pe)try{let Ee=new URL(pe),ae=fe.startsWith("//")?fe.slice(1):fe.startsWith("/")?fe:`/${fe}`;fe=new URL(ae,Ee.origin).toString()}catch{try{let Ee=new URL(J),ae=fe.startsWith("//")?fe.slice(1):fe.startsWith("/")?fe:`/${fe}`;fe=new URL(ae,Ee.origin).toString()}catch{throw Error(`Invalid redirectUri: "${B}". It must be a valid absolute URL.`)}}}let be=new URL(J);be.searchParams.append("client_id",F),be.searchParams.append("redirect_uri",fe),be.searchParams.append("response_type","code"),be.searchParams.append("scope",ne),be.searchParams.append("state",de),be.searchParams.append("nonce",se);let me=await $t(re);be.searchParams.append("code_challenge",me),be.searchParams.append("code_challenge_method","S256");let Ie=await X.beforeLogin?.({request:M}),Oe=Ie===void 0?{state:de,codeVerifier:re,nonce:se}:{state:de,codeVerifier:re,nonce:se,context:Ie};return new Response("Redirecting to SSO Provider",{status:302,headers:{Location:be.toString(),"Set-Cookie":ct(Se(de),Oe,X.loginStateTtl??600,"Lax")}})}async function _e(M){if(!X)throw Error("ionite SSO Manager not initialized");let B;try{B=await Le(M)}catch{B=void 0}let J=await X.beforeLogout?.({request:M,user:B}),F=ht("session",M),ne;try{ne=await Ze(M);let me=ne.tokens?.refresh_token??ht("refresh",M);if(me)await Et(me)}catch(me){k.warn("Failed to revoke token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},me)}if(X.sessionStore)try{let me=ne?.sid??F;if(me)await X.sessionStore.delete(me)}catch(me){k.warn("Failed to delete session",{"ion.operation":"session.delete","ion.outcome":"degraded"},me)}let pe=[["Set-Cookie",rt("session")]],de=await X.afterLogout?.({request:M,context:J}),re=wt(de,"/",M.url);if(re.response){let me=new Headers(re.response.headers);for(let[,Ie]of pe)me.append("Set-Cookie",Ie);return new Response(re.response.body,{status:re.response.status,statusText:re.response.statusText,headers:me})}let se=re.location??"/",fe=M.headers.get("accept");if(fe?.includes("application/json")||fe?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:se}),{status:200,headers:[["Content-Type","application/json"],...pe]});return new Response("Logged out",{status:302,headers:[["Location",se],...pe]})}async function Ne(M){if(!X)throw Error("ionite SSO Manager not initialized");if(!X.sessionStore)throw Error("Back-Channel Logout requires sessionStore configuration");try{if(!M.headers.get("content-type")?.includes("application/x-www-form-urlencoded"))return new Response("Invalid Content-Type, expected application/x-www-form-urlencoded",{status:400});let J=await M.text(),ne=new URLSearchParams(J).get("logout_token");if(!ne)return new Response("Missing logout_token parameter",{status:400});let pe=t(X.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify logout tokens."),de=t(X.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify logout tokens."),re=X.jwksUri||`${pe}/protocol/openid-connect/certs`,se=await Pn({logoutToken:ne,jwksUri:re,issuer:pe,audience:de,log:k}),fe=typeof se.sid==="string"?se.sid:void 0;if(!fe)return k.warn("Back-Channel Logout: logout_token missing sid claim",{"ion.operation":"backchannel_logout","ion.outcome":"failure"}),new Response("Invalid logout_token: missing sid claim",{status:400});return await X.sessionStore.delete(fe),k.info("Back-Channel Logout: successfully deleted session",{"ion.module":"sso",sid:fe}),new Response("OK",{status:200})}catch(B){return k.error("Error during back-channel logout",{"ion.operation":"backchannel_logout","ion.outcome":"failure"},B),new Response("Internal Server Error",{status:500})}}async function $e(M){if(!X)throw Error("ionite SSO Manager not initialized");let B=Date.now(),J=new URL(M.url),F=new URLSearchParams(J.search);k.debug("SSO callback received",{"ion.event":"ion.sso.callback.received","ion.module":"sso","ion.operation":"sign_in.callback","http.method":M.method,"url.path":J.pathname,hasCode:F.has("code"),hasState:F.has("state"),hasError:F.has("error"),...dn(F.get("iss")??void 0,"oidc.issuer")});let ne=Object.fromEntries(F.entries()),pe=await y.callbackParams.validate(ne);if(pe.issues)return k.warn("SSO callback parameter validation failed",{"ion.event":"ion.sso.callback.validation_failed","ion.operation":"sign_in.callback","ion.outcome":"failure","validation.issues":ln(pe.issues)}),D(pe.issues,"OIDC callback parameters validation failed");let{code:de,state:re}=pe.value,se;try{let fe=t(re,'OIDC "state" was not present in the callback parameters'),be=ht(Se(fe),M,!0),{codeVerifier:me,state:Ie,nonce:Oe,context:Ee}=be??{};se=Ee,k.debug("SSO callback state cookie read",{"ion.event":"ion.sso.callback.state_cookie_read","ion.module":"sso","ion.operation":"sign_in.callback",hasStateCookie:Boolean(be),hasCodeVerifier:Boolean(me),hasStateVerifier:Boolean(Ie),hasNonce:Boolean(Oe),hasContext:Ee!==void 0});let ae=t(me,'OIDC "codeVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');t(Ie,'OIDC "stateVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');let ee=t(Oe,'OIDC "nonce" was not present in cookies, ensure that the SSO login was initiated correctly'),oe=t(de,'OIDC "code" was not present in the callback parameters');if(re!==Ie)throw k.warn("SSO callback state verification failed",{"ion.event":"ion.sso.callback.state_verification_failed","ion.operation":"sign_in.callback","ion.outcome":"failure"}),Error('SSO State Verifier failed, the "state" request parameter does not equal the "state" in the SSO cookie');k.debug("SSO callback state verified",{"ion.event":"ion.sso.callback.state_verified","ion.module":"sso","ion.operation":"sign_in.callback"});let ue=X.cookiesSecure?M.url.replace(/^http:\/\//,"https://"):M.url,ce=await Ut(oe,ae,ue),{tokenExpiresAt:he,sessionExpiresAt:we}=tt(ce);ce.expires=he.toISOString();let ge=Date.now();k.debug("SSO ID token parsing started",{"ion.event":"ion.sso.id_token.parse_started","ion.module":"sso","ion.operation":"id_token.parse"});let Ce=await Ge(ce,ee,we);k.debug("SSO ID token parsing completed",{"ion.event":"ion.sso.id_token.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":Ye(ge),"user.id":Ce.id});let Ae,Me;{let Te=ot("SSO requires sessionStore configuration for opaque session cookies."),Ke=typeof Ce.sso.profile.sid==="string"?Ce.sso.profile.sid:void 0,Ue=Ke||st(32),qe=Ce.id;if(k.debug("SSO session creation evaluated",{"ion.event":"ion.sso.session.create_evaluated","ion.module":"sso","ion.operation":"session.create",hasSid:Boolean(Ue),hasIdpSid:Boolean(Ke),hasSub:Boolean(qe),"user.id":qe}),!qe)throw Error("Session creation failed: missing sub in ID token claims");let St=Date.now(),Yt={sid:Ue,sub:qe,idpSid:Ke,authType:"sso",tenantId:X.tenantId,tokens:ce,claims:Ce.sso.profile,expiresAt:we,createdAt:new Date};await vt(Te,Yt),Me=Yt,Ae=["Set-Cookie",ct("session",Ue,we)],k.info("SSO session created",{"ion.event":"ion.sso.session.created","ion.operation":"session.create","ion.outcome":"success","duration.ms":Ye(St),"user.id":qe})}if(X.userStore)try{let Te=Ce.id;if(Te){let Ke=new Date,Ue=Date.now();k.debug("SSO user store lookup started",{"ion.event":"ion.sso.user.lookup_started","ion.module":"sso","ion.operation":"user.lookup","user.id":Te});let qe=await X.userStore.get(Te);if(k.debug("SSO user store lookup completed",{"ion.event":"ion.sso.user.lookup_completed","ion.module":"sso","ion.operation":"user.lookup","duration.ms":Ye(Ue),"user.id":Te,found:Boolean(qe)}),qe||X.enableJitUserProvisioning){let St=Date.now(),Yt={...qe??{},...Ce,id:Te,tenantId:qe?.tenantId,createdAt:qe?.createdAt??Ke,updatedAt:Ke};await X.userStore.upsert(Yt),k.info("SSO user stored",{"ion.event":"ion.sso.user.stored","ion.operation":"user.store","ion.outcome":"success","duration.ms":Ye(St),"user.id":Te,existing:Boolean(qe),jitProvisioning:Boolean(X.enableJitUserProvisioning)})}else k.warn("JIT user provisioning disabled: user not found in store and will not be created",{"ion.event":"ion.sso.user.skipped","ion.operation":"user.store","ion.outcome":"skipped","user.id":Te})}else k.warn("User storage skipped: missing sub in ID token claims",{"ion.event":"ion.sso.user.skipped","ion.operation":"user.store","ion.outcome":"skipped"})}catch(Te){k.warn("Failed to store user",{"ion.event":"ion.sso.user.store_failed","ion.operation":"user.store","ion.outcome":"degraded",...Fn(Te)})}k.info("SSO sign-in succeeded",{"ion.event":"ion.sso.sign_in.succeeded","ion.operation":"sign_in.callback","ion.outcome":"success","duration.ms":Ye(B),"user.id":Ce.id});let ze=[["Set-Cookie",rt(Se(fe))],...Ae?[Ae]:[]],Qe=await X.afterLogin?.({ok:!0,request:M,user:Ce,session:Me,context:se}),Ve=wt(Qe,"/",M.url);if(Ve.response)return At(Ve.response,ze.map(([,Te])=>Te));return new Response("Authentication successful, redirecting",{status:302,headers:[["Location",Ve.location],...ze]})}catch(fe){k.error("Error during sign-in callback",{"ion.event":"ion.sso.sign_in.callback_failed","ion.operation":"sign_in.callback","ion.outcome":"failure","duration.ms":Ye(B),...Fn(fe)});let be=re?[["Set-Cookie",rt(Se(re))]]:[],me=await X.afterLogin?.({ok:!1,request:M,error:fe,context:se}),Ie=wt(me,"/",M.url);if(Ie.response)return At(Ie.response,be.map(([,Oe])=>Oe));return new Response("Authentication failed, redirecting",{status:302,headers:[["Location",Ie.location],...be]})}}function tt(M){let B=Date.now(),J=Number(M.expires_in??3600)||3600,F=new Date(B+J*1000),ne;if(M.refresh_expires_in!=null&&Number.isFinite(Number(M.refresh_expires_in)))ne=Number(M.refresh_expires_in);else if(M.refresh_token)ne=je;else ne=J;return{tokenExpiresAt:F,sessionExpiresAt:new Date(B+ne*1000)}}async function Ge(M,B,J){if(!X)throw Error("ionite SSO Manager not initialized");let F=Date.now(),ne=await Lt(M.id_token,B);return k.debug("SSO user parsed from ID token",{"ion.event":"ion.sso.user.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":Ye(F),"user.id":ne.sub,hasEmail:Boolean(ne.email),hasName:Boolean(ne.name)}),Je(ne,M,J)}function Je(M,B,J){let F=J??tt(B).sessionExpiresAt,ne=M.ecid!==void 0&&M.ecid!==null?w(M.ecid):void 0;return{id:M.sub,userName:M.preferred_username||"",name:M.name||"",email:M.email||"",emails:[{value:M.email||"",primary:!0}],...ne?{ecid:ne}:{},avatar:M.picture,sso:{profile:{...M},tenant:{id:M.idp||M.iss||"",name:M.iss||""},scope:B.scope,tokenType:B.token_type,sessionState:B.session_state,expires:F}}}async function nt(M){if(!X.userStore)return M;let B=await X.userStore.lookup(M);if(!B)return M;return{...M,...B,id:M.id,sso:M.sso}}async function Ut(M,B,J){if(!X)throw Error("ionite SSO Manager not initialized");De();let F=t(X.tokenUrl,"Missing 'tokenUrl' from SSO Config"),ne=t(X.redirectUri,"Missing 'redirectUri' from SSO Config"),pe=t(X.clientId,"Missing 'clientId' from SSO Config"),de=ne;try{new URL(de)}catch{if(J)try{let se=new URL(J),fe=de.startsWith("//")?de.slice(1):de.startsWith("/")?de:`/${de}`;de=new URL(fe,se.origin).toString()}catch{try{let se=new URL(F),fe=de.startsWith("//")?de.slice(1):de.startsWith("/")?de:`/${de}`;de=new URL(fe,se.origin).toString()}catch{throw Error(`Invalid redirectUri: "${ne}". It must be a valid absolute URL.`)}}}let re=new URLSearchParams;if(re.append("grant_type","authorization_code"),re.append("code",M),re.append("redirect_uri",de),re.append("client_id",pe),X.clientSecret)re.append("client_secret",X.clientSecret);re.append("code_verifier",B);try{let se=Date.now();k.debug("SSO token exchange started",{"ion.event":"ion.sso.token.exchange_started","ion.module":"sso","ion.operation":"token.exchange",...dn(F,"oidc.token_url"),...dn(de,"oidc.redirect_uri"),hasClientSecret:Boolean(X.clientSecret)});let fe=await fetch(F,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:re.toString()});k.debug("SSO token exchange response received",{"ion.event":"ion.sso.token.response_received","ion.module":"sso","ion.operation":"token.exchange","http.status_code":fe.status,"duration.ms":Ye(se)}),k.debug("SSO token exchange response body read started",{"ion.event":"ion.sso.token.response_body_read_started","ion.module":"sso","ion.operation":"token.exchange"});let be=await fe.json();if(k.debug("SSO token exchange response body read completed",{"ion.event":"ion.sso.token.response_body_read_completed","ion.module":"sso","ion.operation":"token.exchange","duration.ms":Ye(se)}),!fe.ok){k.error("Token exchange error",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":fe.status,"duration.ms":Ye(se),...Ii(be)});let Ie=be;throw Error(`Token exchange failed: ${Ie.error||fe.statusText} - ${Ie.error_description||""}`.trim())}let me=await y.tokenResponse.validate(be);if(me.issues)throw k.error("Token response validation failed",{"ion.event":"ion.sso.token.response_validation_failed","ion.operation":"token.exchange","ion.outcome":"failure","duration.ms":Ye(se),"validation.issues":ln(me.issues)}),Error(`Token response validation failed: ${me.issues}`);return k.debug("SSO token exchange completed",{"ion.event":"ion.sso.token.exchange_completed","ion.module":"sso","ion.operation":"token.exchange","ion.outcome":"success","duration.ms":Ye(se),tokenType:me.value.token_type,hasAccessToken:Boolean(me.value.access_token),hasIdToken:Boolean(me.value.id_token),hasRefreshToken:Boolean(me.value.refresh_token),expiresIn:me.value.expires_in}),me.value}catch(se){throw k.error("Error during token exchange",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure",...Fn(se)}),se}}async function Rt(M){return Cn(async()=>{if(!X)throw Error("ionite SSO Manager not initialized");De();let B=t(X.tokenUrl,"Missing 'tokenUrl' from SSO Config"),J=t(X.clientId,"Missing 'clientId' from SSO Config"),F=new URLSearchParams;if(F.append("grant_type","refresh_token"),F.append("refresh_token",M),F.append("client_id",J),X.clientSecret)F.append("client_secret",X.clientSecret);let ne=await fetch(B,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:F.toString()}),pe=await ne.json();if(!ne.ok){k.error("Token refresh error",{"ion.operation":"token.refresh","ion.outcome":"failure",response:pe});let re=pe;throw Error(`Token refresh failed: ${re.error||ne.statusText} - ${re.error_description||""}`.trim())}let de=await y.tokenResponse.validate(pe);if(de.issues)throw k.error("Token refresh response validation failed",{"ion.event":"ion.sso.token.refresh_validation_failed","ion.operation":"token.refresh","ion.outcome":"failure","validation.issues":ln(de.issues)}),Error(`Token refresh response validation failed: ${de.issues}`);return de.value},void 0,void 0,void 0,k)}async function Et(M){try{if(!X)throw Error("ionite SSO Manager not initialized");if(!X.revocationEndpoint)return;let B=t(X.clientId,"Missing 'clientId' from SSO Config"),J=new URLSearchParams;if(J.append("token",M),J.append("token_type_hint","refresh_token"),J.append("client_id",B),X.clientSecret)J.append("client_secret",X.clientSecret);let F=await fetch(X.revocationEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:J.toString()});if(!F.ok)k.warn("Token revocation failed",{"ion.operation":"token.revoke","ion.outcome":"degraded",status:F.status,statusText:F.statusText});else k.info("Token revoked successfully",{"ion.module":"sso"})}catch(B){k.warn("Error revoking token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},B)}}async function Dt(){if(!X)throw Error("ionite SSO Manager not initialized");let M=X.authority;if(!X.jwksUri&&!M)throw Error("Missing 'jwksUri' or 'authority' from SSO Config. OIDC configuration is required for this operation.");let B=X.jwksUri||`${M}/protocol/openid-connect/certs`;return Wt(B,k)}async function Lt(M,B){let J=Date.now(),F=t(X.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify ID tokens."),ne=t(X.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify ID tokens."),pe=X.jwksUri||`${F}/protocol/openid-connect/certs`;k.debug("SSO ID token verification started",{"ion.event":"ion.sso.id_token.verify_started","ion.module":"sso","ion.operation":"id_token.verify",...dn(pe,"oidc.jwks_uri")});let de;try{de=await kt({idToken:M,jwksUri:pe,issuer:F,audience:ne,expectedNonce:B,log:k})}catch(se){throw k.error("SSO ID token verification failed",{"ion.event":"ion.sso.id_token.verify_failed","ion.module":"sso","ion.operation":"id_token.verify","ion.outcome":"failure","duration.ms":Ye(J)},se),se}k.debug("SSO ID token signature verified",{"ion.event":"ion.sso.id_token.signature_verified","ion.module":"sso","ion.operation":"id_token.verify","duration.ms":Ye(J)});let re=await y.idTokenClaims.validate(de);if(re.issues)throw k.error("ID token claims validation failed",{"ion.event":"ion.sso.id_token.validation_failed","ion.operation":"id_token.validate","ion.outcome":"failure","duration.ms":Ye(J),"validation.issues":ln(re.issues)}),Error(`ID token claims validation failed: ${re.issues}`);return k.debug("SSO ID token claims validated",{"ion.event":"ion.sso.id_token.claims_validated","ion.module":"sso","ion.operation":"id_token.validate","ion.outcome":"success","duration.ms":Ye(J),"user.id":re.value.sub,hasIssuer:Boolean(re.value.iss),hasAudience:Boolean(re.value.aud)}),re.value}function ot(M="SSO sessionStore is required for opaque session cookies."){if(!X.sessionStore)throw Error(M);return X.sessionStore}async function vt(M,B){try{await M.create(B)}catch(J){if(!await M.get(B.sid))throw J;await M.update(B.sid,B)}}function gt(M){if(!M)return;if(M instanceof Date)return M;let B=new Date(M);return Number.isNaN(B.getTime())?void 0:B}function at(M){let B=M.tokens;if(!B?.access_token||!B.id_token||!B.token_type)return;return B}async function It(M,B=!1){let J=ot(),F=ht("session",M);if(!F)return{tokens:void 0,refreshHeaders:[]};let ne=await J.get(F);if(ne&&X.tenantId&&ne.tenantId&&ne.tenantId!==X.tenantId)return{tokens:void 0,refreshHeaders:[["Set-Cookie",rt("session")]],sid:F};if(ne?.authType!=="sso")return{tokens:void 0,refreshHeaders:[["Set-Cookie",rt("session")]],sid:F};let pe=at(ne);if(!pe)return{tokens:void 0,refreshHeaders:[["Set-Cookie",rt("session")]],sid:F};let de=gt(ne.expiresAt);if(de?Date.now()>de.getTime():!1)return await J.delete(F),{tokens:void 0,sid:F,refreshHeaders:[["Set-Cookie",rt("session")]]};let se=gt(pe.expires),fe=se?Date.now()>se.getTime():!0;if((B||fe)&&pe.refresh_token)return lt(F,ne,pe);return{tokens:pe,sid:F,session:ne,refreshHeaders:[]}}function lt(M,B,J){let F=H.get(M);if(F)return F;let ne=ot(),pe=(async()=>{let de=await Rt(J.refresh_token),{tokenExpiresAt:re,sessionExpiresAt:se}=tt(de);de.expires=re.toISOString();let fe=await Ge(de,void 0,se),be=fe.sso.profile,me=st(32),Ie={...B,sid:me,tokens:de,claims:be,expiresAt:se,createdAt:new Date};await vt(ne,Ie);try{if(Pe<=0)await ne.delete(M);else{let{refresh_token:Oe,...Ee}=J;await ne.update(M,{tokens:Ee,expiresAt:new Date(Date.now()+Pe)})}}catch(Oe){k.warn("Failed to retire rotated SSO session record",{"ion.operation":"session.rotate","ion.outcome":"degraded"},Oe)}return{tokens:de,sid:me,session:Ie,refreshedUser:fe,refreshHeaders:[["Set-Cookie",ct("session",me,se)]]}})();return H.set(M,pe),pe.finally(()=>{H.delete(M)})}async function Ze(M,B=!1){return It(M,B)}async function yt(M){let{tokens:B}=await Ze(M);if(!B)return;return B.access_token}function ct(M,B,J,F=X.cookiesSameSite??"Strict"){if(!X)throw Error("ionite SSO Manager not initialized");if(M=`${X.cookiesPrefix}.${M}`,typeof B!=="string")B=btoa(JSON.stringify(B));let ne;if(J instanceof Date)ne=`Expires=${J.toUTCString()}`;else if(typeof J==="number")ne=`Max-Age=${J}`;else throw Error("Invalid expires type",J);if(B.length>4000)throw Error(`Error setting cookie: ${M}. Cookie length is: ${B.length}`);return`${M}=${B}; ${ne}; Path=${X.cookiesPath}; HttpOnly;${X.cookiesSecure?" Secure;":""} SameSite=${F};`}function rt(M){if(!X)throw Error("ionite SSO Manager not initialized");return`${X.cookiesPrefix}.${M}=; Max-Age=0; Path=${X.cookiesPath}; HttpOnly;${X.cookiesSecure?" Secure;":""} SameSite=${X.cookiesSameSite};`}function ht(M,B,J=!1){if(!X)throw Error("ionite SSO Manager not initialized");let F=B.headers.get("cookie");if(!F)return null;let ne=`${X.cookiesPrefix}.${M}`,pe=F.split(";").find((fe)=>fe.trim().startsWith(`${ne}=`));if(!pe)return null;let de=pe.indexOf("="),re=pe.slice(de+1).trim();if(!J)return re;let se=atob(re);return JSON.parse(se)}function Se(M){return`state_${M}`}async function ve(M,B){if(!X)throw Error("ionite SSO Manager not initialized");let{loginUrl:J,userUrl:F,tokenUrl:ne,refreshUrl:pe,logoutUrl:de,logoutBackChannelUrl:re,jwksUrl:se,redirectUri:fe}={...X,...B},be=new URL(M.url).pathname;if(fe){let me;try{me=new URL(fe).pathname}catch{try{let Ie=new URL(M.url),Oe=fe.startsWith("//")?fe.slice(1):fe;me=new URL(Oe,Ie.origin).pathname}catch{me=fe.startsWith("/")?fe:`/${fe}`}}if(me===be)return $e(M)}if(J===be)return ye(M);if(F===be)try{let{tokens:me,session:Ie,refreshedUser:Oe,refreshHeaders:Ee}=await Ze(M);if(!me)return new Response("User not logged in",{status:401,headers:Ee});let ae=Oe??(Ie?.claims?Je(Ie.claims,me,gt(Ie.expiresAt)):void 0);if(!ae)return new Response("User not logged in",{status:401,headers:Ee});let ee=await nt(ae);return new Response(JSON.stringify(ee),{headers:[["Content-Type","application/json"],...Ee]})}catch(me){if(xr(me))return new Response("User not logged in",{status:401});return k.error("Error resolving SSO user",{"ion.operation":"sso.user","ion.outcome":"degraded"},me),new Response(JSON.stringify({error:"auth_unavailable"}),{status:503,headers:{"Content-Type":"application/json"}})}if(ne===be){let{tokens:me,refreshHeaders:Ie}=await Ze(M);if(!me)return new Response("User not logged in",{status:401,headers:Ie});return new Response(JSON.stringify({token:me.access_token,expires:me.expires}),{headers:[["Content-Type","application/json"],...Ie]})}if(pe===be){let{tokens:me,refreshHeaders:Ie}=await Ze(M,!0);if(!me)return new Response("User not logged in",{status:401});return new Response("Refresh Complete",{status:200,headers:Ie})}if(de===be)return _e(M);if(re===be)return Ne(M);if(se===be){let me=await Dt();return new Response(JSON.stringify(me),{headers:[["Content-Type","application/json"]]})}return new Response("Not Found",{status:404})}return{...X,getUser:Le,resolveUser:We,getJwt:yt,initiateLogin:ye,logout:_e,logoutBackChannel:Ne,callbackHandler:$e,handler:ve}}function Pi(y){let k={},R=y.split(";");for(let W of R){let V=W.trim();if(!V)continue;let G=V.indexOf("=");if(G===-1)continue;let H=V.slice(0,G).trim(),Y=V.slice(G+1).trim();k[H]=Y}return k}function xr(y){if(!(y instanceof Error))return!1;return["Public key not found","Invalid JWT","Invalid JWT signature","ID token expired","ID token issuer mismatch","ID token audience mismatch","ID token nonce mismatch","ID token missing exp","invalid_grant"].some((k)=>y.message.includes(k))}function Ur(y){return y=y??"SSO Unavailable",new Response(JSON.stringify({error:y}),{status:503,statusText:y,headers:{"Content-Type":"application/json"}})}var pn="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.";async function xi(y,k){return t(k,pn),k.sso?.getUser(y)}async function Ui(y,k){return t(k,pn),await k.sso?.resolveUser(y)??{status:"unauthenticated"}}async function Ei(y,k){t(k,pn);let R=k.sso;if(!R)return Ur();return R.initiateLogin(y)}async function Mi(y,k){t(k,pn);let R=k.sso;if(!R)return Ur();return R.callbackHandler(y)}export{Ft as CACHE_BOUNDS,Qn as CIAM_PROVIDER_PRESETS,_ as CatalogAdjacencyCache,Z as InMemoryTenantStore,fs as allowHosts,ms as allowOrigins,pr as allowRelativePaths,mr as allowSameOrigin,Cr as assertSubjectTypeAssignable,cr as assertTrustedIdTokenClaims,Ln as baseCustomerToScim,On as baseUserToScimUser,Dn as baseWorkloadToScim,lr as blockDangerousUrls,An as buildAuthorizationUrl,Hn as buildLfvSigningInput,Mi as callback,ys as captureRedirect,ws as ciam,cs as clearDiscoveryCache,Zr as clearJwksCache,te as collectReferencedDefinitions,Jr as configureJwksCache,gs as defaultRedirectPolicies,xn as discoverOidcEndpoints,Pr as discoverSessionRecords,Tr as discoverSessions,_n as entitlementToScimGroup,Tn as exchangeAuthorizationCode,O as expandRoot,Un as fetchUserInfo,En as generateAppleClientSecret,pi as generateLfvEd25519KeyPair,Rn as getCachedVerificationKey,bs as getCustomer,bi as getDiscoveredSessionUsers,Wt as getJwks,gn as getProviderPreset,ts as getPublicKeyForKid,es as getPublicKeyFromJwks,xi as getUser,vn as getVerificationKeyForKid,Nr as has,zr as hasAll,Kr as hasAllScope,$r as hasAny,Gr as hasAnyScope,qr as hasGroup,Wr as hasPermission,Vr as hasRole,Br as hasScope,si as iam,Ei as initiateLogin,fr as isRedirectAllowed,Ai as listSsoClientIdsFromCookies,qt as normalizeOidcIssuer,hn as orderedEnabledProviders,Rr as parseLfvJwks,$t as pkceChallengeFromVerifier,z as reconcileSubjectAccess,wt as resolveAfterRedirect,mi as resolveCacheConfig,hs as resolveCapturedRedirect,Zt as resolveCiamProvider,Cs as resolveCustomer,Qr as resolveJwkForKid,vr as resolveJwksCacheConfig,yn as resolveProviderBranding,jn as resolveRedirect,Ir as resolveSessionCacheConfig,Ui as resolveUser,Mn as sameOriginRedirectRules,le as sendTenantWebhook,as as setDiscoveryClock,Hr as setJwksClock,Fr as setJwksRetry,li as signLfvPayload,Ti as sso,ai as stringifyLfvJwks,kt as verifyIdToken,di as verifyLfvSignature,Pn as verifyLogoutToken,vi as verifyUser,At as withSetCookies};
1
+ import{F,d,R,A,I,o,c,H,f,e,g,D,j,N,Y,L,n,p,X,Z,le,xe,K,Q,ee,W,te,m,q,ne,z,v,x,V,P,re,se,y,s,_,i,oe,r,w,h,B,a,l,t,ie,U,S,G,k,O,Re,Fe,u,b,C,ae,ce}from"./shared/core-anx7e6cp.js";var Us="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.",Lr=["user","customer","workload"],Es={user:async(T,E)=>E.sso?.getUser(T),customer:async(T,E)=>E.ciam?.getCustomer(T),workload:async(T,E)=>{let M=await E.workload?.getWorkloadIdentity?.(T);if(!M)return;let J=M.clientId??M.workloadId??M.claims.sub;return J?{...M,id:J}:void 0}};function Ms(T){if(T==="any")return Lr;let E=Array.isArray(T)?T:[T];return Lr.filter((M)=>E.includes(M))}function Ds(T){let E=T.headers.get("cookie");if(!E)return[];return E.split(";").map((M)=>M.slice(0,M.indexOf("=")===-1?M.length:M.indexOf("=")).trim()).filter(Boolean)}function Os(T,E){let M=T.headers.get("authorization")?.toLowerCase().startsWith("bearer ")??!1,J=Ds(T),ue=new Set;for(let me of J){if(me.startsWith("ion.sso"))ue.add("user");if(me.startsWith("ion.ciam"))ue.add("customer")}let pe=J.length>0&&!ue.has("user")&&!ue.has("customer");return E.filter((me)=>{if(me==="workload")return M;if(J.length===0)return!1;return ue.has(me)||pe})}function lt(T){return typeof T==="string"?T:T.id}function Nr(T){let{subject:E,subjectType:M}=T,J;if(M==="user")J=E.sso?.scope;else if(M==="customer")J=E.ciam?.scope;else if(M==="workload")J=E.scope;return new Set((J??"").split(/\s+/).filter(Boolean))}function Jn(T,E,M){let J=Nr(T),ue=E.filter((me)=>J.has(me));return{allow:M==="any"?ue.length>0:E.length>0&&ue.length===E.length,metadata:{reason:"scope",wantedScopes:E,matchedScopes:ue}}}function on(T,E){return(M)=>{if(T.length===0)return;let J=Nr(M),ue=T.filter((me)=>J.has(me));return(E==="any"?ue.length>0:ue.length===T.length)?ue:void 0}}function In(T,E,M){return(J)=>{if(E.length===0||J.subjectType!=="workload")return;let ue=F(T.config?.authz,J.subject);if(!ue)return;let pe=E.filter((ge)=>ue.has(ge));return(M==="any"?pe.length>0:pe.length===E.length)?pe:void 0}}function _s(T,E){if(T.subjectType==="workload"){let M=T.subject.scopesAsEntitlements;if(typeof M==="boolean")return M}return E.config?.authz?.scopesAsEntitlements===!0}function Gn(T,E,M,J,ue){return{allow:M==="ok",subject:E?.subject,subjectType:E?.subjectType,reason:M,decision:J,response(){if(M==="ok")return new Response(null,{status:204});if(M==="unauthenticated")return T.log.warn("authz.denied",{reason:M,...ue()}),Response.json({error:"Unauthorized"},{status:401});if(M==="not_configured")return T.log.warn("authz.denied",{reason:M,subject:E?.subject?.id,subjectType:E?.subjectType,...ue()}),Response.json({error:"not_configured"},{status:503});return T.log.warn("authz.denied",{reason:M,subject:E?.subject?.id,subjectType:E?.subjectType,...ue()}),Response.json({error:"Forbidden"},{status:403})}}}function js(T,E,M){return new Promise((J)=>{let ue=[],pe=T.length,me=!1,ge=()=>{if(pe-=1,pe===0&&!me)me=!0,J({outcomes:ue})};for(let ye of T)E(ye).then((fe)=>{if(ue.push({principal:ye,decision:fe}),!me&&fe.allow){me=!0,J({matched:{principal:ye,decision:fe},outcomes:ue});return}ge()},(fe)=>{M?.(ye,fe),ue.push({principal:ye,decision:{allow:!1,metadata:{reason:"error"}}}),ge()})})}async function Lt(T,E,M,J,ue,pe,me){t(E,Us);let ge=Os(T,Ms(M)),fe=(await Promise.all(ge.map(async(Oe)=>{let rt=await Es[Oe](T,E);return rt?.id?{subject:rt,subjectType:Oe,subjectId:rt.id}:void 0}))).filter((Oe)=>Oe!==void 0);if(fe.length===0)return Gn(E,void 0,"unauthenticated",void 0,ue);let $e=async(Oe)=>{let rt=E.authz.accessIndex;if(!rt?.isSubjectDisabled)return!1;return rt.isSubjectDisabled(Oe.subjectId,Oe.subjectType)},Xe=async(Oe)=>{if(me){let rt=me(Oe);if(rt&&rt.length>0){if(await $e(Oe))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"trusted-client",matchedPermissions:rt}}}}if(pe&&_s(Oe,E)){let rt=pe(Oe);if(rt&&rt.length>0){if(await $e(Oe))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"scope",matchedScopes:rt}}}}return J(Oe)},{matched:et,outcomes:st}=await js(fe,Xe,(Oe,rt)=>{E.log.warn("authz.check_error",{"ion.operation":"authz.check","ion.outcome":"error",subject:Oe.subjectId,subjectType:Oe.subjectType,error:rt instanceof Error?rt.message:String(rt),...ue()})});if(et){if(et.decision.metadata?.reason==="scope")E.log.info("authz.scope_honor",{"ion.operation":"authz.scope_honor","ion.outcome":"allow",subject:et.principal.subjectId,subjectType:et.principal.subjectType,matchedScopes:et.decision.metadata.matchedScopes,...ue()});return Gn(E,et.principal,"ok",et.decision,ue)}let it=st.length>0&&st.every((Oe)=>{let rt=Oe.decision.metadata?.reason;return rt==="access_index_not_configured"||rt==="error"}),Pe=st[0],He=it?"not_configured":"forbidden";return Gn(E,Pe?.principal,He,Pe?.decision,ue)}async function Ls(T,E,M,J,ue,pe="any"){return Lt(T,E,pe,(me)=>E.authz.has(me.subjectId,M,J,ue,me.subjectType),()=>({targetType:M,target:lt(J),resource:ue?lt(ue):void 0}),ue?void 0:on([lt(J)],"any"),M==="permission"&&!ue?In(E,[lt(J)],"any"):void 0)}async function Ns(T,E,M,J,ue="any"){return Lt(T,E,ue,(pe)=>E.authz.hasPermission(pe.subjectId,M,J,pe.subjectType),()=>({targetType:"permission",target:lt(M),resource:J?lt(J):void 0}),J?void 0:on([lt(M)],"any"),J?void 0:In(E,[lt(M)],"any"))}async function $s(T,E,M,J,ue="any"){return Lt(T,E,ue,(pe)=>E.authz.hasRole(pe.subjectId,M,J,pe.subjectType),()=>({targetType:"role",target:lt(M),resource:J?lt(J):void 0}),J?void 0:on([lt(M)],"any"))}async function Ws(T,E,M,J,ue="any"){return Lt(T,E,ue,(pe)=>E.authz.hasGroup(pe.subjectId,M,J,pe.subjectType),()=>({targetType:"group",target:lt(M),resource:J?lt(J):void 0}),J?void 0:on([lt(M)],"any"))}async function Vs(T,E,M,J="any"){let ue=M.filter((me)=>!me.resource).map((me)=>lt(me.target)),pe=M.filter((me)=>!me.resource&&me.targetType==="permission").map((me)=>lt(me.target));return Lt(T,E,J,(me)=>E.authz.hasAny(me.subjectId,M,me.subjectType),()=>({targets:M.map((me)=>`${me.targetType}:${lt(me.target)}`)}),ue.length>0?on(ue,"any"):void 0,pe.length>0?In(E,pe,"any"):void 0)}async function qs(T,E,M,J="any"){let ue=M.length>0&&M.every((ge)=>!ge.resource),pe=M.length>0&&M.every((ge)=>!ge.resource&&ge.targetType==="permission"),me=M.map((ge)=>lt(ge.target));return Lt(T,E,J,(ge)=>E.authz.hasAll(ge.subjectId,M,ge.subjectType),()=>({targets:M.map((ge)=>`${ge.targetType}:${lt(ge.target)}`)}),ue?on(me,"all"):void 0,pe?In(E,me,"all"):void 0)}async function zs(T,E,M,J="any"){return Lt(T,E,J,(ue)=>Promise.resolve(Jn(ue,[M],"any")),()=>({scope:M}))}async function Bs(T,E,M,J="any"){return Lt(T,E,J,(ue)=>Promise.resolve(Jn(ue,M,"any")),()=>({scopes:M}))}async function Ks(T,E,M,J="any"){return Lt(T,E,J,(ue)=>Promise.resolve(Jn(ue,M,"all")),()=>({scopes:M}))}function ht(T){return typeof T==="string"&&T.length>0?T:void 0}function $r(T){let E=ht(T.email);return{sub:String(T.sub??""),email:E,name:ht(T.name),userName:ht(T.preferred_username)??E,avatar:ht(T.picture)}}var Wr={oidc:{flow:"id_token",scope:"openid profile email",branding:{displayName:"Single sign-on"},mapClaims:$r},google:{flow:"id_token",authorizationUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",jwksUri:"https://www.googleapis.com/oauth2/v3/certs",scope:"openid email profile",branding:{displayName:"Google",iconUrl:"https://www.gstatic.com/firebasejs/ui/2.0.0/images/auth/google.svg",colors:{light:"#ffffff",dark:"#131314",secondary:"#4285F4"},url:"https://accounts.google.com"},mapClaims:$r},microsoft:{flow:"id_token",authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",jwksUri:"https://login.microsoftonline.com/common/discovery/v2.0/keys",scope:"openid email profile",branding:{displayName:"Microsoft",colors:{light:"#ffffff",dark:"#2f2f2f",secondary:"#0067b8"},url:"https://login.microsoftonline.com"},mapClaims:(T)=>{let E=ht(T.email)??ht(T.preferred_username);return{sub:String(T.sub??T.oid??""),email:E,name:ht(T.name),userName:ht(T.preferred_username)??E,avatar:ht(T.picture)}}},apple:{flow:"id_token",authorizationUrl:"https://appleid.apple.com/auth/authorize",tokenUrl:"https://appleid.apple.com/auth/token",jwksUri:"https://appleid.apple.com/auth/keys",scope:"openid email name",extraAuthParams:{response_mode:"form_post"},branding:{displayName:"Apple",colors:{light:"#000000",dark:"#ffffff"},url:"https://appleid.apple.com"},mapClaims:(T)=>{let E=ht(T.email);return{sub:String(T.sub??""),email:E,name:ht(T.name),userName:E}}},github:{flow:"userinfo",authorizationUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",userInfoUrl:"https://api.github.com/user",scope:"read:user user:email",branding:{displayName:"GitHub",colors:{light:"#24292f",dark:"#ffffff"},url:"https://github.com"},mapClaims:(T)=>({sub:String(T.id??T.node_id??""),email:ht(T.email),name:ht(T.name)??ht(T.login),userName:ht(T.login),avatar:ht(T.avatar_url)})}};function Hn(T){if(T==="magic-link")return;return Wr[T]}function Tn(T,E){if(E.type==="magic-link")return;let M=Hn(E.type);if(!M)return;return{name:T,type:E.type,flow:M.flow,authorizationUrl:E.authorizationUrl??M.authorizationUrl,tokenUrl:E.tokenUrl??M.tokenUrl,jwksUri:E.jwksUri??M.jwksUri,userInfoUrl:E.userInfoUrl??M.userInfoUrl,scope:E.scope??M.scope,clientId:E.clientId,clientSecret:E.clientSecret,extraAuthParams:M.extraAuthParams,branding:{...M.branding,...E.branding},mapClaims:M.mapClaims,config:E}}function Fn(T){return{...Hn(T.type)?.branding??{displayName:T.type},...T.branding}}function Yn(T){if(!T)return[];return Object.entries(T).filter(([,E])=>E.enabled!==!1).map(([E,M],J)=>({name:E,config:M,index:J})).sort((E,M)=>{let J=E.config.order??Number.MAX_SAFE_INTEGER,ue=M.config.order??Number.MAX_SAFE_INTEGER;if(J!==ue)return J-ue;return E.index-M.index}).map(({name:E,config:M})=>({name:E,config:M}))}var Gs=/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;function xn(T){if(T===void 0)return;let E=T.trim().toLowerCase();if(!Gs.test(E))throw Error(`Invalid cookiesDomain "${T}": expected a hostname such as "app.example.com" without a scheme, port, path, or leading dot.`);return E}function Bt(T){return T?` Domain=${T};`:""}var Vr=4000;function Js(T){return`Expires=${T.toUTCString()}`}function qr(T){return`Path=${T.path};${Bt(T.domain)}${T.secure?" Secure;":""} SameSite=${T.sameSite};`}function Qn(T,E,M,J){if(E.length>Vr)throw Error(`Display cookie ${T} value is ${E.length} bytes; the limit is ${Vr}.`);return`${T}=${E}; ${Js(M)}; ${qr(J)}`}function Nt(T,E){return`${T}=; Max-Age=0; ${qr(E)}`}function Xn(T){if(!T)return;let E=T instanceof Date?T:new Date(T);return Number.isNaN(E.getTime())?void 0:E}function Zn(T){return!T||T.getTime()>Date.now()}async function Hs(T,E,M){let J=T.envelope.kind??"session";if(J==="discovered"){let ge=Xn(T.envelope.expiresAt);return{...T,kind:J,live:Boolean(ge&&Zn(ge))}}let ue=E[`${T.prefix}.session`];if(!ue)return{...T,kind:J,live:!1};let pe=await M.get(ue);if(!pe||pe.authType!=="sso"&&pe.authType!=="ciam")return{...T,kind:J,live:!1};let me=Xn(pe.expiresAt);return{...T,kind:J,live:Zn(me),...me?{sessionExpiresAt:me}:{}}}function an(T,E,M){let J=x(E);return T?.includes(`${J}=`)?[Nt(J,M)]:[]}function zr(T,E,M,J,ue){let pe=[...T.filter(($e)=>$e.kind==="session").slice(0,M),...T.filter(($e)=>$e.kind==="discovered").slice(0,J)],me=ue?ue(T,{max:M,maxDiscovered:J}):pe,ge=[...me.filter(($e)=>$e.kind==="session").slice(0,M),...me.filter(($e)=>$e.kind==="discovered").slice(0,J)];if(ge.some(($e)=>$e.name===E))return ge;let ye=T.find(($e)=>$e.name===E);if(!ye)return ge;return[...[ye,...ge.filter(($e)=>$e.kind==="session")].slice(0,M),...ge.filter(($e)=>$e.kind==="discovered")]}async function mn(T){let E=x(T.cookiesPrefix),M=T.attr;if(T.displayCookie?.enabled!==!0)return an(T.cookieHeader,T.cookiesPrefix,M);if(!T.sessionStore)return[];let J=m(T.user,T.projector),ue={v:K,...T.tenantId?{tenantId:T.tenantId}:{},authType:T.authType,expiresAt:T.expiresAt.toISOString(),user:J},pe={name:E,prefix:T.cookiesPrefix,envelope:ue,kind:"session",sessionExpiresAt:T.expiresAt,live:!0},me=ne(T.cookieHeader),ge=T.sessionStore,ye=await Promise.all(z(T.cookieHeader).filter((He)=>He.name!==E).map((He)=>Hs(He,me,ge))),fe=[pe,...ye.filter((He)=>He.live&&He.kind==="session")].sort((He,Oe)=>v(He.sessionExpiresAt?.toISOString()??He.envelope.expiresAt,Oe.sessionExpiresAt?.toISOString()??Oe.envelope.expiresAt)),$e=T.displayCookie.discovered?.enabled===!0?ye.filter((He)=>He.live&&He.kind==="discovered"&&(!T.tenantId||He.envelope.tenantId!==T.tenantId)).sort((He,Oe)=>v(He.envelope.expiresAt,Oe.envelope.expiresAt)):[],Xe=[...fe,...$e],et=ee(T.displayCookie?.max),st=W(T.displayCookie.discovered?.max),it=new Set(zr(Xe,E,et,st,T.trim).map((He)=>He.name)),Pe=[Qn(E,q(ue),T.expiresAt,M)];for(let He of ye)if(!it.has(He.name))Pe.push(Nt(He.name,M));return Pe}function Fs(T){let E=ne(T.cookieHeader),M=Object.keys(E).filter((Pe)=>Pe.startsWith(`${Q}.`)&&Pe.endsWith(".profile"));if(!(T.displayCookie?.enabled===!0&&T.displayCookie.discovered?.enabled===!0))return M.map((Pe)=>Nt(Pe,T.attr));let ue=T.now??new Date,pe=te(T.displayCookie?.discovered?.ttlSeconds),me=new Date(ue.getTime()+pe*1000),ge=W(T.displayCookie?.discovered?.max),ye=z(T.cookieHeader),fe=new Set(ye.filter((Pe)=>(Pe.envelope.kind??"session")==="session").flatMap((Pe)=>Pe.envelope.tenantId?[Pe.envelope.tenantId]:[])),$e=new Map;for(let Pe of ye){if(Pe.envelope.kind!=="discovered"||!Pe.envelope.tenantId)continue;let He=Xn(Pe.envelope.expiresAt);if(He&&Zn(He)&&!fe.has(Pe.envelope.tenantId))$e.set(Pe.envelope.tenantId,Pe.envelope)}let Xe=m(T.user,T.projector);for(let Pe of T.tenants){let He=Pe.tenantId.trim();if(!He||fe.has(He))continue;$e.set(He,{v:K,kind:"discovered",tenantId:He,authType:T.authType,expiresAt:me.toISOString(),user:Xe,...Pe.tenantName?{tenantName:Pe.tenantName}:{}})}let et=[...$e.values()].sort((Pe,He)=>v(Pe.expiresAt,He.expiresAt)).slice(0,ge),st=new Set(et.map((Pe)=>V(Pe.tenantId??""))),it=et.map((Pe)=>Qn(V(Pe.tenantId??""),q(Pe),new Date(Pe.expiresAt),T.attr));for(let Pe of M)if(!st.has(Pe))it.push(Nt(Pe,T.attr));return it}var sr=60000,Kr=86400000,Gr=600000,tr=256,vt=new Map;function Ys(T){if(typeof T?.ttlMs==="number"&&Number.isFinite(T.ttlMs))Gr=Math.min(Math.max(T.ttlMs,sr),Kr);if(typeof T?.maxEntries==="number"&&Number.isFinite(T.maxEntries)){tr=Math.max(1,Math.floor(T.maxEntries));while(vt.size>tr){let E=vt.keys().next().value;if(E===void 0)break;vt.delete(E)}}}function Br(T,E){vt.delete(T),vt.set(T,E);while(vt.size>tr){let M=vt.keys().next().value;if(M===void 0)break;vt.delete(M)}}var fn=new Map,nr=()=>Date.now();function Xs(T){nr=T??(()=>Date.now())}var rr={};function Zs(T){rr=T??{}}function Qs(T){if(!T)return;if(/\bno-store\b/i.test(T))return sr;let E=/max-age\s*=\s*(\d+)/i.exec(T);if(!E)return;let M=Number(E[1]);return Number.isFinite(M)?M*1000:void 0}function ei(T){let M=Qs(T)??Gr;return Math.min(Math.max(M,sr),Kr)}async function ir(T,E=3,M=1000,J=30000,ue){let pe=Error("Placeholder Error");for(let me=0;me<=E;me++)try{return await T()}catch(ge){if(pe=ge instanceof Error?ge:Error(String(ge)),ge instanceof Error&&ge.message.includes("400"))throw ge;if(me===E)throw pe;let ye=Math.min(M*2**me,J),fe=Math.random()*0.1*ye;await new Promise(($e)=>setTimeout($e,ye+fe)),ue?.warn(`Retry attempt ${me+1} after ${ye+fe}ms delay`)}throw pe}async function gn(T,E,M){let J=vt.get(T);if(!M?.forceRefresh&&J&&J.expiresAt>nr())return Br(T,J),J.jwks;let ue=fn.get(T);if(ue)return ue;let pe=(async()=>{try{return await ir(async()=>{let me=await fetch(T,{headers:i});if(!me.ok){let fe=await B(me);throw E?.warn("JWKS endpoint returned an error",{"ion.operation":"jwks.fetch","ion.outcome":"degraded",reason:"upstream_error",status:me.status,contentType:fe.contentType,excerpt:fe.excerpt}),Error(`Failed to fetch JWKS (${me.status})`)}let ge=await a(me,{log:E,operation:"jwks.fetch"}),ye=ei(me.headers.get("cache-control"));return Br(T,{jwks:ge,expiresAt:nr()+ye,importedKeys:new Map}),ge},rr.maxRetries,rr.baseDelayMs,void 0,E)}catch(me){let ge=vt.get(T);if(ge)return E?.warn("JWKS refresh failed; serving last-known-good keys",{"ion.operation":"jwks.refresh","ion.outcome":"degraded"}),ge.jwks;throw me}finally{fn.delete(T)}})();return fn.set(T,pe),pe}function ti(T){if(T){vt.delete(T),fn.delete(T);return}vt.clear(),fn.clear()}async function ni(T,E,M){return(await Jr(T,E,M)).jwk}async function Jr(T,E,M){if(!E?.trim())throw Error("JWT header missing kid");await gn(T,M);let J=vt.get(T),ue=J?.jwks.keys.find((pe)=>pe.kid===E);if(!ue)await gn(T,M,{forceRefresh:!0}),J=vt.get(T),ue=J?.jwks.keys.find((pe)=>pe.kid===E);if(!J||!ue)throw Error("Public key not found");return{jwk:ue,entry:J}}async function or(T,E,M,J,ue){let{jwk:pe,entry:me}=await Jr(T,E,ue),ge=`${E}\x00${M}`,ye=me.importedKeys.get(ge);if(ye)return ye;let fe=J(pe);return fe.catch(()=>{if(me.importedKeys.get(ge)===fe)me.importedKeys.delete(ge)}),me.importedKeys.set(ge,fe),fe}async function ri(T,E){let M=T.keys.find((J)=>J.kid===E);if(!M)throw Error("Public key not found");return Hr(M)}function Hr(T){return crypto.subtle.importKey("jwk",{kty:T.kty,n:T.n,e:T.e},{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},!1,["verify"])}async function si(T,E,M){return or(T,E,"rs256",Hr,M)}var er={RS256:{kty:"RSA",importParams:{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},verifyParams:{name:"RSASSA-PKCS1-v1_5"}},ES256:{kty:"EC",crv:"P-256",importParams:{name:"ECDSA",namedCurve:"P-256"},verifyParams:{name:"ECDSA",hash:"SHA-256"}}};async function ar(T,E,M,J){if(typeof M!=="string"||!(M in er))throw Error(`Unsupported JWT alg "${String(M)}" (allowed: ${Object.keys(er).join(", ")})`);let ue=er[M];return{key:await or(T,E,`oidc:${M}`,(me)=>{if(me.kty!==ue.kty)throw Error(`JWK type "${me.kty}" does not match token alg "${M}"`);if(ue.kty==="EC"){let ge=me;if(ge.crv!==ue.crv)throw Error(`JWK curve "${String(ge.crv)}" does not match token alg "${M}"`);return crypto.subtle.importKey("jwk",{kty:"EC",crv:ge.crv,x:ge.x,y:ge.y},ue.importParams,!1,["verify"])}return crypto.subtle.importKey("jwk",{kty:me.kty,n:me.n,e:me.e},ue.importParams,!1,["verify"])},J),algorithm:ue.verifyParams}}function Pt(T=32){let E=new Uint8Array(T);return crypto.getRandomValues(E),Array.from(E,(M)=>M.toString(16).padStart(2,"0")).join("").substring(0,T)}function Pn(T){let E="";return T.forEach((M)=>{E+=String.fromCharCode(M)}),btoa(E).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function Xr(T){let E=T.replace(/-/g,"+").replace(/_/g,"/"),M=E.padEnd(E.length+(4-E.length%4)%4,"="),J=atob(M),ue=new Uint8Array(J.length);for(let pe=0;pe<J.length;pe++)ue[pe]=J.charCodeAt(pe);return ue}function Fr(T){let E=new TextDecoder().decode(Xr(T));return JSON.parse(E)}async function kn(T){let E=new TextEncoder().encode(T),M=await crypto.subtle.digest("SHA-256",E);return Pn(new Uint8Array(M))}function ur(T){let E=new URL(T.authorizationUrl);if(E.searchParams.set("client_id",T.clientId),E.searchParams.set("redirect_uri",T.redirectUri),E.searchParams.set("response_type","code"),E.searchParams.set("scope",T.scope),E.searchParams.set("state",T.state),T.codeChallenge)E.searchParams.set("code_challenge",T.codeChallenge),E.searchParams.set("code_challenge_method","S256");if(T.nonce)E.searchParams.set("nonce",T.nonce);for(let[M,J]of Object.entries(T.extraParams??{}))E.searchParams.set(M,J);return E.toString()}async function dr(T){let E=new URLSearchParams;if(E.append("grant_type","authorization_code"),E.append("code",T.code),E.append("redirect_uri",T.redirectUri),E.append("client_id",T.clientId),T.clientSecret)E.append("client_secret",T.clientSecret);if(T.codeVerifier)E.append("code_verifier",T.codeVerifier);let M=await fetch(T.tokenUrl,{method:"POST",headers:{...h,...i},body:E.toString()}),J=await a(M,{log:T.log,operation:"oidc.token.exchange"});if(!M.ok){let ue=J,pe=ue.error==="invalid_client"&&!T.clientSecret;throw T.log?.error(pe?"OIDC authorization-code exchange failed: no client_secret was configured; the provider may require a confidential client":"OIDC authorization-code exchange failed",{"ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":M.status,oidc_error:ue.error,...pe?{client_auth:"none"}:{}}),Error(`Token exchange failed: ${ue.error||M.statusText} - ${ue.error_description||""}`.trim())}if(typeof J.access_token!=="string")throw Error("Token exchange response missing access_token");return J}var Zr=60;function hn(T){return T.trim().replace(/\/$/,"")}function Qr(T){let{claims:E,audience:M}=T,J=hn(T.issuer),ue=T.nowSec??Math.floor(Date.now()/1000),pe=T.clockSkewSec??Zr,me=E.iss;if(typeof me!=="string"||hn(me)!==J)throw Error("ID token issuer mismatch");let ge=E.aud,ye=Array.isArray(ge)?ge.includes(M):typeof ge==="string"&&ge===M,fe=typeof E.azp==="string"&&E.azp===M;if(!ye&&!fe)throw Error("ID token audience mismatch");if(typeof E.exp!=="number")throw Error("ID token missing exp");if(E.exp<ue-pe)throw Error("ID token expired");if(T.expectedNonce!==void 0){if(E.nonce!==T.expectedNonce)throw Error("ID token nonce mismatch")}}async function es(T,E,M){let J=T.split(".");if(J.length!==3)throw Error("Invalid JWT");let ue=Fr(J[0]),pe=Fr(J[1]),me=Xr(J[2]),{key:ge,algorithm:ye}=await ar(E,ue.kid,ue.alg,M),fe=new TextEncoder().encode(`${J[0]}.${J[1]}`);if(!await crypto.subtle.verify(ye,ge,me,fe))throw Error("Invalid JWT signature");return{header:ue,payload:pe}}async function Kt(T){let{payload:E}=await es(T.idToken,T.jwksUri,T.log);return Qr({claims:E,issuer:T.issuer,audience:T.audience,clockSkewSec:T.clockSkewSec,expectedNonce:T.expectedNonce}),E}var ii="http://schemas.openid.net/event/backchannel-logout";async function lr(T){let{payload:E}=await es(T.logoutToken,T.jwksUri,T.log),M=hn(T.issuer),J=E.iss;if(typeof J!=="string"||hn(J)!==M)throw Error("Logout token issuer mismatch");let ue=E.aud,pe=Array.isArray(ue)?ue.includes(T.audience):typeof ue==="string"&&ue===T.audience,me=typeof E.azp==="string"&&E.azp===T.audience;if(!pe&&!me)throw Error("Logout token audience mismatch");if(E.nonce!=null)throw Error("Logout token must not contain a nonce");let ge=E.events;if(!(typeof ge==="object"&&ge!==null&&!Array.isArray(ge)&&Object.hasOwn(ge,ii)))throw Error("Logout token missing back-channel logout event");let fe=typeof E.sid==="string"&&E.sid.length>0,$e=typeof E.sub==="string"&&E.sub.length>0;if(!fe&&!$e)throw Error("Logout token missing sid and sub");if(typeof E.exp==="number"){let Xe=Math.floor(Date.now()/1000),et=T.clockSkewSec??Zr;if(E.exp<Xe-et)throw Error("Logout token expired")}return E}var oi=3600000,ai=60000,ci=86400000,ui=256,$t=new Map,yn=new Map;function Yr(T,E){$t.delete(T),$t.set(T,E);while($t.size>ui){let M=$t.keys().next().value;if(M===void 0)break;$t.delete(M)}}var cr=()=>Date.now();function di(T){cr=T??(()=>Date.now())}function li(T){if(T){$t.delete(T),yn.delete(T);return}$t.clear(),yn.clear()}function pi(T){let E=T?/max-age\s*=\s*(\d+)/i.exec(T):null,M=E?Number(E[1]):Number.NaN,J=Number.isFinite(M)?M*1000:oi;return Math.min(Math.max(J,ai),ci)}async function pr(T){let E=$t.get(T);if(E&&E.expiresAt>cr())return Yr(T,E),E.endpoints;let M=yn.get(T);if(M)return M;let J=(async()=>{try{let ue=T.replace(/\/$/,""),pe=await fetch(`${ue}/.well-known/openid-configuration`,{headers:i});if(!pe.ok)throw Error(`OIDC discovery failed for ${T} with status ${pe.status}`);let me=await a(pe),ge={authorizationUrl:typeof me.authorization_endpoint==="string"?me.authorization_endpoint:void 0,tokenUrl:typeof me.token_endpoint==="string"?me.token_endpoint:void 0,jwksUri:typeof me.jwks_uri==="string"?me.jwks_uri:void 0,userInfoUrl:typeof me.userinfo_endpoint==="string"?me.userinfo_endpoint:void 0};return Yr(T,{endpoints:ge,expiresAt:cr()+pi(pe.headers.get("cache-control"))}),ge}catch(ue){let pe=$t.get(T);if(pe)return pe.endpoints;throw ue}finally{yn.delete(T)}})();return yn.set(T,J),J}async function mr(T,E){let M=await fetch(T,{headers:{Authorization:`Bearer ${E}`,...i,"User-Agent":"ionite-ciam"}});if(!M.ok)throw Error(`UserInfo request failed with status ${M.status}`);return await a(M)}function mi(T){let E=T.replace(/-----BEGIN [^-]+-----/g,"").replace(/-----END [^-]+-----/g,"").replace(/\s+/g,""),M=atob(E),J=new Uint8Array(M.length);for(let ue=0;ue<M.length;ue++)J[ue]=M.charCodeAt(ue);return J}async function fr(T){let E=Math.floor(Date.now()/1000),M={alg:"ES256",kid:T.keyId,typ:"JWT"},J={iss:T.teamId,iat:E,exp:E+(T.expiresInSeconds??3600),aud:"https://appleid.apple.com",sub:T.clientId},ue=Pn(new TextEncoder().encode(JSON.stringify(M))),pe=Pn(new TextEncoder().encode(JSON.stringify(J))),me=`${ue}.${pe}`,ge=await crypto.subtle.importKey("pkcs8",mi(T.privateKey),{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),ye=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},ge,new TextEncoder().encode(me));return`${me}.${Pn(new Uint8Array(ye))}`}function fi(T){for(let E=0;E<T.length;E++){let M=T.charCodeAt(E);if(M<=31||M===127)return!0}return!1}function gi(T,E){let M=null;try{M=new URL(T,E)}catch{M=null}let J="";try{J=new URL(E).origin}catch{J=""}return{candidate:T,url:M,requestOrigin:J}}function ts(T,E,M){let J=gi(T,M),ue=!1;for(let pe of E){let me=pe(J);if(me==="deny")return!1;if(me==="allow")ue=!0}return ue}function ns(){return({candidate:T,url:E})=>{if(fi(T))return"deny";if(T.includes("\\"))return"deny";if(T.startsWith("//"))return"deny";if(!E)return"deny";if(E.protocol!=="http:"&&E.protocol!=="https:")return"deny";if(E.username||E.password)return"deny";return"abstain"}}function rs(){return({candidate:T})=>T.startsWith("/")&&!T.startsWith("//")&&!T.startsWith("/\\")?"allow":"abstain"}function ss(){return({url:T,requestOrigin:E})=>T&&E&&T.origin===E?"allow":"abstain"}function yi(...T){let E=new Set(T.map((M)=>{try{return new URL(M).origin}catch{return M}}));return({url:M})=>M&&E.has(M.origin)?"allow":"abstain"}function hi(...T){let E=T.map((M)=>M.toLowerCase());return({url:M})=>{if(!M)return"abstain";let J=M.hostname.toLowerCase();for(let ue of E)if(ue.startsWith(".")){if(J===ue.slice(1)||J.endsWith(ue))return"allow"}else if(J===ue)return"allow";return"abstain"}}function gr(){return[ns(),rs(),ss()]}function is(T,E,M){if(!T)return!1;return ts(T,E,M)}function yr(T,E){if(!T)return E.fallback;return ts(T,E.rules,E.requestUrl)?T:E.fallback}var ki={rules:gr(),fallback:"/"};function Si(T,E,M="redirect"){let J=new URL(T.url).searchParams.get(M)??void 0;return is(J,E.rules,T.url)?{redirect:J}:void 0}function wi(T,E){let M=T.context;return yr(M?.redirect,{rules:E.rules,fallback:E.fallback,requestUrl:T.request.url})}function Gt(T,E,M){if(T instanceof Response)return{response:T};if(typeof T==="string")return{location:yr(T,{rules:gr(),fallback:E,requestUrl:M})};return{location:E}}function Yt(T,E){if(E.length===0)return T;let M=new Headers(T.headers);for(let J of E)M.append("Set-Cookie",J);return new Response(T.body,{status:T.status,statusText:T.statusText,headers:M})}var Un="ciam",Ci="id_token",bi="access_token";function vi(T,E,M,J,ue,pe){if(!M&&!J)return;let me=new WeakMap,ge={...M,...J},ye={...ge,magicLinkTtl:ge.magicLinkTtl??3600,sessionTtl:ge.sessionTtl??86400,cookiesSecure:ge.cookiesSecure!==void 0?ge.cookiesSecure:!0,cookiesSameSite:ge.cookiesSameSite!==void 0?ge.cookiesSameSite:"Strict",cookiesPrefix:ge.cookiesPrefix??(ge.ciamId?`ion.ciam.${ge.ciamId}`:"ion.ciam"),cookiesPath:ge.cookiesPath??"/",cookiesDomain:xn(ge.cookiesDomain)};function fe(){if(!ye.sessionStore)throw Error("Missing CIAM configuration field: sessionStore. CIAM sessionStore is required for server-side session tracking and first-party logout.");return ye.sessionStore}function $e(){fe()}let Xe=T.callbackParams??l(re("ionite.ciam")),et=T.idTokenClaims??l(y("ionite.ciam")),st=T.tokenResponse??l(se("ionite.ciam"));function it(de=32){let Se=new Uint8Array(de);return crypto.getRandomValues(Se),Array.from(Se,(ke)=>ke.toString(16).padStart(2,"0")).join("").substring(0,de)}function Pe(de,Se,ke,Ce=ye.cookiesSameSite??"Strict"){if(!ye)throw Error("ionite CIAM Manager not initialized");if(de=`${ye.cookiesPrefix}.${de}`,typeof Se!=="string")Se=btoa(JSON.stringify(Se));let Ue;if(ke instanceof Date)Ue=`Expires=${ke.toUTCString()}`;else if(typeof ke==="number")Ue=`Max-Age=${ke}`;else throw Error("Invalid expires type",ke);if(Se.length>4000)throw Error(`Error setting cookie: ${de}. Cookie length is: ${Se.length}`);return`${de}=${Se}; ${Ue}; Path=${ye.cookiesPath};${Bt(ye.cookiesDomain)} HttpOnly;${ye.cookiesSecure?" Secure;":""} SameSite=${Ce};`}function He(de){if(!ye)throw Error("ionite CIAM Manager not initialized");return`${ye.cookiesPrefix}.${de}=; Max-Age=0; Path=${ye.cookiesPath};${Bt(ye.cookiesDomain)} HttpOnly;${ye.cookiesSecure?" Secure;":""} SameSite=${ye.cookiesSameSite};`}function Oe(de,Se,ke=!1){if(!ye)throw Error("ionite CIAM Manager not initialized");let Ce=Se.headers.get("cookie");if(!Ce)return null;let Ue=`${ye.cookiesPrefix}.${de}`,_e=Ce.split(";").find((Ee)=>Ee.trim().startsWith(`${Ue}=`));if(!_e)return null;let Le=_e.indexOf("="),je=_e.substring(Le+1).trim();if(!ke)return je;try{let Ee=atob(je);return JSON.parse(Ee)}catch(Ee){return E.error("[CIAM] Failed to parse cookie",{"ion.operation":"cookie.parse","ion.outcome":"failure",cookieName:Ue},Ee),null}}function rt(de){return`cstate_${de}`}async function ot(de,Se,ke,Ce){let Ue=await ye.afterLogin?.({...Se,request:de,context:ke,displayCookie:ye.displayCookie,displayCookieAttributes:St()}),_e=Gt(Ue,"/",de.url);if(_e.response)return Yt(_e.response,Ce.map(([,Le])=>Le));return new Response(Se.ok?"Authentication successful, redirecting":"Authentication failed, redirecting",{status:302,headers:[["Location",_e.location],...Ce]})}function ut(de,Se){return["Set-Cookie",Pe("session",de,Se)]}function St(){return{path:ye.cookiesPath??"/",domain:ye.cookiesDomain,secure:ye.cookiesSecure!==!1,sameSite:ye.cookiesSameSite??"Strict"}}function pt(){return[["Set-Cookie",He("session")],["Set-Cookie",Nt(`${ye.cookiesPrefix}.profile`,St())]]}function gt(de){if(ye.displayCookie?.enabled===!0)return[];return an(de.headers.get("cookie"),ye.cookiesPrefix??"ion.ciam",St()).map((Se)=>["Set-Cookie",Se])}async function wt(de,Se,ke){return(await mn({cookieHeader:de.headers.get("cookie"),sessionStore:ye.sessionStore,cookiesPrefix:ye.cookiesPrefix??"ion.ciam",authType:"ciam",tenantId:ye.tenantId,expiresAt:ke,user:Se,projector:ye.displayUser,displayCookie:ye.displayCookie,trim:ye.trimDisplayCookies,attr:St()})).map((Ue)=>["Set-Cookie",Ue])}function en(de){if(!de)return;if(de instanceof Date)return de;let Se=new Date(de);return Number.isNaN(Se.getTime())?void 0:Se}async function tn(de){let Se=Oe("session",de);if(!Se)return;let ke=await fe().get(Se);if(ke&&ye.tenantId&&ke.tenantId&&ke.tenantId!==ye.tenantId)return;if(ke?.authType!=="ciam")return;let Ce=en(ke.expiresAt);if(Ce&&Date.now()>Ce.getTime()){await fe().delete(Se);return}return ke}async function Ft(de){if(!ye)throw Error("ionite CIAM Manager not initialized");$e();let Se=me.get(de);if(Se)return Se;let ke=ln(de);return me.set(de,ke),ke}async function ln(de){try{let Se=await tn(de);if(!Se?.claims?.sub)return{status:"unauthenticated"};return{status:"authenticated",value:qt(Se.claims)}}catch(Se){return E.error("CIAM session resolution failed",{"ion.operation":"ciam.session","ion.outcome":"degraded"},Se),{status:"degraded",error:Se instanceof Error?Se:void 0}}}async function nn(de){let Se=await Ft(de);return Se.status==="authenticated"?Se.value:void 0}async function Ot(de){if(!ye)throw Error("ionite CIAM Manager not initialized");$e();let Se;try{Se=await nn(de)}catch{Se=void 0}let ke=await ye.beforeLogout?.({request:de,user:Se});try{let Ke=Oe("session",de);if(Ke)await fe().delete(Ke)}catch(Ke){E.warn("Failed to delete CIAM session",{"ion.operation":"session.delete","ion.outcome":"degraded"},Ke)}let Ce=pt(),Ue=await ye.afterLogout?.({request:de,context:ke}),_e=Gt(Ue,"/",de.url);if(_e.response)return Yt(_e.response,Ce.map(([,Ke])=>Ke));let Le=_e.location??"/",je=de.headers.get("accept");if(je?.includes(s)||je?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:Le}),{status:200,headers:[["Content-Type",s],...Ce]});return new Response("Logged out",{status:302,headers:[["Location",Le],...Ce]})}function Vt(de){return de.id||de.email||`ciam-${de.userName}`}function _t(de,Se,ke){return{sub:Vt(de),iss:Un,aud:Un,typ:Ci,exp:Math.floor(ke.getTime()/1000),iat:Math.floor(Date.now()/1000),email:de.email,name:de.name,preferred_username:de.userName,picture:de.avatar,sid:Se}}function rn(de,Se,ke){return{sub:de,iss:Un,aud:Un,typ:bi,exp:Math.floor(ke.getTime()/1000),iat:Math.floor(Date.now()/1000),sid:Se,scope:"openid profile email"}}function qt(de){let Se=de.exp?new Date(de.exp*1000):new Date;return{id:de.sub,userName:de.preferred_username??"",name:de.name??"",email:de.email??"",avatar:de.picture,userType:"customer",ciam:{profile:de,scope:"openid profile email",tokenType:"Bearer",expires:Se}}}async function zt(de){if(!ye)throw Error("ionite CIAM Manager not initialized");if(!ue)return new Response(JSON.stringify({error:"Workload authentication required"}),{status:401,headers:r});if(!await ue.getWorkloadIdentity(de))return new Response(JSON.stringify({error:"Unauthorized: Valid workload token required"}),{status:401,headers:r});let ke,Ce;try{if(!de.headers.get("content-type")?.includes(s))return new Response(JSON.stringify({error:"Content-Type must be application/json"}),{status:400,headers:r});let Ie=await de.text(),Ae=JSON.parse(Ie);Ce=typeof Ae?.redirect==="string"&&Ae.redirect.length>0?Ae.redirect:void 0;let Me={userName:Ae.userName,name:Ae.name,email:Ae.email,avatar:Ae.avatar},Ve=await T.customer.validate(Me);if(Ve.issues)return new Response(JSON.stringify({error:"Missing required fields: userName, name, email"}),{status:400,headers:r});ke=Ve.value}catch(ve){return new Response(JSON.stringify({error:"Invalid JSON in request body"}),{status:400,headers:r})}let _e=new URL(de.url).searchParams.get("ttl"),Le=_e?parseInt(_e,10):ye.magicLinkTtl??3600;if(Number.isNaN(Le)||Le<=0)return new Response(JSON.stringify({error:"Invalid TTL parameter"}),{status:400,headers:r});let je=it(32),Ee=new Date(Date.now()+Le*1000);if(!ye.magicLinkStore)return new Response(JSON.stringify({error:"Magic link store not configured"}),{status:501,headers:r});try{await ye.magicLinkStore.create(je,ke,Ee)}catch(ve){return E.error("Error creating magic link",{"ion.operation":"magic_link.create","ion.outcome":"failure"},ve),new Response(JSON.stringify({error:"Failed to create magic link"}),{status:500,headers:r})}let Ke=new URL(de.url),be=ye.magicLinkLoginUrl||"/magic-link/login",he=new URL(be,Ke.origin);if(he.searchParams.set("token",je),Ce)he.searchParams.set("redirect",Ce);return new Response(JSON.stringify({magicLink:he.toString(),expiresAt:Ee.toISOString()}),{status:200,headers:r})}async function Rt(de){if(!ye)throw Error("ionite CIAM Manager not initialized");$e();let ke=new URL(de.url).searchParams.get("token");if(!ke)return ot(de,{ok:!1,error:Error("Missing magic-link token")},void 0,[]);if(!ye.magicLinkStore)return ot(de,{ok:!1,error:Error("Magic link store not configured")},void 0,[]);let Ce=await ye.magicLinkStore.getAndDelete(ke);if(!Ce)return ot(de,{ok:!1,error:Error("Magic link invalid, expired, or already used")},void 0,[]);let Ue=new Date(Date.now()+(ye.sessionTtl??86400)*1000),_e=it(32),Le=Vt(Ce.customer),je=_t(Ce.customer,_e,Ue),Ee=rn(Le,_e,Ue),Ke=qt(je),be;try{let ve={sid:_e,sub:Le,authType:"ciam",tenantId:ye.tenantId,expiresAt:Ue,claims:je,accessClaims:Ee,createdAt:new Date};await fe().create(ve),be=ve}catch(ve){throw E.warn("Failed to create session",{"ion.operation":"session.create","ion.outcome":"degraded"},ve),ve}if(ye.customerStore)try{let ve=Ke.id;if(ve){let Ie=new Date,Ae=await ye.customerStore.get(ve);if(Ae||ye.enableJitUserProvisioning){let Me={...Ae??{},...Ke,id:ve,tenantId:Ae?.tenantId,createdAt:Ae?.createdAt??Ie,updatedAt:Ie,userType:Ae?.userType??"customer"};await ye.customerStore.upsert(Me)}}}catch(ve){E.warn("Failed to store customer",{"ion.operation":"customer.store","ion.outcome":"degraded"},ve)}let he=[ut(_e,Ue),...await wt(de,Ke,Ue)];return ot(de,{ok:!0,user:Ke,session:be},void 0,he)}function At(de,Se=200,ke=[]){return new Response(JSON.stringify(de),{status:Se,headers:[["Content-Type",s],...ke]})}function xt(de,Se){try{return new URL(de).toString()}catch{let ke=new URL(Se).origin,Ce=ye.cookiesSecure?ke.replace(/^http:\/\//,"https://"):ke;return new URL(de,Ce).toString()}}function jt(){let de=ye.customerLoginUrl||"/auth/customer/login",Se=de.includes("?")?"&":"?";return Yn(ye.providers).map(({name:ke,config:Ce})=>{let Ue=Fn(Ce);return{name:ke,type:Ce.type,displayName:Ue.displayName,loginUrl:`${de}${Se}provider=${encodeURIComponent(ke)}`,iconUrl:Ue.iconUrl,colors:Ue.colors,url:Ue.url}})}async function Et(de){if(!de)return{};let{authorizationUrl:Se,tokenUrl:ke,jwksUri:Ce,userInfoUrl:Ue}=de,_e=de.config.authority;if(_e&&(!Se||!ke||de.flow==="id_token"&&!Ce))try{let je=await pr(_e);Se=Se??je.authorizationUrl,ke=ke??je.tokenUrl,Ce=Ce??je.jwksUri,Ue=Ue??je.userInfoUrl}catch(je){E.error("CIAM provider OIDC discovery failed",{"ion.operation":"ciam.oidc.discovery","ion.outcome":"failure"},je)}return{authorizationUrl:Se,tokenUrl:ke,jwksUri:Ce,userInfoUrl:Ue}}async function We(de){if(de.type==="apple"){let{teamId:Se,keyId:ke,privateKey:Ce,clientId:Ue}=de.config;if(Se&&ke&&Ce&&Ue)return fr({teamId:Se,keyId:ke,privateKey:Ce,clientId:Ue})}return de.clientSecret}async function Ge(de){fe();let ke=new URL(de.url).searchParams.get("provider");if(!ke)return At({error:"Missing required query parameter: provider"},400);let Ce=ye.providers?.[ke];if(!Ce||Ce.enabled===!1||Ce.type==="magic-link")return At({error:`Unknown or disabled CIAM provider: ${ke}`},404);let Ue=Tn(ke,Ce);if(!Ue?.clientId)return At({error:`CIAM provider ${ke} is not fully configured`},500);let _e=await Et(Ue);if(!_e.authorizationUrl)return At({error:`CIAM provider ${ke} is missing an authorization endpoint`},500);let Le=ye.customerCallbackUrl||"/auth/customer/callback",je=xt(Le,de.url),Ee=Pt(),Ke=Pt(64),be=Pt(),he=Ue.flow==="id_token",ve=he?await kn(Ke):void 0,Ie=await ye.beforeLogin?.({request:de}),Ae=ur({authorizationUrl:_e.authorizationUrl,clientId:Ue.clientId,redirectUri:je,scope:Ue.scope,state:Ee,codeChallenge:ve,nonce:be,extraParams:Ue.extraAuthParams}),Me={provider:ke,state:Ee,codeVerifier:he?Ke:void 0,nonce:be,redirectUri:je,...Ie===void 0?{}:{context:Ie}};return new Response("Redirecting to CIAM provider",{status:302,headers:[["Location",Ae],["Set-Cookie",Pe(rt(Ee),Me,ye.loginStateTtl??600,"Lax")]]})}async function Ne(de){if(de.method==="POST"){if((de.headers.get("content-type")??"").includes(_)){let ke=await de.text();return Object.fromEntries(new URLSearchParams(ke).entries())}}return Object.fromEntries(new URL(de.url).searchParams.entries())}async function Ze(de,Se){let ke=de.mapClaims(Se);if(!ke.sub)return{ok:!1};let Ce=`${de.name}:${ke.sub}`,Ue={id:Ce,userName:ke.userName||ke.email||Ce,name:ke.name||"",email:ke.email||"",avatar:ke.avatar,userType:"customer"},_e=Ce;if(ye.customerStore){let he=await ye.customerStore.lookup(Ue)??await ye.customerStore.get(Ce);if(_e=he?.id??Ce,!he&&!ye.enableJitUserProvisioning)return E.warn("CIAM JIT customer provisioning disabled: unknown customer rejected",{"ion.operation":"customer.store","ion.outcome":"skipped"}),{ok:!1};let ve=new Date,Ie={...he??{},...Ue,id:_e,tenantId:he?.tenantId,createdAt:he?.createdAt??ve,updatedAt:ve,userType:he?.userType??"customer"};await ye.customerStore.upsert(Ie)}let Le=new Date(Date.now()+(ye.sessionTtl??86400)*1000),je=Pt(32),Ee={sub:_e,iss:de.name,aud:de.clientId,exp:Math.floor(Le.getTime()/1000),iat:Math.floor(Date.now()/1000),email:ke.email,name:ke.name,preferred_username:ke.userName??ke.email,picture:ke.avatar,sid:je},Ke={sid:je,sub:_e,authType:"ciam",tenantId:ye.tenantId,expiresAt:Le,claims:Ee,accessClaims:{sub:_e,sid:je,scope:de.scope},createdAt:new Date},be=fe();try{await be.create(Ke)}catch(he){if(!await be.get(je))throw he;await be.update(je,Ke)}return{ok:!0,claims:Ee,sid:je,expires:Le}}async function ze(de){fe();let Se,ke,Ce=(Ue)=>{let _e=Se?[["Set-Cookie",He(Se)]]:[];return ot(de,{ok:!1,error:Ue},ke,_e)};try{let Ue=await Ne(de),_e=await Xe.validate(Ue);if(_e.issues||!_e.value)return Ce(Error("Invalid CIAM callback parameters"));let{code:Le,state:je}=_e.value;if(!je)return Ce(Error("Missing CIAM callback state"));Se=rt(je);let Ee=Oe(Se,de,!0);if(ke=Ee?.context,!Ee?.provider||!Ee.state||Ee.state!==je)return E.warn("CIAM callback state verification failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),Ce(Error("CIAM callback state verification failed"));let Ke=ye.providers?.[Ee.provider];if(!Ke)return Ce(Error("Unknown CIAM provider"));let be=Tn(Ee.provider,Ke);if(!be?.clientId)return Ce(Error("CIAM provider not configured"));let he=await Et(be);if(!he.tokenUrl)return Ce(Error("CIAM provider missing token endpoint"));let ve=await We(be),Ie=await dr({tokenUrl:he.tokenUrl,clientId:be.clientId,clientSecret:ve,redirectUri:Ee.redirectUri||xt(ye.customerCallbackUrl||"/auth/customer/callback",de.url),code:Le,codeVerifier:be.flow==="id_token"?Ee.codeVerifier:void 0,log:E}),Ae;if(be.flow==="id_token"){let qe=be.config.authority;if(!Ie.id_token||!he.jwksUri||!qe)return Ce(Error("CIAM id_token flow misconfigured"));if(!Ee.nonce)return Ce(Error("CIAM callback state cookie missing nonce"));if((await st.validate(Ie)).issues)return E.warn("CIAM token response validation failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),Ce(Error("CIAM token response validation failed"));Ae=await Kt({idToken:Ie.id_token,jwksUri:he.jwksUri,issuer:qe,audience:be.clientId,expectedNonce:Ee.nonce,log:E});let Qe=await et.validate(Ae);if(!Qe.issues)Ae=Qe.value}else{if(!he.userInfoUrl)return Ce(Error("CIAM provider missing userinfo endpoint"));Ae=await mr(he.userInfoUrl,Ie.access_token);let qe=be.config.authority;if(Ie.id_token&&he.jwksUri&&qe){let Ye=await Kt({idToken:Ie.id_token,jwksUri:he.jwksUri,issuer:qe,audience:be.clientId,expectedNonce:Ee.nonce||void 0,log:E}),Qe=typeof Ye.sub==="string"?Ye.sub:"";if(Qe){if(typeof Ae.sub==="string"&&Ae.sub.length>0&&Ae.sub!==Qe)return E.warn("CIAM UserInfo sub does not match verified id_token sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),Ce(Error("CIAM UserInfo sub mismatch"));Ae.sub=Qe}}if(typeof Ae.sub!=="string"||Ae.sub.length===0)return E.warn("CIAM UserInfo response missing sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),Ce(Error("CIAM UserInfo response missing sub"))}let Me=await Ze(be,Ae);if(!Me.ok)return Ce(Error("Failed to persist CIAM customer"));let Ve=qt(Me.claims);E.info("CIAM third-party sign-in succeeded",{"ion.operation":"ciam.oidc.callback","ion.outcome":"success",provider:be.name});let De=[["Set-Cookie",He(Se)],ut(Me.sid,Me.expires),...await wt(de,Ve,Me.expires)];return ot(de,{ok:!0,user:Ve,session:void 0},ke,De)}catch(Ue){return E.error("Error during CIAM third-party sign-in callback",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"},Ue),Ce(Ue)}}async function Be(de){if(!ye)throw Error("ionite CIAM Manager not initialized");$e();let Se=ye.magicLinkUrl||"/magic-link",ke=ye.magicLinkLoginUrl||"/magic-link/login",Ce=ye.logoutUrl||"/auth/customer/logout",Ue=ye.customerLoginUrl||"/auth/customer/login",_e=ye.customerCallbackUrl||"/auth/customer/callback",Le=ye.customerProvidersUrl||"/auth/customer/providers",je=new URL(de.url).pathname,Ee=(Me)=>{if(!Me)return;try{return new URL(Me).pathname}catch{return Me.startsWith("/")?Me:`/${Me}`}};if(Ee(Se)===je&&de.method==="POST")return zt(de);if(Ee(ke)===je&&de.method==="GET")return Rt(de);if(Ee(Ce)===je&&de.method==="GET")return Ot(de);if(Ee(Le)===je&&de.method==="GET")return At({providers:jt()});if(Ee(Ue)===je&&de.method==="GET")return Ge(de);if(Ee(_e)===je&&(de.method==="GET"||de.method==="POST"))return ze(de);return new Response("Not Found",{status:404})}async function we(de){if((ye.userEndpoint??"full")==="off")return new Response("Not Found",{status:404,headers:gt(de)});let Se=await Ft(de);if(Se.status==="degraded")return new Response(JSON.stringify({error:"auth_unavailable"}),{status:503,headers:r});if(Se.status==="unauthenticated")return new Response(JSON.stringify({error:"Unauthorized"}),{status:401,headers:r});let ke=en(Se.value.ciam?.expires),Ce=ye.displayCookie?.enabled===!0?ke&&!Oe("profile",de)?await wt(de,Se.value,ke):[]:gt(de),Ue=ye.userEndpoint==="display"?m(Se.value,ye.displayUser):Se.value;return new Response(JSON.stringify(Ue),{headers:[["Content-Type",s],...Ce]})}return{...ye,getCustomer:nn,resolveCustomer:Ft,logout:Ot,handler:Be,customerHandler:we,listCustomerProviders:jt}}async function Ri(T,E){return t(E,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),E.ciam?.getCustomer(T)}async function En(T,E){return t(E,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),await E.ciam?.resolveCustomer(T)??{status:"unauthenticated"}}var Ai="urn:ietf:params:scim:schemas:core:2.0:User",os="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",Ii="urn:ietf:params:scim:schemas:core:2.0:Group";function hr(T,E,M){let ue=(E==="group"?T.resources:void 0)?.map((pe)=>typeof pe==="string"?pe:pe.id).filter(Boolean);return{schemas:[Ii,e],id:T.id,externalId:T.providerId,displayName:T.displayName??T.name,members:M,[e]:{type:E,requestable:T.requestable,riskLevel:T.riskLevel??f,providerId:T.providerId,requestUrl:T.requestUrl,source:T.source,deprecated:T.deprecated,description:T.description,resources:ue&&ue.length>0?ue:void 0,assignableSubjectTypes:T.assignableSubjectTypes,recommendedSubjectTypes:T.recommendedSubjectTypes,attributes:o(T,d)}}}function Ti(T){if(T.scimName)return T.scimName;if(!T.name)return;let[E,...M]=T.name.split(" ");return{givenName:E,familyName:M.join(" ")||void 0}}function xi(T){let E={attributes:o(T,R)};if(T.ecid!==void 0)E.ecid=T.ecid;if(T.accountClass!==void 0)E.accountClass=T.accountClass;return E.ecid!==void 0||E.accountClass!==void 0||E.attributes!==void 0?E:void 0}function Pi(T){return Object.keys(T.scimSchemaExtensions??{}).filter((E)=>E.startsWith("urn:")&&T.scimSchemaExtensions?.[E]!==void 0)}function kr(T){let E=T.userName||T.email||T.id||"",M=T.emails??(T.email?[{value:T.email,primary:!0}]:[]),J=new Set([Ai]);if(T.scimEnterprise!==void 0)J.add(os);let ue=xi(T);if(ue!==void 0)J.add(u);for(let me of Pi(T))J.add(me);let pe={};if(T.scimEnterprise!==void 0)pe[os]=T.scimEnterprise;if(ue!==void 0)pe[u]=ue;for(let[me,ge]of Object.entries(T.scimSchemaExtensions??{}))if(me.startsWith("urn:")&&me!==u&&ge!==void 0)pe[me]=ge;return{schemas:Array.from(J),id:T.id,externalId:T.externalId,userName:E,displayName:T.displayName??T.name??E,name:Ti(T),nickName:T.nickName,profileUrl:T.avatar,title:T.title,userType:T.userType,preferredLanguage:T.preferredLanguage,locale:T.locale,timezone:T.timezone,active:T.active??!0,emails:M,phoneNumbers:T.phoneNumbers,ims:T.ims,photos:T.photos,addresses:T.addresses,groups:T.groups,entitlements:T.entitlements,roles:T.roles,x509Certificates:T.x509Certificates,meta:{resourceType:"User",created:(T.createdAt??T.updatedAt??new Date).toISOString(),lastModified:(T.updatedAt??T.createdAt??new Date).toISOString()},...pe}}function Sr(T){return{schemas:[b],id:T.id,externalId:T.externalId,userName:T.clientId??T.id,displayName:T.displayName??T.clientId??T.id,description:T.description,active:T.active??!0,ecid:T.ecid,providerId:T.providerId,requestUrl:T.requestUrl,attributes:o(T,I),meta:{resourceType:"Workload",created:(T.createdAt??T.updatedAt??new Date).toISOString(),lastModified:(T.updatedAt??T.createdAt??new Date).toISOString()}}}function wr(T){return{schemas:[C],id:T.id,externalId:T.externalId??T.id,userName:T.userName??T.email??T.id,displayName:T.displayName??T.name??T.userName??T.id,active:T.active??!0,emails:T.emails??(T.email?[{value:T.email,primary:!0}]:void 0),providerId:T.providerId,requestUrl:T.requestUrl,attributes:o(T,A),meta:{resourceType:"Customer",created:(T.createdAt??T.updatedAt??new Date).toISOString(),lastModified:(T.updatedAt??T.createdAt??new Date).toISOString()}}}function Cr(T){return{enabled:T?.enabled!==!1,assignment:T?.assignment??"app",delta:T?.delta}}var Ui="urn:ietf:params:scim:api:messages:2.0:ListResponse",Tr="urn:ietf:params:scim:api:messages:2.0:Error",xr="urn:ietf:params:scim:schemas:core:2.0:User",bn="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",Pr="urn:ietf:params:scim:schemas:core:2.0:Group",Ei="urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig",Mn="urn:ietf:params:scim:schemas:core:2.0:ResourceType",Xt="urn:ietf:params:scim:schemas:core:2.0:Schema",Mi="00000000000000000000000000000000";function Di(T){let E={timestamp:new Date().toISOString()};if(T)E.actor=T;try{let ue=globalThis[Symbol.for("opentelemetry.js.api.1")]?.trace?.getActiveSpan?.()?.spanContext?.(),pe=ue?.traceId;if(pe&&pe!==Mi){if(E.traceId=pe,ue?.spanId)E.spanId=ue.spanId}}catch{}return E}class vn extends Error{constructor(T){super(T);this.name="SubjectTypeNotAssignableError",Object.setPrototypeOf(this,vn.prototype)}}async function ms(T,E,M,J){let ue=M.subjectType;if(!g.includes(ue))throw new vn(`Cannot grant ${M.targetType} "${n(M.target)}" to a "${ue}" principal: only [${g.join(", ")}] principals are assignable on this platform.`);let pe=L(E,T);if(!pe&&!J)return;let me=n(M.target),ge;if(J)ge=await J.getNode(M.targetType,me);else if(pe)ge=await(M.targetType==="group"?pe.groups:M.targetType==="role"?pe.roles:pe.permissions).get(me);if(!ge)return;let ye=ge.assignableSubjectTypes;if(!ye||ye.length===0||!ye.includes(ue))throw new vn(`Cannot grant ${M.targetType} "${me}" to a "${ue}" principal: this entitlement restricts assignment to [${(ye??[]).join(", ")||"none"}].`)}async function Oi(T,E){let M=D(T.codeCatalog,n(E.target));if(!M)return;if(M.kind!==E.targetType)throw Error(`Cannot grant ${E.targetType} "${M.entity.id}": code declares that id as ${M.kind}.`);if(!T.catalogStore)throw Error(`Cannot grant code entitlement "${M.entity.id}": no AccessCatalogStore is wired for materialization.`);await N(M.kind,M.entity,j(T.catalogStore,M.kind))}async function _i(T,E,M,J){await Oi(T,E),await ms(T.catalogStore,T.codeCatalog,E,J);let ue={...E,status:E.status??"active",provenance:E.provenance??Di()};if(ue.id=p(ue),await T.accessStore?.grant(ue),T.accessIndex&&(T.catalogStore||T.codeCatalog)){let pe=await Z(ue,{catalog:T.catalogStore,code:T.codeCatalog,resources:T.resources,cache:J});await T.accessIndex.materialize(ue.id,pe)}return M?.push({op:"add",change:ue}),ue}async function wn(T,E,M){let J=E.id??p(E);await T.accessStore?.revoke(E),await T.accessIndex?.removeByRoot(J),M?.push({op:"delete",change:{...E,id:J}})}async function _n(T,E){let M=await ji(T,E),J=await Ni(T,E);return{oaa:M,delta:J}}async function ji(T,E){if(E.length===0||!T.authz.oaa.isReady())return{status:"skipped"};return Ht(T,"authz.oaa.push","OAA incremental access push failed after SCIM mutation; full sync will reconcile",()=>T.authz.oaa.pushAccessChanges(E),{count:E.length})}async function Ht(T,E,M,J,ue){try{return await J(),{status:"ok"}}catch(pe){return T.log?.warn(M,{"ion.operation":E,"ion.outcome":"degraded",...ue,error:Dt(pe)}),{status:"degraded",reason:Dt(pe)}}}var Li=6;async function Ni(T,E){let M=T.iamDelta;if(!M?.isReady()||E.length===0)return{status:"skipped"};let J=new Map;for(let ye of E){let fe=`${ye.change.subjectType}:${n(ye.change.subject)}\x00${ye.change.targetType}:${n(ye.change.target)}`;J.set(fe,ye)}let ue=[...J.values()],pe=ue.map(({op:ye,change:fe})=>()=>ye==="add"?M.onGrant(fe):M.onRevoke(fe)),ge=(await $i(pe,Li)).filter((ye)=>ye.status==="rejected");if(ge.length>0)return T.log?.warn("IAM delta egress degraded after SCIM mutation; IAM server reconcile/aggregation will recover",{"ion.operation":"iam.delta.egress","ion.outcome":"degraded",failed:ge.length,total:ue.length,error:Dt(ge[0]?.reason)}),{status:"degraded",reason:Dt(ge[0]?.reason)};return{status:"ok"}}async function $i(T,E){let M=Array(T.length),J=0,ue=async()=>{while(!0){let me=J++;if(me>=T.length)return;let ge=T[me];if(!ge)continue;try{M[me]={status:"fulfilled",value:await ge()}}catch(ye){M[me]={status:"rejected",reason:ye}}}},pe=Array.from({length:Math.min(E,T.length)},ue);return await Promise.all(pe),M}class Ln extends Error{constructor(T){super(T);this.name="DerivedRevokeError",Object.setPrototypeOf(this,Ln.prototype)}}class dn extends Error{constructor(T,E,M=!1){super(T);this.name="ScimMutationError",this.summary=E,this.clientError=M,Object.setPrototypeOf(this,dn.prototype)}}function Je(T,E,M){return new Response(JSON.stringify({schemas:[Tr],status:String(T),scimType:M,detail:E}),{status:T,headers:w})}function Wt(T,E){let M=E?.totalResults??T.length,J=E?.startIndex??1,ue=E?.itemsPerPage??T.length;return new Response(JSON.stringify({schemas:[Ui],totalResults:M,startIndex:J,itemsPerPage:ue,Resources:T}),{status:200,headers:w})}function Ct(T,E=200,M){let J=new Headers(w);if(M)J.set("Location",M);return new Response(JSON.stringify(T),{status:E,headers:J})}function as(T){return Je(T.clientError?409:500,`${T.message}; authz mutation summary: ${JSON.stringify(T.summary)}`,T.clientError?"mutability":"invalidValue")}function Cn(T){return p(T)}function br(T,E){return jn(cs(T),cs(E))}function cs(T){let E=new Map;if(!T?.id)return E;for(let M of T.groups??[]){let J={subject:T.id,subjectType:"user",targetType:"group",target:M.value,metadata:M.display||M.type?{display:M.display,type:M.type}:void 0};E.set(Cn(J),J)}for(let M of T.roles??[]){let J={subject:T.id,subjectType:"user",targetType:"role",target:M.value,metadata:M.display||M.type?{display:M.display,type:M.type,primary:M.primary}:void 0};E.set(Cn(J),J)}for(let M of T.entitlements??[]){let J={subject:T.id,subjectType:"user",targetType:"permission",target:M.value,metadata:M.display||M.type?{display:M.display,type:M.type,primary:M.primary}:void 0};E.set(Cn(J),J)}return E}class Nn extends Error{constructor(T){super(T);this.name="AmbiguousMemberSubjectTypeError",Object.setPrototypeOf(this,Nn.prototype)}}function Wi(T,E,M){if(T.type==="Group")return;if(T.type==="Workload")return"workload";if(T.type==="User")return"user";if(T.type==="Customer")return"customer";let J=E??[];if(J.length===1)return J[0];throw new Nn(`SCIM Group member "${T.value}" of entitlement "${M}" omits type, and the entitlement is assignable to more than one principal kind [${J.join(", ")||"none"}]. Set members[].type to User, Workload, or Customer.`)}function Dn(T,E,M,J,ue){let pe=new Map,me=J&&J.length>0?J:void 0;for(let ge of T??[]){let ye=Wi(ge,ue,M);if(!ye)continue;let fe={subject:ge.value,subjectType:ye,targetType:E,target:M,resources:me,metadata:ge.display||ge.type?{display:ge.display,type:ge.type}:void 0};pe.set(Cn(fe),fe)}return pe}function vr(T){let E=T[e]?.resources;return E&&E.length>0?E:void 0}function Vi(T,E){let M=(ue,pe)=>[...ue??[]].sort().join(",")===[...pe??[]].sort().join(","),J=T[e];if(J?.type!==void 0&&J.type!==E.kind)return!0;if(J?.requestable!==void 0&&J.requestable!==E.entity.requestable)return!0;if(J?.resources!==void 0&&!M(J.resources,Ur(E.entity)))return!0;if(J?.assignableSubjectTypes!==void 0&&!M(J.assignableSubjectTypes,E.entity.assignableSubjectTypes))return!0;if(J?.recommendedSubjectTypes!==void 0&&!M(J.recommendedSubjectTypes,E.entity.recommendedSubjectTypes))return!0;return!1}function qi(T,E){let M=(pe,me)=>[...pe??[]].sort().join(",")===[...me??[]].sort().join(","),J=T[e],ue=E[e];if(J?.type!==void 0&&J.type!==ue?.type)return!0;if(J?.requestable!==void 0&&J.requestable!==ue?.requestable)return!0;if(J?.resources!==void 0&&!M(J.resources,ue?.resources))return!0;if(J?.assignableSubjectTypes!==void 0&&!M(J.assignableSubjectTypes,ue?.assignableSubjectTypes))return!0;if(J?.recommendedSubjectTypes!==void 0&&!M(J.recommendedSubjectTypes,ue?.recommendedSubjectTypes))return!0;return!1}function zi(T){let E=new Map;for(let M of T)E.set(Cn(M),M);return E}async function Zt(T,E,M,J,ue,pe){let me=[],ge=new Set,ye=($e,Xe)=>`${Xe}\x00${$e}`,fe=pe?pe.get(`${M}:${J}`)??[]:E?(await E.listByTarget(M,J)).items:[];for(let $e of fe){let Xe=n($e.subject),et=$e.metadata,st=$e.subjectType==="workload"?"Workload":$e.subjectType==="customer"?"Customer":et?.type??"User",it=ye(Xe,st);if(ge.has(it))continue;ge.add(it),me.push({value:Xe,...et?.display?{display:et.display}:{},type:st})}for(let $e of ue??[]){if($e.targetType!==M||n($e.target)!==J)continue;let Xe=n($e.subject),et=ye(Xe,"Workload");if(ge.has(et))continue;ge.add(et),me.push({value:Xe,type:"Workload"})}if(M==="group"){let $e=await T.groups.get(J);for(let Xe of $e?.groups??[]){let et=n(Xe),st=ye(et,"Group");if(!et||ge.has(st))continue;ge.add(st),me.push({value:et,type:"Group"})}}return me.length>0?me:void 0}function jn(T,E){let M=[];for(let[J,ue]of E)if(!T.has(J))M.push({action:"grant",change:ue});for(let[J,ue]of T)if(!E.has(J))M.push({action:"revoke",change:ue});return M}async function Rr(T,E){if(T.oaa.isReady())await T.oaa.pushUser(E)}async function us(T,E,M){if(E?.externalId&&E.externalId!==M.externalId)await T?.onUserDelete(E.externalId);await T?.onUserUpsert(M)}async function cn(T,E,M,J){let ue={metadataApplied:!1,access:[]},pe={status:"skipped"},me=[],ge=new X(T.catalogStore,T.resources,T.codeCatalog);try{try{await E(),ue.metadataApplied=!0}catch(ye){for(let fe of M)ue.access.push({change:fe.change,status:"rolled_back"});throw ue.metadataApplied=!1,new dn(`SCIM metadata write failed: ${Dt(ye)}`,ue,!1)}if(J?.oaa)await Ht(T,"authz.oaa.metadata","OAA metadata projection failed after SCIM write; full sync will reconcile",J.oaa);if(J?.delta&&T.iamDelta?.isReady())pe=await Ht(T,"iam.delta.egress","IAM delta metadata projection failed after SCIM write; full aggregation will reconcile",J.delta);for(let ye=0;ye<M.length;ye++){let fe=M[ye];try{if(fe.action==="grant")await _i(T,fe.change,me,ge);else await Hi(T,fe.change,me);ue.access.push({change:fe.change,status:"applied"})}catch($e){ue.access.push({change:fe.change,status:"failed",error:$e});for(let et=ye+1;et<M.length;et++)ue.access.push({change:M[et].change,status:"rolled_back"});let Xe=$e instanceof Ln||$e instanceof vn;if(!Xe)await Gi(T,fe.change,ge);throw new dn(Xe?Dt($e):`SCIM access mutation failed: ${Dt($e)}`,ue,Xe)}}return ue}finally{await Ki(T),ue.egress=await _n(T,me),ue.egress.delta=Bi(pe,ue.egress.delta),Ji(T,ue)}}function Bi(T,E){if(T.status==="degraded")return T;if(E.status==="degraded")return E;return T.status==="ok"||E.status==="ok"?{status:"ok"}:{status:"skipped"}}function Dt(T){return T instanceof Error?T.message:String(T)}async function Ki(T){try{await T.settleAuthz?.()}catch{}}async function Gi(T,E,M){if(!T.accessIndex||!T.catalogStore&&!T.codeCatalog||!T.accessStore)return;let J=n(E.subject);if(!J)return;let ue=E.subjectType;try{await le(J,ue,{accessStore:T.accessStore,accessIndex:T.accessIndex,catalogStore:T.catalogStore,code:T.codeCatalog,resources:T.resources},M)}catch(pe){T.log?.warn("Per-subject reconcile after failed SCIM access mutation failed",{"ion.operation":"authz.reconcile.subject.repair","ion.outcome":"degraded",subject:J,subjectType:ue,error:Dt(pe)})}}function Ji(T,E){if(!T.onAccessMutation)return;try{T.onAccessMutation(E)}catch{}}async function Hi(T,E,M){if(T.accessStore){let J=E.id??p(E);if(!await T.accessStore.get(J)){if((T.accessIndex?await T.accessIndex.has(E.subject,E.targetType,E.target,E.resources?.[0],E.subjectType):{allow:!1}).allow)throw new Ln(`Cannot revoke ${E.targetType} "${n(E.target)}" for "${n(E.subject)}": it is not a directly granted root (it is derived from group/role membership). Remove the granting group/role instead.`);await wn(T,E,M);return}}await wn(T,E,M)}function un(T){let E=T[e]?.type??"group";if(E==="group"||E==="role"||E==="permission")return E;throw Error(`Unsupported ionite SCIM Group authz type "${String(E)}"`)}async function Ar(T,E,M){if(!T.oaa.isReady())return;if(M==="role"){await T.oaa.pushRole(E);return}if(M==="permission"){await T.oaa.pushPermission(E);return}await T.oaa.pushGroup(E)}function Ur(T){let E=T.resources;if(!E||E.length===0)return;let M=E.map((J)=>typeof J==="string"?J:J.id).filter(Boolean);return M.length>0?M:void 0}function Qt(T,E,M){return hr(T,E,M)}function Fi(T,E){let M=T[e],ue={...o(M?.attributes??{},d),id:E,name:T.displayName,displayName:T.displayName,description:M?.description??T.displayName,requestable:M?.requestable,riskLevel:M?.riskLevel??f,providerId:M?.providerId??T.externalId,requestUrl:M?.requestUrl,assignableSubjectTypes:["user"]};if(M?.resources!==void 0)ue.resources=M.resources;return ue}function Yi(T){if(!T)return;let E=T.trim().match(/^requestable\s+eq\s+(true|false)$/i);if(!E)return;return{requestable:E[1]?.toLowerCase()==="true"}}function ds(T){if(!T)return;let E=T.trim().match(/^externalId\s+eq\s+"([^"]*)"$/i);return E?E[1]:void 0}function Xi(T){if(!T)return;let E=T.trim(),M=E.match(/^userName\s+eq\s+"([^"]*)"$/i);if(M)return{userName:M[1]};let J=E.match(/^externalId\s+eq\s+"([^"]*)"$/i);if(J)return{externalId:J[1]};let ue=E.match(/^meta\.lastModified\s+gt\s+"([^"]*)"$/i);if(ue)return{updatedAfter:ue[1]};return}function Zi(T,E,M){let J=new Set(["id","schemas"]),ue={...T};if(E){let pe=new Set(E.split(",").map((me)=>me.trim()).filter(Boolean));for(let me of Object.keys(ue))if(!J.has(me)&&!pe.has(me))delete ue[me]}if(M){for(let pe of M.split(",").map((me)=>me.trim()).filter(Boolean))if(!J.has(pe))delete ue[pe]}return ue}function ls(T,E){let M=async(pe,me,ge)=>{let ye=await T.toScim(pe),fe=pe.id;return{...ye,id:fe,meta:{...ye.meta??{},resourceType:T.resourceType,location:fe?yt(me,`${ge}/${encodeURIComponent(fe)}`):void 0}}},J=(pe,me)=>{let ge=me.op.toLowerCase();if(!me.path){if(ge!=="remove"&&me.value&&typeof me.value==="object"&&!Array.isArray(me.value))Object.assign(pe,me.value);return}if(ge==="remove"){delete pe[me.path];return}pe[me.path]=me.value};return{handler:async(pe,me)=>{if(!await E.validateAuth(pe))return Je(401,"Authorization required");let ge=new URL(pe.url),ye=me?.basePath??`/${T.resourceType}s`,fe=ge.pathname;if(fe.startsWith(ye))fe=fe.substring(ye.length);let $e=fe.match(/^\/([^/]+)$/),Xe=$e?.[1]?decodeURIComponent($e[1]):void 0,et=ge.searchParams.get("attributes"),st=ge.searchParams.get("excludedAttributes"),it=(Pe)=>Zi(Pe,et,st);try{if(Xe){if(pe.method==="GET"){let Pe=await T.store.get(Xe);if(!Pe)return Je(404,`${T.resourceType} not found`);return Ct(it(await M(Pe,pe,ye)))}if(pe.method==="PUT"||pe.method==="PATCH"){let Pe=await T.store.get(Xe);if(!Pe)return Je(404,`${T.resourceType} not found`);let He=await pe.json(),Oe=He;if(pe.method==="PATCH"){let pt=He.Operations;if(!Array.isArray(pt))return Je(400,"PATCH requires Operations","invalidSyntax");let gt=await T.toScim(Pe);for(let wt of pt)J(gt,wt);Oe=gt}let rt=await Jt(T.validator,Oe);if(rt.issues)return Je(400,rt.issues.map((pt)=>pt.message).join("; "),"invalidValue");let ot=pe.method==="PATCH"?"patch":"replace",ut=await T.store.upsert({...await T.fromScim(rt.value,{existing:Pe,mode:ot}),id:Pe.id??Xe});if(Pe.active!==ut.active)await E.accessIndex?.setSubjectDisabled?.(ut.id,T.subjectType,ut.active===!1);let St=ut.id?yt(pe,`${ye}/${encodeURIComponent(ut.id)}`):void 0;for(let pt of T.projections??[])await Ht(E,`${pt.channel}.${T.subjectType}.upsert`,`${T.resourceType} projection degraded after SCIM upsert; aggregation will reconcile`,()=>pt.upsert(ut,Pe));return Ct(it(await M(ut,pe,ye)),200,St)}if(pe.method==="DELETE"){let Pe=await T.store.get(Xe);if(!Pe)return Je(404,`${T.resourceType} not found`);if(E.revokeSubjectAccess)await E.revokeSubjectAccess(Xe,T.subjectType);await T.store.delete(Xe),await E.accessIndex?.setSubjectDisabled?.(Xe,T.subjectType,!1);for(let He of T.projections??[])await Ht(E,`${He.channel}.${T.subjectType}.delete`,`${T.resourceType} projection degraded after SCIM delete; aggregation will reconcile`,()=>He.delete(Pe));return new Response(null,{status:204})}return Je(405,"Method not allowed")}if(pe.method==="GET"){let Pe=parseInt(ge.searchParams.get("startIndex")??"",10),He=parseInt(ge.searchParams.get("count")??"",10),Oe=Pe!=null&&!Number.isNaN(Pe)?Math.max(0,Pe-1):0,rt=He!=null&&!Number.isNaN(He)?He:void 0,ot=Xi(ge.searchParams.get("filter"));if(ot?.externalId!==void 0){let pt=T.store.getByExternalId?await T.store.getByExternalId(ot.externalId):await T.store.lookup({externalId:ot.externalId}),gt=pt?[it(await M(pt,pe,ye))]:[];return Wt(gt,{totalResults:gt.length,startIndex:1,itemsPerPage:gt.length})}let ut=await T.store.list({start:Oe,limit:rt,filter:ot}),St=await Promise.all(ut.items.map(async(pt)=>it(await M(pt,pe,ye))));return Wt(St,{totalResults:ut.total,startIndex:Oe+1,itemsPerPage:ut.count})}if(pe.method==="POST"){let Pe=await pe.json(),He=await Jt(T.validator,Pe);if(He.issues)return Je(400,He.issues.map((ot)=>ot.message).join("; "),"invalidValue");let Oe=await T.store.upsert(await T.fromScim(He.value,{mode:"create"}));if(Oe.active===!1)await E.accessIndex?.setSubjectDisabled?.(Oe.id,T.subjectType,!0);for(let ot of T.projections??[])await Ht(E,`${ot.channel}.${T.subjectType}.upsert`,`${T.resourceType} projection degraded after SCIM create; aggregation will reconcile`,()=>ot.upsert(Oe,void 0));let rt=Oe.id?yt(pe,`${ye}/${encodeURIComponent(Oe.id)}`):void 0;return Ct(it(await M(Oe,pe,ye)),201,rt)}return Je(405,"Method not allowed")}catch(Pe){if(O(Pe))return Je(409,Pe.message,"uniqueness");return Je(500,Pe instanceof Error?Pe.message:"Internal error")}}}}async function Qi(T,E,M,J){let ue=[],pe=[["group",T.groups],["role",T.roles],["permission",T.permissions]];for(let[ge,ye]of pe)for await(let fe of c(($e,Xe)=>ye.list({start:$e,limit:Xe,filter:{requestable:!0}})))if(fe.providerId===M)ue.push({entity:fe,type:ge});if(ue.length>1)throw new k(`Ambiguous providerId "${M}": ${ue.length} entitlements share it (${ue.map((ge)=>`${ge.type}:${ge.entity.id}`).join(", ")})`,"unique_violation","providerId");let me=ue[0];if(me?.entity.requestable!==!0)return;return Qt(me.entity,me.type,await Zt(T,E,me.type,me.entity.id,J))}async function eo(T,E,M,J){let ue=Math.max(0,M.start),pe=M.limit!=null?ue+M.limit:void 0,me={start:0,limit:pe,filter:M.filter},[ge,ye,fe]=await Promise.all([T.groups.list(me),T.roles.list(me),T.permissions.list(me)]),$e=[...ge.items.map((Pe)=>({entity:Pe,type:"group"})),...ye.items.map((Pe)=>({entity:Pe,type:"role"})),...fe.items.map((Pe)=>({entity:Pe,type:"permission"}))],Xe=ge.total+ye.total+fe.total,et=$e.slice(ue,pe),st=E?.listByTargets?await E.listByTargets(et.map(({entity:Pe,type:He})=>({targetType:He,target:Pe.id}))):void 0,it=await Promise.all(et.map(async({entity:Pe,type:He})=>Qt(Pe,He,await Zt(T,E,He,Pe.id,J,st))));return{resources:it,total:Xe,count:it.length}}async function Sn(T,E,M,J){let[ue,pe,me]=await Promise.all([T.groups.get(M),T.roles.get(M),T.permissions.get(M)]);if(ue)return Qt(ue,"group",await Zt(T,E,"group",M,J));if(pe)return Qt(pe,"role",await Zt(T,E,"role",M,J));if(me)return Qt(me,"permission",await Zt(T,E,"permission",M,J));return}async function Ir(T,E,M,J){let ue=un(E),pe=ue==="role"?await T.roles.get(M):ue==="permission"?await T.permissions.get(M):await T.groups.get(M),me=Fi(E,M),ge=pe?.assignableSubjectTypes&&pe.assignableSubjectTypes.length>0?pe.assignableSubjectTypes:["user"],ye={...pe??{},...me,source:pe?.source??"scim",assignableSubjectTypes:ge},fe=J?J.displayName??J.name:pe?.name;if(me.displayName===fe)delete ye.displayName;if(me.riskLevel===(J?.riskLevel??f))delete ye.riskLevel;let $e=o(me,d),Xe=J?o(J,d):void 0;if(E[e]?.attributes!==void 0){for(let st of Object.keys(o(pe??{},d)??{}))if(!(st in($e??{})))delete ye[st]}for(let[st,it]of Object.entries($e??{}))if(S(it,Xe?.[st]))delete ye[st];if(J)ye.name=J.name;let et=ue==="role"?T.roles.set(ye):ue==="permission"?T.permissions.set(ye):T.groups.set(ye);return await et.ready(),et}async function to(T,E){await Promise.all([T.groups.delete(E),T.roles.delete(E),T.permissions.delete(E)])}function On(){return crypto.randomUUID()}function Jt(T,E){let M=T;if(typeof M.validate==="function")return M.validate(E);return Promise.resolve(T["~standard"].validate(E))}function no(T){if(!T)return;try{return new URL(T).pathname}catch{return T.startsWith("/")?T:`/${T}`}}function Mt(T){let E=no(T);return E?U(E):void 0}function ps(...T){for(let E of T){let M=Mt(E);if(!M)continue;for(let J of["/Users","/Groups","/Workloads","/Customers"])if(M.endsWith(J))return M.slice(0,-J.length)}return}function yt(T,E){return new URL(E,T.url).toString()}function Te(T,E,M,J){let{multiValued:ue=!1,...pe}=J??{};return{name:T,type:E,description:M,multiValued:ue,...pe}}function ro(T,E){return{schemas:[Ei],documentationUri:E?.documentationUri,patch:{supported:!0},bulk:{supported:!1},filter:{supported:!0,maxResults:1000},changePassword:{supported:!1},sort:{supported:!1},etag:{supported:!1},authenticationSchemes:[{type:"oauthbearertoken",name:"OAuth Bearer Token",description:"Use an ionite workload bearer token for IAM discovery and provisioning requests.",primary:!0}],meta:{resourceType:"ServiceProviderConfig",location:yt(T.request,`${T.basePath}/ServiceProviderConfig`)}}}function so(T){let E=[];if(T.supportsUsers)E.push({schemas:[Mn],id:"User",name:"User",description:"User Account",endpoint:T.usersUrl,schema:xr,schemaExtensions:[{schema:bn,required:!1},{schema:u,required:!1}],meta:{resourceType:"ResourceType",location:yt(T.request,`${T.basePath}/ResourceTypes/User`)}});if(T.supportsGroups)E.push({schemas:[Mn],id:"Group",name:"Group",description:"Group",endpoint:T.groupsUrl,schema:Pr,schemaExtensions:[{schema:e,required:!1}],meta:{resourceType:"ResourceType",location:yt(T.request,`${T.basePath}/ResourceTypes/Group`)}});if(T.supportsWorkloads)E.push({schemas:[Mn],id:"Workload",name:"Workload",description:"Workload (machine) principal",endpoint:T.workloadsUrl,schema:b,meta:{resourceType:"ResourceType",location:yt(T.request,`${T.basePath}/ResourceTypes/Workload`)}});if(T.supportsCustomers)E.push({schemas:[Mn],id:"Customer",name:"Customer",description:"Customer (CIAM) principal",endpoint:T.customersUrl,schema:C,meta:{resourceType:"ResourceType",location:yt(T.request,`${T.basePath}/ResourceTypes/Customer`)}});return E}function io(T){let E=[];if(T.supportsUsers)E.push({schemas:[Xt],id:xr,name:"User",description:"User Account",meta:{resourceType:"Schema",location:yt(T.request,`${T.basePath}/Schemas/${encodeURIComponent(xr)}`)},attributes:[Te("id","string","Unique identifier for the User.",{multiValued:!1,required:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),Te("externalId","string","External identifier from the provisioning client.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",uniqueness:"none"}),Te("userName","string","Unique identifier typically used for login.",{multiValued:!1,required:!0,caseExact:!1,mutability:"readWrite",returned:"default",uniqueness:"server"}),Te("name","complex","The components of the user name.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",subAttributes:[Te("formatted","string","The full name, including titles and suffixes.",{multiValued:!1}),Te("familyName","string","The family name of the User.",{multiValued:!1}),Te("givenName","string","The given name of the User.",{multiValued:!1}),Te("middleName","string","The middle name(s) of the User.",{multiValued:!1}),Te("honorificPrefix","string","The honorific prefix(es) of the User.",{multiValued:!1}),Te("honorificSuffix","string","The honorific suffix(es) of the User.",{multiValued:!1})]}),Te("displayName","string","The name of the User, suitable for display.",{multiValued:!1}),Te("nickName","string","The casual way to address the user.",{multiValued:!1}),Te("profileUrl","reference","A URL pointing to the User profile.",{multiValued:!1,referenceTypes:["external"]}),Te("title","string","The user title, such as Vice President.",{multiValued:!1}),Te("userType","string","The relationship between the organization and the User.",{multiValued:!1}),Te("preferredLanguage","string","Preferred written or spoken language.",{multiValued:!1}),Te("locale","string","Default location for localizing values.",{multiValued:!1}),Te("timezone","string","The User time zone.",{multiValued:!1}),Te("active","boolean","The User administrative status.",{multiValued:!1}),Te("emails","complex","Email addresses for the User.",{multiValued:!0,subAttributes:[Te("value","string","Email address value.",{multiValued:!1,required:!0}),Te("display","string","Display label for the email.",{multiValued:!1}),Te("type","string","Email type such as work or home.",{multiValued:!1}),Te("primary","boolean","Primary email indicator.",{multiValued:!1})]}),Te("phoneNumbers","complex","Phone numbers for the User.",{multiValued:!0,subAttributes:[Te("value","string","Phone number value.",{multiValued:!1,required:!0}),Te("display","string","Display label for the phone number.",{multiValued:!1}),Te("type","string","Phone number type.",{multiValued:!1}),Te("primary","boolean","Primary phone number indicator.",{multiValued:!1})]}),Te("photos","complex","Photo URLs for the User.",{multiValued:!0,subAttributes:[Te("value","reference","Photo URL.",{multiValued:!1,required:!0,referenceTypes:["external"]}),Te("display","string","Display label for the photo.",{multiValued:!1}),Te("type","string","Photo type.",{multiValued:!1}),Te("primary","boolean","Primary photo indicator.",{multiValued:!1})]}),Te("addresses","complex","Physical mailing addresses for the User.",{multiValued:!0,subAttributes:[Te("formatted","string","Formatted mailing address.",{multiValued:!1}),Te("streetAddress","string","Full street address component.",{multiValued:!1}),Te("locality","string","City or locality.",{multiValued:!1}),Te("region","string","State or region.",{multiValued:!1}),Te("postalCode","string","Postal code.",{multiValued:!1}),Te("country","string","Country.",{multiValued:!1}),Te("type","string","Address type.",{multiValued:!1}),Te("primary","boolean","Primary address indicator.",{multiValued:!1})]}),Te("groups","complex","Groups to which the User belongs.",{multiValued:!0,mutability:"readOnly",subAttributes:[Te("value","string","Group identifier.",{multiValued:!1,required:!0}),Te("$ref","reference","Reference to the Group resource.",{multiValued:!1,referenceTypes:["Group"]}),Te("display","string","Display name of the group.",{multiValued:!1}),Te("type","string","Relationship type.",{multiValued:!1})]}),Te("entitlements","complex","Entitlements for the User.",{multiValued:!0,subAttributes:[Te("value","string","Entitlement value.",{multiValued:!1,required:!0}),Te("display","string","Display value.",{multiValued:!1}),Te("type","string","Entitlement type.",{multiValued:!1}),Te("primary","boolean","Primary entitlement indicator.",{multiValued:!1})]}),Te("roles","complex","Roles for the User.",{multiValued:!0,subAttributes:[Te("value","string","Role value.",{multiValued:!1,required:!0}),Te("display","string","Display value.",{multiValued:!1}),Te("type","string","Role type.",{multiValued:!1}),Te("primary","boolean","Primary role indicator.",{multiValued:!1})]}),Te("x509Certificates","complex","Certificates issued to the User.",{multiValued:!0,subAttributes:[Te("value","string","Certificate value.",{multiValued:!1,required:!0}),Te("display","string","Display value.",{multiValued:!1}),Te("type","string","Certificate type.",{multiValued:!1}),Te("primary","boolean","Primary certificate indicator.",{multiValued:!1})]})]}),E.push({schemas:[Xt],id:bn,name:"EnterpriseUser",description:"Enterprise User extension",meta:{resourceType:"Schema",location:yt(T.request,`${T.basePath}/Schemas/${encodeURIComponent(bn)}`)},attributes:[Te("employeeNumber","string","Numeric or alphanumeric identifier assigned to a person.",{multiValued:!1}),Te("costCenter","string","Name of a cost center.",{multiValued:!1}),Te("organization","string","Name of an organization.",{multiValued:!1}),Te("division","string","Name of a division.",{multiValued:!1}),Te("department","string","Name of a department.",{multiValued:!1}),Te("manager","complex","The User manager.",{multiValued:!1,subAttributes:[Te("value","string","Identifier of the manager User resource.",{multiValued:!1}),Te("$ref","reference","Reference to the manager User resource.",{multiValued:!1,referenceTypes:["User"]}),Te("displayName","string","Display name of the manager.",{multiValued:!1})]})]}),E.push({schemas:[Xt],id:u,name:"IoniteUser",description:"ionite User extension carrying ECID, account purpose, and AppDev custom attributes. See https://ionite.com/docs/llms-ecid.txt.",meta:{resourceType:"Schema",location:yt(T.request,`${T.basePath}/Schemas/${encodeURIComponent(u)}`)},attributes:[Te("ecid","string","Enterprise Controlled ID formatted as 'ecid:<realm>:<opaque>' (realm = the minting authority's id). Correlates multiple accounts to one identity.",{multiValued:!1,caseExact:!0}),Te("accountClass","string","Account purpose (distinct from userType persona). Open value set: 'daily', 'privileged', 'break_glass', 'service'.",{multiValued:!1}),Te("attributes","complex","AppDev custom attributes. IAM may override seeded values.",{multiValued:!1,required:!1,mutability:"readWrite"})]});if(T.supportsGroups)E.push({schemas:[Xt],id:e,name:"IoniteAuthzGroup",description:"ionite authorization metadata for SCIM Group resources.",meta:{resourceType:"Schema",location:yt(T.request,`${T.basePath}/Schemas/${encodeURIComponent(e)}`)},attributes:[Te("type","string","Authorization entity kind: group, role, or permission.",{multiValued:!1,required:!1}),Te("requestable","boolean","Whether this catalog entry is exposed as assignable access to IAM tooling. Only true entries are served.",{multiValued:!1,required:!1}),Te("riskLevel","string",`Advisory access-risk classification. Unset values project as ${f}; canonical values are suggestions, not a closed enum.`,{multiValued:!1,required:!1,mutability:"readWrite",canonicalValues:[...H]}),Te("providerId","string","IAM service-provider id captured when this entitlement is materialized at the destination.",{multiValued:!1,required:!1,mutability:"readWrite"}),Te("requestUrl","reference","IAM-owned deep link where a principal can request this entitlement.",{multiValued:!1,required:!1,mutability:"readWrite",referenceTypes:["external"]}),Te("source","string","Provenance of the catalog row.",{multiValued:!1,required:!1,mutability:"readOnly",canonicalValues:["code","app","scim"]}),Te("deprecated","boolean","Whether this retired entitlement may be deleted.",{multiValued:!1,required:!1,mutability:"readOnly"}),Te("description","string","Human-readable authorization entity description.",{multiValued:!1,required:!1}),Te("resources","string","Resource ids this entitlement is scoped to.",{multiValued:!0,required:!1}),Te("assignableSubjectTypes","string","AppDev-owned required audience of principal kinds (user, workload, customer) that may hold this entitlement. Read-only to IAM tooling.",{multiValued:!0,required:!1,mutability:"readOnly",canonicalValues:["user","customer","workload"]}),Te("recommendedSubjectTypes","string","AppDev advisory default principal kinds (subset of assignableSubjectTypes). Read-only to IAM tooling.",{multiValued:!0,required:!1,mutability:"readOnly",canonicalValues:["user","customer","workload"]}),Te("attributes","complex","AppDev custom attributes. IAM may override seeded values.",{multiValued:!1,required:!1,mutability:"readWrite"})]});if(T.supportsGroups)E.push({schemas:[Xt],id:Pr,name:"Group",description:"Group",meta:{resourceType:"Schema",location:yt(T.request,`${T.basePath}/Schemas/${encodeURIComponent(Pr)}`)},attributes:[Te("id","string","Unique identifier for the Group.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),Te("externalId","string","External identifier from the provisioning client.",{multiValued:!1,uniqueness:"none"}),Te("displayName","string","Human-readable name for the Group.",{multiValued:!1,required:!0,uniqueness:"none"}),Te("members","complex","Members of the Group.",{multiValued:!0,subAttributes:[Te("value","string","Identifier of the member resource.",{multiValued:!1,required:!0}),Te("$ref","reference","Reference to the member resource.",{multiValued:!1,referenceTypes:["User","Group","Workload","Customer"]}),Te("display","string","Display name of the member.",{multiValued:!1}),Te("type","string","Member type.",{multiValued:!1})]})]});if(T.supportsWorkloads)E.push({schemas:[Xt],id:b,name:"Workload",description:"Workload (machine) principal",meta:{resourceType:"Schema",location:yt(T.request,`${T.basePath}/Schemas/${encodeURIComponent(b)}`)},attributes:[Te("id","string","Unique identifier for the Workload.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),Te("externalId","string","External identifier from the provisioning client.",{multiValued:!1}),Te("userName","string","Login identifier, typically the OAuth clientId.",{multiValued:!1}),Te("displayName","string","Human-readable name for the Workload.",{multiValued:!1}),Te("description","string","Free-form description of the Workload.",{multiValued:!1}),Te("active","boolean","Administrative status of the Workload.",{multiValued:!1}),Te("attributes","complex","AppDev custom attributes.",{multiValued:!1,required:!1,mutability:"readWrite"})]});if(T.supportsCustomers)E.push({schemas:[Xt],id:C,name:"Customer",description:"Customer (CIAM) principal",meta:{resourceType:"Schema",location:yt(T.request,`${T.basePath}/Schemas/${encodeURIComponent(C)}`)},attributes:[Te("id","string","Unique identifier for the Customer.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),Te("externalId","string","External identifier from the provisioning client.",{multiValued:!1}),Te("userName","string","Unique identifier typically used for login.",{multiValued:!1}),Te("displayName","string","Human-readable name for the Customer.",{multiValued:!1}),Te("active","boolean","Administrative status of the Customer.",{multiValued:!1}),Te("emails","complex","Email addresses for the Customer.",{multiValued:!0,subAttributes:[Te("value","string","Email address.",{multiValued:!1,required:!0}),Te("primary","boolean","Whether this is the primary email.",{multiValued:!1})]}),Te("attributes","complex","AppDev custom attributes.",{multiValued:!1,required:!1,mutability:"readWrite"})]});return E}function oo(T,E,M,J,ue,pe,me,ge,ye,fe,$e,Xe,et,st,it){let Pe={authz:J,settleAuthz:it,accessStore:ue,accessIndex:pe,catalogStore:me,codeCatalog:ge,resources:ye,log:E,iamDelta:Xe,onAccessMutation:et};if(!fe&&!$e)return;let Oe={...fe,...$e},rt=Oe.users?.enabled!==!1,ot=Oe.groups?.enabled!==!1,ut=Oe.workloads?.enabled!==!1,St=Oe.customers?.enabled!==!1;if(Boolean(Oe.url||Oe.userStore||me||ge)&&!M)E.error("IAM requires workload identity for SCIM push/pull operations",{"ion.operation":"workload.require","ion.outcome":"failure"});function gt(){if(!M)throw E.error("IAM requires workload identity for SCIM push/pull operations",{"ion.operation":"workload.require","ion.outcome":"failure"}),Error("IAM requires workload identity for SCIM push/pull operations");return M}async function wt(We){let Ge=gt(),Ne=We.headers.get("Authorization");if(!Ne?.startsWith("Bearer "))return!1;try{let Ze=Ne.substring(7);return(await Ge.validateToken(Ze)).valid}catch{return!1}}async function en(){let We=gt(),Ge=typeof We.getServerToken==="function"?await We.getServerToken():await We.getToken();return new Headers({...w,...oe,Authorization:`Bearer ${Ge}`})}async function tn(We,Ge,Ne,Ze){if(!Oe.url)throw Error("IAM URL not configured for outgoing requests");let ze=`${Oe.url}${Ge}`;try{let Be=await en(),we=await fetch(ze,{method:We,headers:Be,body:Ne?JSON.stringify(Ne):void 0}),de=await a(we,{log:E,operation:"scim.request"});if(!we.ok)return{success:!1,error:de,status:we.status};let Se=await Ze["~standard"].validate(de);if(Se.issues)return E.error("SCIM response validation failed",{"ion.operation":"scim.response.validate","ion.outcome":"failure",validationIssues:Se.issues}),{success:!1,error:{schemas:[Tr],status:"400",scimType:"invalidValue",detail:`Response validation failed: ${Se.issues.map((ke)=>ke.message).join("; ")}`},status:400};return{success:!0,data:Se.value,status:we.status}}catch(Be){return{success:!1,error:{schemas:[Tr],status:"500",detail:Be instanceof Error?Be.message:"Unknown error occurred"},status:500}}}function Ft(){return Oe.url}function ln(We,Ge){let Ne=Mt(Ge?.usersUrl??Oe.usersUrl??"/api/iam/Users")??"/api/iam/Users",Ze=Mt(Ge?.groupsUrl??Oe.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",ze=Mt(Ge?.workloadsUrl??Oe.workloadsUrl??"/api/iam/Workloads")??"/api/iam/Workloads",Be=Mt(Ge?.customersUrl??Oe.customersUrl??"/api/iam/Customers")??"/api/iam/Customers",we=Mt(Ge?.discovery?.basePath??Oe.discovery?.basePath)??ps(Ne,Ze,ze,Be);if(!we)return;return{request:We,basePath:we,usersUrl:Ne,groupsUrl:Ze,workloadsUrl:ze,customersUrl:Be,supportsUsers:rt&&Boolean(Oe.userStore),supportsGroups:ot&&Boolean(me||ge),supportsWorkloads:ut&&Boolean(Oe.workloadIdentityStore),supportsCustomers:St&&Boolean(Oe.customerStore)}}async function nn(We){let Ge=ro(We,Oe.discovery);return await Oe.discovery?.buildServiceProviderConfig?.(We,Ge)??Ge}async function Ot(We){let Ge=so(We);return await Oe.discovery?.buildResourceTypes?.(We,Ge)??Ge}async function Vt(We){let Ge=io(We);return await Oe.discovery?.buildSchemas?.(We,Ge)??Ge}async function _t(We,Ge){let Ne=ln(We,Ge);if(!Ne)return;let Ze=U(new URL(We.url).pathname),{basePath:ze}=Ne;if(Ze!==ze&&!Ze.startsWith(`${ze}/`))return;let Be=U(Ze.slice(ze.length)||"/");if(!(Be==="/ServiceProviderConfig"||Be==="/ResourceTypes"||Be.startsWith("/ResourceTypes/")||Be==="/Schemas"||Be.startsWith("/Schemas/")))return;if(We.method!=="GET")return Je(405,"Method not allowed");if(!await wt(We))return Je(401,"Authorization required");if(Be==="/ServiceProviderConfig")return Ct(await nn(Ne));if(Be==="/ResourceTypes")return Wt(await Ot(Ne));if(Be.startsWith("/ResourceTypes/")){let Se=decodeURIComponent(Be.slice(15)),ke=(await Ot(Ne)).find((Ce)=>Ce.id===Se||Ce.name===Se);return ke?Ct(ke):Je(404,"Resource not found")}if(Be==="/Schemas")return Wt(await Vt(Ne));if(Be.startsWith("/Schemas/")){let Se=decodeURIComponent(Be.slice(9)),ke=(await Vt(Ne)).find((Ce)=>Ce.id===Se);return ke?Ct(ke):Je(404,"Resource not found")}return}let rn,qt;if(Oe.url)qt=async(Ge,Ne)=>{let Ze={...Ge,schemas:Ge.schemas??["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"]};return tn("POST","/Users",Ze,T.user)},rn={createGroup:async(Ge,Ne)=>{let Ze={schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],displayName:Ge,externalId:Ne?.id,members:Ne?.members};return tn("POST","/Groups",Ze,T.group)}};let zt;if(me||ge){let We=L(ge,me),Ge=(be,he,ve)=>{let Ie=be[e]??{},Ae=un(be),Me=be.id,Ve=Me?yt(he,`${ve}/${encodeURIComponent(Me)}`):void 0,De={id:Me??be.externalId??be.displayName,name:be.displayName,displayName:be.displayName,description:Ie.description??be.displayName,requestable:Ie.requestable,providerId:Ie.providerId??be.externalId,requestUrl:Ie.requestUrl,source:Ie.source,deprecated:Ie.deprecated,riskLevel:Ie.riskLevel,assignableSubjectTypes:Ie.assignableSubjectTypes,recommendedSubjectTypes:Ie.recommendedSubjectTypes},qe=Ie.requestUrl??Oe.entitlementRequestUrl?.(De,Ae,{request:he});return{...be,meta:{...be.meta,resourceType:"Group",location:Ve},[e]:{...Ie,requestUrl:qe}}},Ne=(be)=>D(ge,be),Ze=async(be,he)=>{if(!me){if(he)throw Error(`Cannot persist access for code entitlement "${be.entity.id}": no AccessCatalogStore is wired.`);return be.entity}try{return await N(be.kind,be.entity,j(me,be.kind))}catch(ve){if(he)throw ve;return E.warn("Code entitlement discovery materialization failed; serving the code template",{"ion.operation":"iam.catalog.materialize","ion.outcome":"degraded",entitlementId:be.entity.id,entitlementType:be.kind,error:Dt(ve)}),be.entity}},ze=async(be)=>{if(!me)return;try{await Y(ge,me,be)}catch(he){E.warn("Retired code entitlement deprecation failed; serving the last durable row",{"ion.operation":"iam.catalog.deprecate","ion.outcome":"degraded",entitlementId:be,error:Dt(he)})}},Be=(be,he)=>Je(403,`Entitlement "${be}" is declared in application code; its structural definition cannot be ${he} through SCIM. IAM may change presentation and receipts, while code continues to own structure.`,"mutability"),we=(be)=>be.path==="members"||Boolean(be.path?.startsWith("members[")),de=(be)=>we(be)||be.path==="displayName"||be.path===`${e}.description`||be.path===`${e}.riskLevel`||be.path===`${e}.providerId`||be.path===`${e}.requestUrl`||be.path===`${e}.attributes`||Boolean(be.path?.startsWith(`${e}.attributes.`)),Se=(be)=>be?.[e]?.requestable===!0,ke=(be)=>Je(404,`Requestable Group ${be} not found`,"invalidValue"),Ce=async(be,he)=>{if(!await wt(be))return Je(401,"Authorization required");let Ie=new URL(be.url),Ae=he?.basePath??"/Groups",Me=Ie.pathname;if(Me.startsWith(Ae))Me=Me.substring(Ae.length);let De=Me.match(/^\/([^/]+)$/)?.[1],qe=be.method;try{if(De)switch(qe){case"GET":return await _e(be,Ae,De);case"PUT":return await je(be,Ae,De);case"PATCH":return await Ee(be,Ae,De);case"DELETE":return await Ke(De);default:return Je(405,"Method not allowed")}else if(Me===""||Me==="/")switch(qe){case"GET":return await Ue(be,Ae);case"POST":return await Le(be,Ae);default:return Je(405,"Method not allowed")}return Je(404,"Resource not found")}catch(Ye){if(Ye instanceof dn)return as(Ye);if(Ye instanceof Nn)return Je(400,Ye.message,"invalidValue");if(O(Ye))return Je(409,Ye.message,"uniqueness");return E.error("Groups inbound handler error",{"ion.operation":"scim.groups.handler","ion.outcome":"failure"},Ye),Je(500,Ye instanceof Error?Ye.message:"Internal server error")}},Ue=async(be,he)=>{let ve=new URL(be.url),Ie=ve.searchParams.get("startIndex"),Ae=ve.searchParams.get("count"),Me=Ie!=null?parseInt(Ie,10):void 0,Ve=Ae!=null?parseInt(Ae,10):void 0,De=Me!=null&&!Number.isNaN(Me)?Math.max(0,Me-1):0,qe=Ve!=null&&!Number.isNaN(Ve)?Ve:void 0,Ye=ve.searchParams.get("filter"),Qe=ds(Ye);if(Qe!==void 0){await ze();let nt=await Qi(We,ue,Qe,st),bt=nt?[Ge(nt,be,he)]:[];return Wt(bt,{totalResults:bt.length,startIndex:1,itemsPerPage:bt.length})}if(Yi(Ye)?.requestable===!1)return Wt([],{totalResults:0,startIndex:1,itemsPerPage:0});let ct={requestable:!0};if(ge)await Promise.all([...ge.groups.list().filter((nt)=>nt.requestable===!0).map((nt)=>({entity:nt,kind:"group"})),...ge.roles.list().filter((nt)=>nt.requestable===!0).map((nt)=>({entity:nt,kind:"role"})),...ge.permissions.list().filter((nt)=>nt.requestable===!0).map((nt)=>({entity:nt,kind:"permission"}))].map((nt)=>Ze(nt,!1)));await ze();let at=await eo(We,ue,{start:De,limit:qe,filter:ct},st);return Wt(at.resources.map((nt)=>Ge(nt,be,he)),{totalResults:at.total,startIndex:De+1,itemsPerPage:at.count})},_e=async(be,he,ve)=>{let Ie=Ne(ve);if(Ie&&Ie.entity.requestable!==!0)return ke(ve);if(Ie)await Ze(Ie,!1);await ze(ve);let Ae=await Sn(We,ue,ve,st);if(!Se(Ae))return ke(ve);return Ct(Ge(Ae,be,he))},Le=async(be,he)=>{let ve=await be.json(),Ie=await Jt(T.group,ve);if(Ie.issues)return E.error("Group creation validation failed",{"ion.operation":"scim.group.create","ion.outcome":"failure",validationIssues:Ie.issues}),Je(400,`Request validation failed: ${Ie.issues.map((at)=>at.message).join("; ")}`,"invalidValue");let Ae=Ie.value;if(!Ae.displayName)return Je(400,"displayName is required","invalidValue");if(Ae[e]?.requestable===!1)return Je(400,"SCIM may create only requestable entitlements; non-requestable definitions are App-owned.","invalidValue");if(Ae[e]={...Ae[e],requestable:!0},!me)return Je(501,"Group creation is not supported: this application declares its catalog in code (authz.catalog) and wires no AccessCatalogStore for SCIM-authored definitions.","invalidValue");let Ve=un(Ae),De=On();if(Ne(De))throw new k(`id "${De}" is reserved by the code catalog`,"unique_violation","id");let qe=vr(Ae),Ye=jn(new Map,Dn(Ae.members,Ve,De,qe,Ae[e]?.assignableSubjectTypes)),Qe;await cn(Pe,async()=>{Qe=await Ir(We,Ae,De)},Ye,{oaa:()=>Ar(J,Qe,Ve)});let dt=await Zt(We,ue,Ve,De),ct=Ge(Qt(Qe,Ve,dt),be,he);return Ct(ct,201,ct.meta?.location)},je=async(be,he,ve)=>{let Ie=await be.json(),Ae=await Jt(T.group,Ie);if(Ae.issues)return E.error("Group replacement validation failed",{"ion.operation":"scim.group.replace","ion.outcome":"failure",validationIssues:Ae.issues}),Je(400,`Request validation failed: ${Ae.issues.map((bt)=>bt.message).join("; ")}`,"invalidValue");let Me=Ae.value,Ve=un(Me),De=Ne(ve);if(De&&De.entity.requestable!==!0)return ke(ve);if(De){if(await Ze(De,!0),Vi(Me,De))return Be(ve,"replaced")}let qe=await Sn(We,ue,ve);if(!Se(qe))return ke(ve);if(!De&&qe[e]?.source==="code"&&qi(Me,qe))return Be(ve,"replaced");let Ye=De?.kind??Ve,Qe=De?Ur(De.entity):vr(Me),dt=ue?(await ue.listByTarget(Ye,ve)).items:[],ct=jn(zi(dt),Dn(Me.members,Ye,ve,Qe,De?.entity.assignableSubjectTypes??qe[e]?.assignableSubjectTypes??Me[e]?.assignableSubjectTypes)),at;await cn(Pe,async()=>{at=await Ir(We,Me,ve,De?.entity)},ct,{oaa:()=>Ar(J,at,Ye)});let nt=await Zt(We,ue,Ye,ve);return Ct(Ge(Qt(at,Ye,nt),be,he))},Ee=async(be,he,ve)=>{let Ie=Ne(ve);if(Ie&&Ie.entity.requestable!==!0)return ke(ve);if(Ie)await Ze(Ie,!0);let Ae=await Sn(We,ue,ve);if(!Se(Ae))return ke(ve);let Me=await be.json();if((Ie!==void 0||Ae[e]?.source==="code")&&(Me.Operations??[]).some((tt)=>!de(tt)))return Be(ve,"patched");let De={...Ae};for(let tt of Me.Operations??[])if(tt.op==="replace"&&tt.path&&tt.value!==void 0){if(tt.path==="displayName")De.displayName=tt.value;else if(tt.path===`${e}.requestable`)De[e]={...De[e],requestable:Boolean(tt.value)};else if(tt.path===`${e}.description`)De[e]={...De[e],description:String(tt.value)};else if(tt.path===`${e}.riskLevel`)De[e]={...De[e],riskLevel:String(tt.value)};else if(tt.path===`${e}.providerId`)De[e]={...De[e],providerId:String(tt.value)};else if(tt.path===`${e}.requestUrl`)De[e]={...De[e],requestUrl:String(tt.value)};else if(tt.path===`${e}.attributes`&&typeof tt.value==="object"&&tt.value!==null&&!Array.isArray(tt.value))De[e]={...De[e],attributes:tt.value};else if(tt.path.startsWith(`${e}.attributes.`)){let It=tt.path.slice(`${e}.attributes.`.length);De[e]={...De[e],attributes:{...De[e]?.attributes,[It]:tt.value}}}}else if(tt.op==="add"&&tt.path==="members"&&tt.value!==void 0){let It=tt.value;De.members=[...De.members??[],...It]}else if(tt.op==="remove"&&tt.path?.startsWith("members[")){let It=tt.path.match(/members\[value eq "([^"]+)"\]/);if(It)De.members=(De.members??[]).filter((mt)=>mt.value!==It[1])}else if(tt.op==="remove"&&tt.path?.startsWith(`${e}.attributes.`)){let It=tt.path.slice(`${e}.attributes.`.length),mt={...De[e]?.attributes};delete mt[It],De[e]={...De[e],attributes:mt}}let qe=await Jt(T.group,De);if(qe.issues)return E.error("Group patch validation failed",{"ion.operation":"scim.group.patch","ion.outcome":"failure",validationIssues:qe.issues}),Je(400,`Request validation failed: ${qe.issues.map((tt)=>tt.message).join("; ")}`,"invalidValue");let Ye=Ie?.kind??un(De),Qe=Ie?Ur(Ie.entity):vr(De),dt=Ie?.entity.assignableSubjectTypes??Ae[e]?.assignableSubjectTypes??De[e]?.assignableSubjectTypes,ct=jn(Dn(Ae.members,Ye,ve,Qe,dt),Dn(De.members,Ye,ve,Qe,dt)),at,nt=!Ie||(Me.Operations??[]).some((tt)=>!we(tt));await cn(Pe,async()=>{if(nt)at=await Ir(We,De,ve,Ie?.entity)},ct,nt?{oaa:()=>Ar(J,at,Ye)}:void 0);let bt=await Sn(We,ue,ve);return Ct(Ge(bt,be,he))},Ke=async(be)=>{let he=Ne(be);if(he&&he.entity.requestable!==!0)return ke(be);if(he)await Ze(he,!0);let ve=await Sn(We,ue,be);if(!Se(ve))return ke(be);let Ie=ve[e];if((he||Ie?.source==="code")&&Ie?.deprecated!==!0)return Je(403,`Code-owned entitlement "${be}" can be deleted only after it is marked deprecated.`,"mutability");let Ae=un(ve);if(ue){let Me=await ue.listByTarget(Ae,be),Ve=[];for(let De of Me.items)await wn(Pe,De,Ve);await _n(Pe,Ve)}return await to(We,be),new Response(null,{status:204})};zt={handler:Ce}}let Rt,At,xt;if(Oe.userStore){let{userStore:We,inboundUsers:Ge}=Oe,Ne=(he)=>he?.find((ve)=>ve.primary)?.value||he?.[0]?.value,Ze=async(he)=>{if(Ge?.mapBaseUserToScim)return await Ge.mapBaseUserToScim(he);return kr(he)},ze=async(he,ve,Ie)=>{let Ae=await Ze(he),Me=Ae.id??he.id;return{...Ae,id:Me,meta:{...Ae.meta,resourceType:"User",location:Me?yt(ve,`${Ie}/${encodeURIComponent(Me)}`):void 0}}},Be=async(he,ve)=>{if(Ge?.mapValidatedScimToBaseUser)return await Ge.mapValidatedScimToBaseUser(he,ve);let Ie=new Date,Ae=Ne(he.emails),Me=he.name?.formatted||[he.name?.givenName,he.name?.middleName,he.name?.familyName].filter(Boolean).join(" ").trim()||he.displayName,Ve=he.id||ve.existing?.id||On(),De=he.userName||Ae||ve.existing?.userName||Ve,qe=Me||he.displayName||ve.existing?.name||De,Ye=Object.fromEntries(Object.entries(he).filter(([bt,tt])=>bt.startsWith("urn:")&&bt!==bn&&bt!==u&&tt!==void 0)),Qe=he[u],dt=o(Qe?.attributes??{},R),ct=Qe?.ecid!==void 0&&Qe.ecid!==null?P(Qe.ecid):ve.existing?.ecid,at=Qe?.accountClass??ve.existing?.accountClass,nt=ve.existing?.sso;return{...ve.existing??{},id:Ve,userName:De,name:qe,email:Ae||ve.existing?.email||De,avatar:he.profileUrl,sso:{...nt??{},profile:{...nt?.profile??{},sub:Ve,iss:nt?.profile.iss??"iam-provisioned",aud:nt?.profile.aud??"iam-provisioned",exp:nt?.profile.exp??Math.floor(Date.now()/1000)+3600,iat:nt?.profile.iat??Math.floor(Date.now()/1000),email:Ae||ve.existing?.email||De,email_verified:!0,name:qe,preferred_username:De},tenant:nt?.tenant??{id:"iam-provisioned",name:"IAM Provisioned"},scope:nt?.scope??"openid profile email",tokenType:nt?.tokenType??"Bearer",expires:nt?.expires??new Date(Date.now()+3600000)},externalId:he.externalId,ecid:ct,accountClass:at,displayName:he.displayName,scimName:he.name,emails:he.emails,nickName:he.nickName,title:he.title,preferredLanguage:he.preferredLanguage,locale:he.locale,timezone:he.timezone,active:he.active,phoneNumbers:he.phoneNumbers,ims:he.ims,photos:he.photos,addresses:he.addresses,groups:he.groups,entitlements:he.entitlements,roles:he.roles,x509Certificates:he.x509Certificates,scimEnterprise:he[bn],scimSchemaExtensions:Object.keys(Ye).length>0?Ye:void 0,createdAt:ve.existing?.createdAt??(he.meta?.created?new Date(he.meta.created):Ie),updatedAt:he.meta?.lastModified?new Date(he.meta.lastModified):Ie,userType:he.userType,...dt}},we=(he,ve,Ie)=>{he[ve]=Ie},de=(he,ve,Ie)=>{let Ae=he[ve];if(Array.isArray(Ae)){he[ve]=[...Ae,...Array.isArray(Ie)?Ie:[Ie]];return}if(Ae&&typeof Ae==="object"&&!Array.isArray(Ae)&&Ie&&typeof Ie==="object"&&!Array.isArray(Ie)){he[ve]={...Ae,...Ie};return}he[ve]=Ie},Se=(he,ve,Ie)=>{let Ae=ve.match(/^(urn:.*:(?:User|Group))(?::(.+))?$/),Me=Ae?[Ae[1],...Ae[2]?.split(":")??[]]:ve.split("."),Ve=he;for(let qe of Me.slice(0,-1)){let Ye=Ve[qe];if(Ye===void 0){if(!Ie)return null;Ve[qe]={}}else if(Ye===null||typeof Ye!=="object"||Array.isArray(Ye)){if(!Ie)return null;Ve[qe]={}}Ve=Ve[qe]}let De=Me.at(-1);if(!De)return null;return{parent:Ve,key:De}},ke=(he,ve)=>{let Ie=ve.op.toLowerCase();if(!ve.path){if(Ie!=="remove"&&ve.value&&typeof ve.value==="object"&&!Array.isArray(ve.value))Object.assign(he,ve.value);return}let Ae=ve.path.match(/^([A-Za-z0-9]+)\[value eq "([^"]+)"\]$/);if(Ae&&Ie==="remove"){let[,Ve,De]=Ae,qe=he[Ve];if(Array.isArray(qe))he[Ve]=qe.filter((Ye)=>!(Ye&&typeof Ye==="object"&&("value"in Ye)&&Ye.value===De));return}let Me=Se(he,ve.path,Ie!=="remove");if(!Me)return;if(Ie==="remove"){delete Me.parent[Me.key];return}if(Ie==="add"){de(Me.parent,Me.key,ve.value);return}we(Me.parent,Me.key,ve.value)},Ce=async(he,ve)=>{if(!await wt(he))return Je(401,"Authorization required");let Ae=new URL(he.url),Me=ve?.basePath??"/Users",Ve=Ae.pathname;if(Ve.startsWith(Me))Ve=Ve.substring(Me.length);let qe=Ve.match(/^\/([^/]+)$/)?.[1],Ye=he.method;try{if(qe)switch(Ye){case"GET":return await _e(he,Me,qe);case"PUT":return await Ee(he,Me,qe);case"PATCH":return await Ke(he,Me,qe);case"DELETE":return await be(qe);default:return Je(405,"Method not allowed")}else if(Ve===""||Ve==="/")switch(Ye){case"GET":return await Ue(he,Me);case"POST":return await je(he,Me);default:return Je(405,"Method not allowed")}return Je(404,"Resource not found")}catch(Qe){if(Qe instanceof dn)return as(Qe);if(O(Qe))return Je(409,Qe.message,"uniqueness");return E.error("Users inbound handler error",{"ion.operation":"scim.users.handler","ion.outcome":"failure"},Qe),Je(500,Qe instanceof Error?Qe.message:"Internal server error")}},Ue=async(he,ve)=>{let Ie=new URL(he.url),Ae=Ie.searchParams.get("startIndex"),Me=Ie.searchParams.get("count"),Ve=Ae!=null?parseInt(Ae,10):void 0,De=Me!=null?parseInt(Me,10):void 0,qe=Ve!=null&&!Number.isNaN(Ve)?Math.max(0,Ve-1):0,Ye=De!=null&&!Number.isNaN(De)?De:void 0,Qe=ds(Ie.searchParams.get("filter"));if(Qe!==void 0){let at=await We.lookup({externalId:Qe}),nt=at?[await ze(at,he,ve)]:[];return Wt(nt,{totalResults:nt.length,startIndex:1,itemsPerPage:nt.length})}let dt=await We.list({start:qe,limit:Ye}),ct=await Promise.all(dt.items.map((at)=>ze(at,he,ve)));return Wt(ct,{totalResults:dt.total,startIndex:qe+1,itemsPerPage:dt.count})},_e=async(he,ve,Ie)=>{let Ae=await We.get(Ie);if(!Ae)return Je(404,`User ${Ie} not found`,"invalidValue");return Ct(await ze(Ae,he,ve))},Le=async(he,ve)=>{let Ie=Pe.accessIndex;if(!Ie?.setSubjectDisabled||!ve.id)return;let Ae=he?he.active??!0:!0,Me=ve.active??!0;if(he&&Ae===Me)return;if(!he&&Me)return;await Ie.setSubjectDisabled(ve.id,"user",!Me)},je=async(he,ve)=>{let Ie=await he.json(),Ae=await Jt(T.user,Ie);if(Ae.issues)return E.error("User creation validation failed",{"ion.operation":"scim.user.create","ion.outcome":"failure",validationIssues:Ae.issues}),Je(400,`Request validation failed: ${Ae.issues.map((qe)=>qe.message).join("; ")}`,"invalidValue");let Me=Ae.value;if(!Me.userName&&!Me.emails?.[0]?.value)return Je(400,"userName or email is required","invalidValue");let Ve=await Be(Me,{mode:"create"});await cn(Pe,async()=>{await We.upsert(Ve),await Le(void 0,Ve)},br(void 0,Ve),{oaa:async()=>{await Rr(J,Ve)},delta:async()=>{await Pe.iamDelta?.onUserUpsert(Ve)}});let De=await ze(Ve,he,ve);return Ct(De,201,De.meta?.location)},Ee=async(he,ve,Ie)=>{let Ae=await We.get(Ie);if(!Ae)return Je(404,`User ${Ie} not found`,"invalidValue");let Me=await he.json(),Ve=await Jt(T.user,Me);if(Ve.issues)return E.error("User replacement validation failed",{"ion.operation":"scim.user.replace","ion.outcome":"failure",validationIssues:Ve.issues}),Je(400,`Request validation failed: ${Ve.issues.map((Ye)=>Ye.message).join("; ")}`,"invalidValue");let De=Ve.value,qe=await Be({...De,id:Ie},{existing:Ae,mode:"replace"});return qe.createdAt=Ae.createdAt,qe.updatedAt=new Date,await cn(Pe,async()=>{await We.upsert(qe),await Le(Ae,qe)},br(Ae,qe),{oaa:async()=>{await Rr(J,qe)},delta:async()=>{await us(Pe.iamDelta,Ae,qe)}}),Ct(await ze(qe,he,ve))},Ke=async(he,ve,Ie)=>{let Ae=await We.get(Ie);if(!Ae)return Je(404,`User ${Ie} not found`,"invalidValue");let Ve=(await he.json()).Operations??[],qe={...await Ze(Ae)};for(let dt of Ve)ke(qe,dt);let Ye=await Jt(T.user,qe);if(Ye.issues)return E.error("User patch validation failed",{"ion.operation":"scim.user.patch","ion.outcome":"failure",validationIssues:Ye.issues}),Je(400,`Request validation failed: ${Ye.issues.map((dt)=>dt.message).join("; ")}`,"invalidValue");let Qe=await Be(Ye.value,{existing:Ae,mode:"patch"});return Qe.updatedAt=new Date,await cn(Pe,async()=>{await We.upsert(Qe),await Le(Ae,Qe)},br(Ae,Qe),{oaa:async()=>{await Rr(J,Qe)},delta:async()=>{await us(Pe.iamDelta,Ae,Qe)}}),Ct(await ze(Qe,he,ve))},be=async(he)=>{let ve=await We.get(he);if(!ve)return Je(404,`User ${he} not found`,"invalidValue");if(ue){let Ie=[];for await(let Ae of c((Me,Ve)=>ue.listBySubject(he,"user",{start:Me,limit:Ve})))await wn(Pe,Ae,Ie);await _n(Pe,Ie)}if(await We.delete(he),await Pe.accessIndex?.setSubjectDisabled?.(he,"user",!1),ve.externalId&&Pe.iamDelta?.isReady())await Ht(Pe,"iam.delta.egress","IAM delta user delete failed after SCIM write; full aggregation will reconcile",()=>Pe.iamDelta?.onUserDelete(ve.externalId)??Promise.resolve(),{id:he,kind:"user"});else if(Pe.iamDelta?.isReady())Pe.log?.warn("IAM delta: deleted User has no externalId; destination delete skipped",{"ion.operation":"iam.delta.delete","ion.outcome":"skipped",id:he,kind:"user"});if(Pe.authz.oaa.isReady())await Ht(Pe,"authz.oaa.delete","OAA incremental user delete failed; full sync will reconcile",()=>Pe.authz.oaa.deleteUser(he),{id:he,kind:"user"});return new Response(null,{status:204})};Rt={handler:Ce}}let jt=async(We,Ge)=>{if(!ue)return;let Ne=[];for await(let Ze of c((ze,Be)=>ue.listBySubject(We,Ge,{start:ze,limit:Be})))await wn(Pe,Ze,Ne);await _n(Pe,Ne)};if(Oe.workloadIdentityStore){let{workloadIdentityStore:We,inboundWorkloads:Ge}=Oe;At=ls({resourceType:"Workload",subjectType:"workload",store:We,validator:T.workload??ae,toScim:async(Ne)=>await(Ge?.mapBaseWorkloadToScim?.(Ne)??Sr(Ne)),fromScim:async(Ne,Ze)=>{if(Ge?.mapValidatedScimToBaseWorkload)return Ge.mapValidatedScimToBaseWorkload(Ne,Ze);let ze=Ze.existing,Be=Ne,we=Be.id?.trim()||ze?.id||On(),de=o(Be.attributes??{},I);return{...ze??{},id:we,externalId:Be.externalId??ze?.externalId,clientId:Be.userName??ze?.clientId??we,displayName:Be.displayName??ze?.displayName,description:Be.description??ze?.description,active:Be.active??ze?.active??!0,providerId:ze?.providerId,requestUrl:ze?.requestUrl,...de}},projections:[{channel:"oaa",upsert:async(Ne)=>{if(J.oaa.isReady())await J.oaa.pushWorkload(Ne)},delete:async(Ne)=>{if(J.oaa.isReady())await J.oaa.deleteWorkload(Ne.id)}},{channel:"delta",upsert:async(Ne,Ze)=>{let ze=Ze?.externalId??Ze?.id,Be=Ne.externalId??Ne.id;if(ze&&ze!==Be)await Xe?.onWorkloadDelete(ze);await Xe?.onWorkloadUpsert(Ne)},delete:async(Ne)=>{await Xe?.onWorkloadDelete(Ne.externalId??Ne.id)}}]},{validateAuth:wt,accessStore:ue,accessIndex:pe,revokeSubjectAccess:jt,log:E})}if(Oe.customerStore){let{customerStore:We,inboundCustomers:Ge}=Oe;xt=ls({resourceType:"Customer",subjectType:"customer",store:We,validator:T.customer??ce,toScim:async(Ne)=>await(Ge?.mapBaseCustomerToScim?.(Ne)??wr(Ne)),fromScim:async(Ne,Ze)=>{if(Ge?.mapValidatedScimToBaseCustomer)return Ge.mapValidatedScimToBaseCustomer(Ne,Ze);let ze=Ze.existing,Be=Ne,we=Be.id?.trim()||ze?.id||On(),de=o(Be.attributes??{},A),Se=Be.emails?.find((ke)=>ke.primary)?.value??Be.emails?.[0]?.value;return{...ze??{},id:we,externalId:Be.externalId??ze?.externalId??we,userName:Be.userName??ze?.userName??we,name:Be.displayName??ze?.name??Be.userName??we,email:Se??ze?.email??"",displayName:Be.displayName??ze?.displayName,emails:Be.emails??ze?.emails,active:Be.active??ze?.active??!0,providerId:ze?.providerId,requestUrl:ze?.requestUrl,...de}},projections:[{channel:"oaa",upsert:async(Ne)=>{if(J.oaa.isReady())await J.oaa.pushCustomer(Ne)},delete:async(Ne)=>{if(J.oaa.isReady()&&Ne.id)await J.oaa.deleteCustomer(Ne.id)}},{channel:"delta",upsert:async(Ne,Ze)=>{let ze=Ze?.externalId??Ze?.id,Be=Ne.externalId??Ne.id;if(ze&&ze!==Be)await Xe?.onCustomerDelete(ze);await Xe?.onCustomerUpsert(Ne)},delete:async(Ne)=>{let Ze=Ne.externalId??Ne.id;if(Ze)await Xe?.onCustomerDelete(Ze)}}]},{validateAuth:wt,accessStore:ue,accessIndex:pe,revokeSubjectAccess:jt,log:E})}async function Et(We,Ge){gt();let Ne=new URL(We.url).pathname,Ze=Mt(Ge?.usersUrl??Oe.usersUrl??"/api/iam/Users")??"/api/iam/Users",ze=Mt(Ge?.groupsUrl??Oe.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",Be=Mt(Ge?.workloadsUrl??Oe.workloadsUrl??"/api/iam/Workloads")??"/api/iam/Workloads",we=Mt(Ge?.customersUrl??Oe.customersUrl??"/api/iam/Customers")??"/api/iam/Customers",de=`${ps(Ze,ze,Be,we)??"/api/iam"}/AccessRequests`,Se=await _t(We,Ge);if(Se)return Se;let ke=(Ce)=>Ne===Ce||Ne.startsWith(`${Ce}/`);if(ke(Ze)){if(!rt)return Je(404,"SCIM Users endpoint is disabled by RemoteConfig");if(!Rt)return Je(501,"SCIM Users endpoint is enabled by RemoteConfig but no user store capability is wired by the application.");return Rt.handler(We,{basePath:Ze})}if(ke(ze)){if(!ot)return Je(404,"SCIM Groups endpoint is disabled by RemoteConfig");if(!zt)return Je(501,"SCIM Groups endpoint is enabled by RemoteConfig but no AccessCatalogStore capability is wired by the application.");return zt.handler(We,{basePath:ze})}if(ke(Be)){if(!ut)return Je(404,"SCIM Workloads endpoint is disabled by RemoteConfig");if(!At)return Je(501,"SCIM Workloads endpoint is enabled by RemoteConfig but no workload identity store capability is wired by the application.");return At.handler(We,{basePath:Be})}if(ke(we)){if(!St)return Je(404,"SCIM Customers endpoint is disabled by RemoteConfig");if(!xt)return Je(501,"SCIM Customers endpoint is enabled by RemoteConfig but no customer store capability is wired by the application.");return xt.handler(We,{basePath:we})}if(ke(de)){if(!Oe.accessRequests)return Je(404,"AccessRequests endpoint is not configured");if(We.method!=="POST")return Je(405,"Method not allowed");if(!await wt(We))return Je(401,"Authorization required");let Ce;try{Ce=await We.json()}catch{return Je(400,"Request body must be valid JSON","invalidSyntax")}if(typeof Ce.subject!=="string"||!Ce.subject||typeof Ce.target!=="string"||!Ce.target||Ce.subjectType!=="user"&&Ce.subjectType!=="workload"&&Ce.subjectType!=="customer"||Ce.targetType!=="group"&&Ce.targetType!=="role"&&Ce.targetType!=="permission"||Ce.operation!=="grant"&&Ce.operation!=="revoke")return Je(400,"subject, subjectType, targetType, target, and operation are required","invalidValue");let Ue=await Oe.accessRequests.create({subject:Ce.subject,subjectType:Ce.subjectType,targetType:Ce.targetType,target:Ce.target,operation:Ce.operation,justification:typeof Ce.justification==="string"?Ce.justification:void 0});return Ct(Ue.request,Ue.created?201:200,Ue.request.trackingUrl)}return Je(404,"Resource not found")}return{...Oe,users:Cr(Oe.users),workloads:Cr(Oe.workloads),customers:Cr(Oe.customers),groups:{enabled:ot},createUser:qt,getBaseUrl:Ft,groups_outbound:rn,groups_inbound:zt,users_inbound:Rt,workloads_inbound:At,customers_inbound:xt,handler:Et,delta:Xe}}function Er(T,E){let M=new TextEncoder().encode(T),J=typeof E==="string"?new TextEncoder().encode(E):E,ue=new Uint8Array(M.length+1+J.length);return ue.set(M,0),ue[M.length]=46,ue.set(J,M.length+1),ue}function ao(T){let E=T.replace(/-/g,"+").replace(/_/g,"/"),M=E.length%4===0?"":"=".repeat(4-E.length%4),J=atob(E+M),ue=new Uint8Array(J.length);for(let pe=0;pe<J.length;pe++)ue[pe]=J.charCodeAt(pe);return ue}function co(T){let E="";for(let M of T)E+=String.fromCharCode(M);return btoa(E).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function fs(T){let E=JSON.parse(T);if(!E||typeof E!=="object"||!Array.isArray(E.keys))throw Error("Invalid JWKS: expected { keys: [...] }");return E}function uo(T){return JSON.stringify(T)}async function lo(T){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:T.x},{name:"Ed25519"},!0,["verify"])}async function po(T){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:T.x,d:T.d},{name:"Ed25519"},!0,["sign"])}async function mo(T){let M=(typeof T.jwks==="string"?fs(T.jwks):T.jwks).keys.find((J)=>J.kid===T.kid&&J.kty==="OKP"&&J.crv==="Ed25519");if(!M?.x)return!1;try{let J=await lo(M),ue=Er(T.requestId,T.rawBody),pe=ao(T.signatureB64Url);return crypto.subtle.verify({name:"Ed25519"},J,pe,ue)}catch{return!1}}async function fo(T){let E=await po(T.privateKeyJwk),M=Er(T.requestId,T.rawBody),J=await crypto.subtle.sign({name:"Ed25519"},E,M);return co(new Uint8Array(J))}async function go(T){let E=await crypto.subtle.generateKey({name:"Ed25519"},!0,["sign","verify"]),M=await crypto.subtle.exportKey("jwk",E.privateKey),ue=(await crypto.subtle.exportKey("jwk",E.publicKey)).x,pe=M.d;if(!ue||!pe)throw Error("Failed to export Ed25519 key material (missing x/d)");return{privateJwk:{kty:"OKP",crv:"Ed25519",x:ue,d:pe,kid:T,alg:"EdDSA",use:"sig"},publicJwks:{keys:[{kty:"OKP",crv:"Ed25519",x:ue,kid:T,alg:"EdDSA",use:"sig"}]}}}var Rn={jwksTtlSeconds:{min:60,max:86400,default:600},jwksMaxEntries:{min:16,max:4096,default:256},sessionReadTtlSeconds:{min:1,max:300,default:30},sessionReadMaxEntries:{min:16,max:65536,default:1024}};function $n(T,E){if(typeof T!=="number"||!Number.isFinite(T))return E.default;let M=Math.floor(T);if(M<E.min)return E.min;if(M>E.max)return E.max;return M}function gs(T){return{ttlMs:$n(T?.ttlSeconds,Rn.jwksTtlSeconds)*1000,maxEntries:$n(T?.maxEntries,Rn.jwksMaxEntries)}}function ys(T){let E=T?.read;return{read:{enabled:E?.enabled===!0,ttlMs:$n(E?.ttlSeconds,Rn.sessionReadTtlSeconds)*1000,maxEntries:$n(E?.maxEntries,Rn.sessionReadMaxEntries)}}}function yo(T){return{jwks:gs(T?.jwks),session:ys(T?.session)}}var Wn=new TextEncoder,ho=new TextDecoder;function Ss(T){let E="";for(let M of T)E+=String.fromCharCode(M);return btoa(E).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function hs(T){return Ss(Wn.encode(JSON.stringify(T)))}function ws(T){if(!/^[A-Za-z0-9_-]+$/.test(T))return;let E=T.replace(/-/g,"+").replace(/_/g,"/").padEnd(Math.ceil(T.length/4)*4,"=");try{return Uint8Array.from(atob(E),(M)=>M.charCodeAt(0))}catch{return}}function ks(T){let E=ws(T);if(!E)return;try{let M=JSON.parse(ho.decode(E));return M!==null&&typeof M==="object"&&!Array.isArray(M)?M:void 0}catch{return}}function ko(T){return Wn.encode(T)}function Cs(T){let E=new Uint8Array(T.byteLength);return E.set(T),E.buffer}async function bs(T){return crypto.subtle.importKey("raw",Cs(ko(T)),{name:"HMAC",hash:"SHA-256"},!1,["sign","verify"])}function So(T){let E=T.active.trim(),M=new Map(Object.entries(T.keys).map(([ue,pe])=>[ue.trim(),{kid:ue.trim(),secret:pe}])),J=M.get(E);if(!E||!J?.secret)throw Error("Signing key ring must name a non-empty active key.");for(let ue of M.values())if(!ue.kid||!ue.secret)throw Error("Signing key ring ids and secrets must be non-empty.");return{current:()=>J,find:(ue)=>M.get(ue)}}async function wo(T,E,M){let J=Math.floor(M.ttlSeconds);if(!Number.isFinite(J)||J<1)throw Error("Compact JWT ttlSeconds must be a positive integer.");let ue=E.current();if(!ue.kid||!ue.secret)throw Error("Signing key ring returned an invalid active key.");let pe=Math.floor(Date.now()/1000),me=hs({alg:"HS256",kid:ue.kid,typ:"JWT"}),ge=hs({...T,iat:pe,exp:pe+J}),ye=`${me}.${ge}`,fe=await crypto.subtle.sign("HMAC",await bs(ue.secret),Wn.encode(ye));return`${ye}.${Ss(new Uint8Array(fe))}`}async function Co(T,E){let M=T.split(".");if(M.length!==3)return null;let[J,ue,pe]=M;if(!J||!ue||!pe)return null;let me=ks(J);if(me?.alg!=="HS256"||me.typ!=="JWT"||typeof me.kid!=="string")return null;let ge=E.find(me.kid);if(!ge?.secret)return null;let ye=ws(pe);if(!ye)return null;if(!await crypto.subtle.verify("HMAC",await bs(ge.secret),Cs(ye),Wn.encode(`${J}.${ue}`)))return null;let $e=ks(ue);if(!$e)return null;let{iat:Xe,exp:et}=$e;if(typeof Xe!=="number"||typeof et!=="number"||!Number.isSafeInteger(Xe)||!Number.isSafeInteger(et))return null;let st=Math.floor(Date.now()/1000);if(Xe>st+60||et+60<=st)return null;return $e}function bo(T){let E={};if(!T)return E;let M=T.split(";");for(let J of M){let ue=J.trim();if(!ue)continue;let pe=ue.indexOf("=");if(pe===-1)continue;E[ue.slice(0,pe).trim()]=ue.slice(pe+1).trim()}return E}function vs(T){if(!T.expiresAt)return!1;let E=T.expiresAt instanceof Date?T.expiresAt:new Date(T.expiresAt);return!Number.isNaN(E.getTime())&&Date.now()>E.getTime()}function vo(T){if(!T||typeof T!=="object"||Array.isArray(T))return;let{access_token:E,id_token:M,refresh_token:J,tokens:ue,...pe}=T;return pe}function Ut(T,E){let M=T[E];return typeof M==="string"?M:""}function Ro(T,E){let M=T.exp;if(typeof M==="number")return new Date(M*1000);if(typeof M==="string"&&M.trim()){let J=Number(M);if(!Number.isNaN(J))return new Date(J*1000)}if(E instanceof Date)return E;if(E){let J=new Date(E);if(!Number.isNaN(J.getTime()))return J}return new Date}function Ao(T){let E=T.claims;if(!E?.sub||typeof E.sub!=="string")return;let M=Ro(E,T.expiresAt);if(T.authType==="sso")return{id:E.sub,userName:Ut(E,"preferred_username"),name:Ut(E,"name"),email:Ut(E,"email"),avatar:Ut(E,"picture")||void 0,sso:{profile:E,tenant:{id:Ut(E,"idp")||Ut(E,"iss"),name:Ut(E,"iss")},tokenType:"Bearer",expires:M}};return{id:E.sub,userName:Ut(E,"preferred_username"),name:Ut(E,"name"),email:Ut(E,"email"),avatar:Ut(E,"picture")||void 0,userType:"customer",ciam:{profile:E,scope:"openid profile email",tokenType:"Bearer",expires:M}}}function Io(T){if(T.authType!=="sso"&&T.authType!=="ciam")return;if(vs(T))return;return{sid:T.sid,authType:T.authType,tenantId:typeof T.tenantId==="string"?T.tenantId:void 0,sub:T.sub,expiresAt:T.expiresAt,createdAt:T.createdAt,claims:vo(T.claims)}}function To(T,E){if(!T.endsWith(".session"))return!1;if(!E||E.length===0)return!0;return E.some((M)=>T===`${M}.session`)}function xo(T){if(T===void 0)return;let E=(Array.isArray(T)?T:[T]).map((M)=>M.trim()).filter((M)=>M.length>0);return E.length>0?E:void 0}async function Rs(T,E,M){return(await As(T,E,M)).map(Io).filter((ue)=>Boolean(ue))}async function As(T,E,M){let J=bo(T.headers.get("cookie")),ue=xo(M?.cookiesPrefix),pe=[],me=new Set;for(let[ge,ye]of Object.entries(J)){if(!To(ge,ue)||!ye)continue;if(me.has(ye))continue;me.add(ye);let fe=await E.get(ye);if(!fe)continue;if(fe.authType!=="sso"&&fe.authType!=="ciam")continue;if(vs(fe))continue;pe.push(fe)}return pe}async function Po(T,E,M){return(await Rs(T,E,M)).map(Ao).filter((ue)=>Boolean(ue))}var Uo="@ionite/core",Eo=l(y(Uo));async function Mo(T,E){let M=await Kt({idToken:T,jwksUri:E.jwksUri,issuer:E.issuer,audience:E.audience}),J=await Eo.validate(M);if(J.issues)throw Error(`ID token claims validation failed: ${J.issues.map((me)=>me.message).join("; ")}`);let ue=J.value;if(ue===void 0)throw Error("ID token claims missing");return G(ue)}function kt(T){return Date.now()-T}function Mr(T){if(T instanceof Error)return{"error.name":T.name,"error.message":T.message};return{"error.name":typeof T,"error.message":String(T)}}function Vn(T,E){if(!T)return{};try{let M=new URL(T);return{[`${E}.origin`]:M.origin,[`${E}.path`]:M.pathname}}catch{return{[`${E}.path`]:T.startsWith("/")?T:`/${T}`}}}function qn(T,E=5){if(!Array.isArray(T))return[String(T)];return T.slice(0,E).map((M)=>{if(!M||typeof M!=="object")return String(M);let J=M,ue=Array.isArray(J.path)?J.path.join("."):String(J.path??""),pe=typeof J.message==="string"?J.message:String(J.message??"validation failed");return ue?`${ue}: ${pe}`:pe})}function Do(T){if(!T||typeof T!=="object")return{};let E=T;return{oidc_error:typeof E.error==="string"?E.error:void 0,oidc_error_description:typeof E.error_description==="string"?E.error_description:void 0,oidc_error_uri:typeof E.error_uri==="string"?E.error_uri:void 0}}function Oo(T,E={}){let M=typeof T==="string"?T:T?.headers.get("cookie")??void 0;if(!M)return[];let ue=`${E.cookiePrefix??"ion.sso"}.`,pe=new Set;for(let me of Object.keys(jo(M))){if(!me.startsWith(ue))continue;let ge=me.slice(ue.length),ye=ge.lastIndexOf(".");if(ye<=0)continue;let fe=ge.slice(0,ye).trim();if(fe)pe.add(fe)}return Array.from(pe)}function _o(T,E,M,J,ue){if(!M&&!J)return;let pe=new WeakMap,me=new Map,ge={...M,...J},ye=!!(ge.authority&&ge.tokenUrl&&ge.authorizationUrl&&ge.clientId&&ge.redirectUri&&ge.scope),fe={...ge,authority:ye?t(ge.authority,"Missing 'authority' from SSO Config"):ge.authority,tokenUrl:ye?t(ge.tokenUrl,"Missing 'tokenUrl' from SSO Config"):ge.tokenUrl,authorizationUrl:ye?t(ge.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"):ge.authorizationUrl,clientId:ye?t(ge.clientId,"Missing 'clientId' from SSO Config"):ge.clientId,redirectUri:ye?t(ge.redirectUri,"Missing 'redirectUri' from SSO Config"):ge.redirectUri,scope:ye?t(ge.scope,"Missing 'scope' from SSO Config"):ge.scope,responseType:ge.responseType??"code",cookiesSecure:ge.cookiesSecure!==void 0?ge.cookiesSecure:!0,cookiesSameSite:ge.cookiesSameSite!==void 0?ge.cookiesSameSite:"Strict",cookiesPrefix:ge.cookiesPrefix??(ge.clientId?`ion.sso.${ge.clientId}`:"ion.sso"),cookiesPath:ge.cookiesPath??"/",cookiesDomain:xn(ge.cookiesDomain)},$e=Math.min(600,Math.max(0,Math.floor(Number(fe.rotationGraceSeconds??60))||0))*1000,Xe=Math.floor(Number(fe.sessionWindowSeconds??86400)),et=Number.isFinite(Xe)&&Xe>=1?Xe:86400;function st(){let we=[];if(!fe.authority)we.push("authority");if(!fe.tokenUrl)we.push("tokenUrl");if(!fe.authorizationUrl)we.push("authorizationUrl");if(!fe.clientId)we.push("clientId");if(!fe.redirectUri)we.push("redirectUri");if(!fe.scope)we.push("scope");if(we.length>0)throw Error(`Missing OIDC configuration fields: ${we.join(", ")}. OIDC configuration is required for SSO operations. Please provide these fields either in your vault configuration or in the SSO config when initializing ionite.`)}async function it(we){if(!fe)throw Error("ionite SSO Manager not initialized");let de=pe.get(we);if(de)return de;let Se=Pe(we);return pe.set(we,Se),Se}async function Pe(we){try{let{tokens:de,session:Se,refreshedUser:ke}=await Rt(we);if(!de)return{status:"unauthenticated"};if(ke)return{status:"authenticated",value:ke};if(Se?.claims)return{status:"authenticated",value:gt(Se.claims,de,_t(Se.expiresAt))};return{status:"unauthenticated"}}catch(de){if(Is(de))return{status:"unauthenticated"};return E.error("Error parsing user from cookies",{"ion.operation":"cookie.parse","ion.outcome":"degraded"},de),{status:"degraded",error:de instanceof Error?de:void 0}}}async function He(we){let de=await it(we);return de.status==="authenticated"?de.value:void 0}async function Oe(we){if(!fe)throw Error("ionite SSO Manager not initialized");st();let de=t(fe.redirectUri,"Missing 'redirectUri' from SSO Config"),Se=t(fe.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"),ke=t(fe.clientId,"Missing 'clientId' from SSO Config"),Ce=t(fe.scope,"Missing 'scope' from SSO Config"),Ue=fe.cookiesSecure?we.url.replace(/^http:\/\//,"https://"):we.url,_e=Pt(),Le=Pt(64),je=Pt(),Ee=de;try{new URL(Ee)}catch{if(Ue)try{let Ie=new URL(Ue),Ae=Ee.startsWith("//")?Ee.slice(1):Ee.startsWith("/")?Ee:`/${Ee}`;Ee=new URL(Ae,Ie.origin).toString()}catch{try{let Ie=new URL(Se),Ae=Ee.startsWith("//")?Ee.slice(1):Ee.startsWith("/")?Ee:`/${Ee}`;Ee=new URL(Ae,Ie.origin).toString()}catch{throw Error(`Invalid redirectUri: "${de}". It must be a valid absolute URL.`)}}}let Ke=new URL(Se);Ke.searchParams.append("client_id",ke),Ke.searchParams.append("redirect_uri",Ee),Ke.searchParams.append("response_type","code"),Ke.searchParams.append("scope",Ce),Ke.searchParams.append("state",_e),Ke.searchParams.append("nonce",je);let be=await kn(Le);Ke.searchParams.append("code_challenge",be),Ke.searchParams.append("code_challenge_method","S256");let he=await fe.beforeLogin?.({request:we}),ve=he===void 0?{state:_e,codeVerifier:Le,nonce:je}:{state:_e,codeVerifier:Le,nonce:je,context:he};return new Response("Redirecting to SSO Provider",{status:302,headers:{Location:Ke.toString(),"Set-Cookie":xt(ze(_e),ve,fe.loginStateTtl??600,"Lax")}})}async function rt(we){if(!fe)throw Error("ionite SSO Manager not initialized");let de;try{de=await He(we)}catch{de=void 0}let Se=await fe.beforeLogout?.({request:we,user:de}),ke=Ze("session",we),Ce;try{Ce=await Rt(we);let be=Ce.tokens?.refresh_token??Ze("refresh",we);if(be)await Ft(be)}catch(be){E.warn("Failed to revoke token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},be)}if(fe.sessionStore)try{let be=Ce?.sid??ke;if(be)await fe.sessionStore.delete(be)}catch(be){E.warn("Failed to delete session",{"ion.operation":"session.delete","ion.outcome":"degraded"},be)}let Ue=We(),_e=await fe.afterLogout?.({request:we,context:Se}),Le=Gt(_e,"/",we.url);if(Le.response){let be=new Headers(Le.response.headers);for(let[,he]of Ue)be.append("Set-Cookie",he);return new Response(Le.response.body,{status:Le.response.status,statusText:Le.response.statusText,headers:be})}let je=Le.location??"/",Ee=we.headers.get("accept");if(Ee?.includes(s)||Ee?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:je}),{status:200,headers:[["Content-Type",s],...Ue]});return new Response("Logged out",{status:302,headers:[["Location",je],...Ue]})}async function ot(we){if(!fe)throw Error("ionite SSO Manager not initialized");if(!fe.sessionStore)throw Error("Back-Channel Logout requires sessionStore configuration");try{if(!we.headers.get("content-type")?.includes(_))return new Response("Invalid Content-Type, expected application/x-www-form-urlencoded",{status:400});let Se=await we.text(),Ce=new URLSearchParams(Se).get("logout_token");if(!Ce)return new Response("Missing logout_token parameter",{status:400});let Ue=t(fe.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify logout tokens."),_e=t(fe.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify logout tokens."),Le=fe.jwksUri||`${Ue}/protocol/openid-connect/certs`,je=await lr({logoutToken:Ce,jwksUri:Le,issuer:Ue,audience:_e,log:E}),Ee=typeof je.sid==="string"?je.sid:void 0;if(!Ee)return E.warn("Back-Channel Logout: logout_token missing sid claim",{"ion.operation":"backchannel_logout","ion.outcome":"failure"}),new Response("Invalid logout_token: missing sid claim",{status:400});return await fe.sessionStore.delete(Ee),E.info("Back-Channel Logout: successfully deleted session",{"ion.module":"sso",sid:Ee}),new Response("OK",{status:200})}catch(de){return E.error("Error during back-channel logout",{"ion.operation":"backchannel_logout","ion.outcome":"failure"},de),new Response("Internal Server Error",{status:500})}}async function ut(we){if(!fe)throw Error("ionite SSO Manager not initialized");let de=Date.now(),Se=new URL(we.url),ke=new URLSearchParams(Se.search);E.debug("SSO callback received",{"ion.event":"ion.sso.callback.received","ion.module":"sso","ion.operation":"sign_in.callback","http.method":we.method,"url.path":Se.pathname,hasCode:ke.has("code"),hasState:ke.has("state"),hasError:ke.has("error"),...Vn(ke.get("iss")??void 0,"oidc.issuer")});let Ce=Object.fromEntries(ke.entries()),Ue=await T.callbackParams.validate(Ce);if(Ue.issues)return E.warn("SSO callback parameter validation failed",{"ion.event":"ion.sso.callback.validation_failed","ion.operation":"sign_in.callback","ion.outcome":"failure","validation.issues":qn(Ue.issues)}),ie(Ue.issues,"OIDC callback parameters validation failed");let{code:_e,state:Le}=Ue.value,je;try{let Ee=t(Le,'OIDC "state" was not present in the callback parameters'),Ke=Ze(ze(Ee),we,!0),{codeVerifier:be,state:he,nonce:ve,context:Ie}=Ke??{};je=Ie,E.debug("SSO callback state cookie read",{"ion.event":"ion.sso.callback.state_cookie_read","ion.module":"sso","ion.operation":"sign_in.callback",hasStateCookie:Boolean(Ke),hasCodeVerifier:Boolean(be),hasStateVerifier:Boolean(he),hasNonce:Boolean(ve),hasContext:Ie!==void 0});let Ae=t(be,'OIDC "codeVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');t(he,'OIDC "stateVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');let Me=t(ve,'OIDC "nonce" was not present in cookies, ensure that the SSO login was initiated correctly'),Ve=t(_e,'OIDC "code" was not present in the callback parameters');if(Le!==he)throw E.warn("SSO callback state verification failed",{"ion.event":"ion.sso.callback.state_verification_failed","ion.operation":"sign_in.callback","ion.outcome":"failure"}),Error('SSO State Verifier failed, the "state" request parameter does not equal the "state" in the SSO cookie');E.debug("SSO callback state verified",{"ion.event":"ion.sso.callback.state_verified","ion.module":"sso","ion.operation":"sign_in.callback"});let De=fe.cookiesSecure?we.url.replace(/^http:\/\//,"https://"):we.url,qe=await en(Ve,Ae,De),{tokenExpiresAt:Ye,sessionExpiresAt:Qe}=St(qe);qe.expires=Ye.toISOString();let dt=Date.now();E.debug("SSO ID token parsing started",{"ion.event":"ion.sso.id_token.parse_started","ion.module":"sso","ion.operation":"id_token.parse"});let ct=await pt(qe,Me,Qe);E.debug("SSO ID token parsing completed",{"ion.event":"ion.sso.id_token.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":kt(dt),"user.id":ct.id});let at,nt;{let mt=Ot("SSO requires sessionStore configuration for opaque session cookies."),sn=typeof ct.sso.profile.sid==="string"?ct.sso.profile.sid:void 0,pn=sn||Pt(32),Tt=ct.id;if(E.debug("SSO session creation evaluated",{"ion.event":"ion.sso.session.create_evaluated","ion.module":"sso","ion.operation":"session.create",hasSid:Boolean(pn),hasIdpSid:Boolean(sn),hasSub:Boolean(Tt),"user.id":Tt}),!Tt)throw Error("Session creation failed: missing sub in ID token claims");let Kn=Date.now(),An={sid:pn,sub:Tt,idpSid:sn,authType:"sso",tenantId:fe.tenantId,tokens:qe,claims:ct.sso.profile,expiresAt:Qe,createdAt:new Date};await Vt(mt,An),nt=An,at=["Set-Cookie",xt("session",pn,Qe)],E.info("SSO session created",{"ion.event":"ion.sso.session.created","ion.operation":"session.create","ion.outcome":"success","duration.ms":kt(Kn),"user.id":Tt})}if(fe.userStore)try{let mt=ct.id;if(mt){let sn=new Date,pn=Date.now();E.debug("SSO user store lookup started",{"ion.event":"ion.sso.user.lookup_started","ion.module":"sso","ion.operation":"user.lookup","user.id":mt});let Tt=await fe.userStore.get(mt);if(E.debug("SSO user store lookup completed",{"ion.event":"ion.sso.user.lookup_completed","ion.module":"sso","ion.operation":"user.lookup","duration.ms":kt(pn),"user.id":mt,found:Boolean(Tt)}),Tt||fe.enableJitUserProvisioning){let Kn=Date.now(),An={...Tt??{},...ct,id:mt,tenantId:Tt?.tenantId,createdAt:Tt?.createdAt??sn,updatedAt:sn};await fe.userStore.upsert(An),E.info("SSO user stored",{"ion.event":"ion.sso.user.stored","ion.operation":"user.store","ion.outcome":"success","duration.ms":kt(Kn),"user.id":mt,existing:Boolean(Tt),jitProvisioning:Boolean(fe.enableJitUserProvisioning)})}else E.warn("JIT user provisioning disabled: user not found in store and will not be created",{"ion.event":"ion.sso.user.skipped","ion.operation":"user.store","ion.outcome":"skipped","user.id":mt})}else E.warn("User storage skipped: missing sub in ID token claims",{"ion.event":"ion.sso.user.skipped","ion.operation":"user.store","ion.outcome":"skipped"})}catch(mt){E.warn("Failed to store user",{"ion.event":"ion.sso.user.store_failed","ion.operation":"user.store","ion.outcome":"degraded",...Mr(mt)})}E.info("SSO sign-in succeeded",{"ion.event":"ion.sso.sign_in.succeeded","ion.operation":"sign_in.callback","ion.outcome":"success","duration.ms":kt(de),"user.id":ct.id});let bt=[["Set-Cookie",jt(ze(Ee))],...at?[at]:[],...at?await Ne(we,await wt(ct),Qe):[]],tt=await fe.afterLogin?.({ok:!0,request:we,user:ct,session:nt,context:je,displayCookie:fe.displayCookie,displayCookieAttributes:Et()}),It=Gt(tt,"/",we.url);if(It.response)return Yt(It.response,bt.map(([,mt])=>mt));return new Response("Authentication successful, redirecting",{status:302,headers:[["Location",It.location],...bt]})}catch(Ee){E.error("Error during sign-in callback",{"ion.event":"ion.sso.sign_in.callback_failed","ion.operation":"sign_in.callback","ion.outcome":"failure","duration.ms":kt(de),...Mr(Ee)});let Ke=Le?[["Set-Cookie",jt(ze(Le))]]:[],be=await fe.afterLogin?.({ok:!1,request:we,error:Ee,context:je,displayCookie:fe.displayCookie,displayCookieAttributes:Et()}),he=Gt(be,"/",we.url);if(he.response)return Yt(he.response,Ke.map(([,ve])=>ve));return new Response("Authentication failed, redirecting",{status:302,headers:[["Location",he.location],...Ke]})}}function St(we){let de=Date.now(),Se=Number(we.expires_in??3600)||3600,ke=new Date(de+Se*1000),Ce;if(we.refresh_expires_in!=null&&Number.isFinite(Number(we.refresh_expires_in)))Ce=Number(we.refresh_expires_in);else if(we.refresh_token)Ce=et;else Ce=Se;return{tokenExpiresAt:ke,sessionExpiresAt:new Date(de+Ce*1000)}}async function pt(we,de,Se){if(!fe)throw Error("ionite SSO Manager not initialized");let ke=Date.now(),Ce=await nn(we.id_token,de);return E.debug("SSO user parsed from ID token",{"ion.event":"ion.sso.user.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":kt(ke),"user.id":Ce.sub,hasEmail:Boolean(Ce.email),hasName:Boolean(Ce.name)}),gt(Ce,we,Se)}function gt(we,de,Se){let ke=Se??St(de).sessionExpiresAt,Ce=we.ecid!==void 0&&we.ecid!==null?P(we.ecid):void 0;return{id:we.sub,userName:we.preferred_username||"",name:we.name||"",email:we.email||"",emails:[{value:we.email||"",primary:!0}],...Ce?{ecid:Ce}:{},avatar:we.picture,sso:{profile:{...we},tenant:{id:we.idp||we.iss||"",name:we.iss||""},scope:de.scope,tokenType:de.token_type,sessionState:de.session_state,expires:ke}}}async function wt(we){if(!fe.userStore)return we;let de=await fe.userStore.lookup(we);if(!de)return we;return{...we,...de,id:we.id,sso:we.sso}}async function en(we,de,Se){if(!fe)throw Error("ionite SSO Manager not initialized");st();let ke=t(fe.tokenUrl,"Missing 'tokenUrl' from SSO Config"),Ce=t(fe.redirectUri,"Missing 'redirectUri' from SSO Config"),Ue=t(fe.clientId,"Missing 'clientId' from SSO Config"),_e=Ce;try{new URL(_e)}catch{if(Se)try{let je=new URL(Se),Ee=_e.startsWith("//")?_e.slice(1):_e.startsWith("/")?_e:`/${_e}`;_e=new URL(Ee,je.origin).toString()}catch{try{let je=new URL(ke),Ee=_e.startsWith("//")?_e.slice(1):_e.startsWith("/")?_e:`/${_e}`;_e=new URL(Ee,je.origin).toString()}catch{throw Error(`Invalid redirectUri: "${Ce}". It must be a valid absolute URL.`)}}}let Le=new URLSearchParams;if(Le.append("grant_type","authorization_code"),Le.append("code",we),Le.append("redirect_uri",_e),Le.append("client_id",Ue),fe.clientSecret)Le.append("client_secret",fe.clientSecret);Le.append("code_verifier",de);try{let je=Date.now();E.debug("SSO token exchange started",{"ion.event":"ion.sso.token.exchange_started","ion.module":"sso","ion.operation":"token.exchange",...Vn(ke,"oidc.token_url"),...Vn(_e,"oidc.redirect_uri"),hasClientSecret:Boolean(fe.clientSecret)});let Ee=await fetch(ke,{method:"POST",headers:{...h,...i},body:Le.toString()});E.debug("SSO token exchange response received",{"ion.event":"ion.sso.token.response_received","ion.module":"sso","ion.operation":"token.exchange","http.status_code":Ee.status,"duration.ms":kt(je)}),E.debug("SSO token exchange response body read started",{"ion.event":"ion.sso.token.response_body_read_started","ion.module":"sso","ion.operation":"token.exchange"});let Ke=await a(Ee,{log:E,operation:"token.exchange"});if(E.debug("SSO token exchange response body read completed",{"ion.event":"ion.sso.token.response_body_read_completed","ion.module":"sso","ion.operation":"token.exchange","duration.ms":kt(je)}),!Ee.ok){E.error("Token exchange error",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":Ee.status,"duration.ms":kt(je),...Do(Ke)});let he=Ke;throw Error(`Token exchange failed: ${he.error||Ee.statusText} - ${he.error_description||""}`.trim())}let be=await T.tokenResponse.validate(Ke);if(be.issues)throw E.error("Token response validation failed",{"ion.event":"ion.sso.token.response_validation_failed","ion.operation":"token.exchange","ion.outcome":"failure","duration.ms":kt(je),"validation.issues":qn(be.issues)}),Error(`Token response validation failed: ${be.issues}`);return E.debug("SSO token exchange completed",{"ion.event":"ion.sso.token.exchange_completed","ion.module":"sso","ion.operation":"token.exchange","ion.outcome":"success","duration.ms":kt(je),tokenType:be.value.token_type,hasAccessToken:Boolean(be.value.access_token),hasIdToken:Boolean(be.value.id_token),hasRefreshToken:Boolean(be.value.refresh_token),expiresIn:be.value.expires_in}),be.value}catch(je){throw E.error("Error during token exchange",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure",...Mr(je)}),je}}async function tn(we){return ir(async()=>{if(!fe)throw Error("ionite SSO Manager not initialized");st();let de=t(fe.tokenUrl,"Missing 'tokenUrl' from SSO Config"),Se=t(fe.clientId,"Missing 'clientId' from SSO Config"),ke=new URLSearchParams;if(ke.append("grant_type","refresh_token"),ke.append("refresh_token",we),ke.append("client_id",Se),fe.clientSecret)ke.append("client_secret",fe.clientSecret);let Ce=await fetch(de,{method:"POST",headers:{...h,...i},body:ke.toString()}),Ue=await a(Ce,{log:E,operation:"token.refresh"});if(!Ce.ok){E.error("Token refresh error",{"ion.operation":"token.refresh","ion.outcome":"failure",response:Ue});let Le=Ue;throw Error(`Token refresh failed: ${Le.error||Ce.statusText} - ${Le.error_description||""}`.trim())}let _e=await T.tokenResponse.validate(Ue);if(_e.issues)throw E.error("Token refresh response validation failed",{"ion.event":"ion.sso.token.refresh_validation_failed","ion.operation":"token.refresh","ion.outcome":"failure","validation.issues":qn(_e.issues)}),Error(`Token refresh response validation failed: ${_e.issues}`);return _e.value},void 0,void 0,void 0,E)}async function Ft(we){try{if(!fe)throw Error("ionite SSO Manager not initialized");if(!fe.revocationEndpoint)return;let de=t(fe.clientId,"Missing 'clientId' from SSO Config"),Se=new URLSearchParams;if(Se.append("token",we),Se.append("token_type_hint","refresh_token"),Se.append("client_id",de),fe.clientSecret)Se.append("client_secret",fe.clientSecret);let ke=await fetch(fe.revocationEndpoint,{method:"POST",headers:{...i,...h},body:Se.toString()});if(!ke.ok)E.warn("Token revocation failed",{"ion.operation":"token.revoke","ion.outcome":"degraded",status:ke.status,statusText:ke.statusText});else E.info("Token revoked successfully",{"ion.module":"sso"})}catch(de){E.warn("Error revoking token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},de)}}async function ln(){if(!fe)throw Error("ionite SSO Manager not initialized");let we=fe.authority;if(!fe.jwksUri&&!we)throw Error("Missing 'jwksUri' or 'authority' from SSO Config. OIDC configuration is required for this operation.");let de=fe.jwksUri||`${we}/protocol/openid-connect/certs`;return gn(de,E)}async function nn(we,de){let Se=Date.now(),ke=t(fe.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify ID tokens."),Ce=t(fe.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify ID tokens."),Ue=fe.jwksUri||`${ke}/protocol/openid-connect/certs`;E.debug("SSO ID token verification started",{"ion.event":"ion.sso.id_token.verify_started","ion.module":"sso","ion.operation":"id_token.verify",...Vn(Ue,"oidc.jwks_uri")});let _e;try{_e=await Kt({idToken:we,jwksUri:Ue,issuer:ke,audience:Ce,expectedNonce:de,log:E})}catch(je){throw E.error("SSO ID token verification failed",{"ion.event":"ion.sso.id_token.verify_failed","ion.module":"sso","ion.operation":"id_token.verify","ion.outcome":"failure","duration.ms":kt(Se)},je),je}E.debug("SSO ID token signature verified",{"ion.event":"ion.sso.id_token.signature_verified","ion.module":"sso","ion.operation":"id_token.verify","duration.ms":kt(Se)});let Le=await T.idTokenClaims.validate(_e);if(Le.issues)throw E.error("ID token claims validation failed",{"ion.event":"ion.sso.id_token.validation_failed","ion.operation":"id_token.validate","ion.outcome":"failure","duration.ms":kt(Se),"validation.issues":qn(Le.issues)}),Error(`ID token claims validation failed: ${Le.issues}`);return E.debug("SSO ID token claims validated",{"ion.event":"ion.sso.id_token.claims_validated","ion.module":"sso","ion.operation":"id_token.validate","ion.outcome":"success","duration.ms":kt(Se),"user.id":Le.value.sub,hasIssuer:Boolean(Le.value.iss),hasAudience:Boolean(Le.value.aud)}),Le.value}function Ot(we="SSO sessionStore is required for opaque session cookies."){if(!fe.sessionStore)throw Error(we);return fe.sessionStore}async function Vt(we,de){try{await we.create(de)}catch(Se){if(!await we.get(de.sid))throw Se;await we.update(de.sid,de)}}function _t(we){if(!we)return;if(we instanceof Date)return we;let de=new Date(we);return Number.isNaN(de.getTime())?void 0:de}function rn(we){let de=we.tokens;if(!de?.access_token||!de.id_token||!de.token_type)return;return de}async function qt(we,de=!1){let Se=Ot(),ke=Ze("session",we);if(!ke)return{tokens:void 0,refreshHeaders:[]};let Ce=await Se.get(ke);if(Ce&&fe.tenantId&&Ce.tenantId&&Ce.tenantId!==fe.tenantId)return{tokens:void 0,refreshHeaders:We(),sid:ke};if(Ce?.authType!=="sso")return{tokens:void 0,refreshHeaders:We(),sid:ke};let Ue=rn(Ce);if(!Ue)return{tokens:void 0,refreshHeaders:We(),sid:ke};let _e=_t(Ce.expiresAt);if(_e?Date.now()>_e.getTime():!1)return await Se.delete(ke),{tokens:void 0,sid:ke,refreshHeaders:We()};let je=_t(Ue.expires),Ee=je?Date.now()>je.getTime():!0;if((de||Ee)&&Ue.refresh_token)return zt(we,ke,Ce,Ue);return{tokens:Ue,sid:ke,session:Ce,refreshHeaders:Ge(we)}}function zt(we,de,Se,ke){let Ce=me.get(de);if(Ce)return Ce;let Ue=Ot(),_e=(async()=>{let Le=await tn(ke.refresh_token),{tokenExpiresAt:je,sessionExpiresAt:Ee}=St(Le);Le.expires=je.toISOString();let Ke=await pt(Le,void 0,Ee),be=Ke.sso.profile,he=Pt(32),ve={...Se,sid:he,tokens:Le,claims:be,expiresAt:Ee,createdAt:new Date};await Vt(Ue,ve);try{if($e<=0)await Ue.delete(de);else{let{refresh_token:Ie,...Ae}=ke;await Ue.update(de,{tokens:Ae,expiresAt:new Date(Date.now()+$e)})}}catch(Ie){E.warn("Failed to retire rotated SSO session record",{"ion.operation":"session.rotate","ion.outcome":"degraded"},Ie)}return{tokens:Le,sid:he,session:ve,refreshedUser:Ke,refreshHeaders:[["Set-Cookie",xt("session",he,Ee)],...await Ne(we,Ke,Ee)]}})();return me.set(de,_e),_e.finally(()=>{me.delete(de)})}async function Rt(we,de=!1){return qt(we,de)}async function At(we){let{tokens:de}=await Rt(we);if(!de)return;return de.access_token}function xt(we,de,Se,ke=fe.cookiesSameSite??"Strict"){if(!fe)throw Error("ionite SSO Manager not initialized");if(we=`${fe.cookiesPrefix}.${we}`,typeof de!=="string")de=btoa(JSON.stringify(de));let Ce;if(Se instanceof Date)Ce=`Expires=${Se.toUTCString()}`;else if(typeof Se==="number")Ce=`Max-Age=${Se}`;else throw Error("Invalid expires type",Se);if(de.length>4000)throw Error(`Error setting cookie: ${we}. Cookie length is: ${de.length}`);return`${we}=${de}; ${Ce}; Path=${fe.cookiesPath};${Bt(fe.cookiesDomain)} HttpOnly;${fe.cookiesSecure?" Secure;":""} SameSite=${ke};`}function jt(we){if(!fe)throw Error("ionite SSO Manager not initialized");return`${fe.cookiesPrefix}.${we}=; Max-Age=0; Path=${fe.cookiesPath};${Bt(fe.cookiesDomain)} HttpOnly;${fe.cookiesSecure?" Secure;":""} SameSite=${fe.cookiesSameSite};`}function Et(){return{path:fe.cookiesPath??"/",domain:fe.cookiesDomain,secure:fe.cookiesSecure!==!1,sameSite:fe.cookiesSameSite??"Strict"}}function We(){return[["Set-Cookie",jt("session")],["Set-Cookie",Nt(`${fe.cookiesPrefix}.profile`,Et())]]}function Ge(we){if(fe.displayCookie?.enabled===!0)return[];return an(we.headers.get("cookie"),fe.cookiesPrefix??"ion.sso",Et()).map((de)=>["Set-Cookie",de])}async function Ne(we,de,Se){return(await mn({cookieHeader:we.headers.get("cookie"),sessionStore:fe.sessionStore,cookiesPrefix:fe.cookiesPrefix??"ion.sso",authType:"sso",tenantId:fe.tenantId,expiresAt:Se,user:de,projector:fe.displayUser,displayCookie:fe.displayCookie,trim:fe.trimDisplayCookies,attr:Et()})).map((Ce)=>["Set-Cookie",Ce])}function Ze(we,de,Se=!1){if(!fe)throw Error("ionite SSO Manager not initialized");let ke=de.headers.get("cookie");if(!ke)return null;let Ce=`${fe.cookiesPrefix}.${we}`,Ue=ke.split(";").find((Ee)=>Ee.trim().startsWith(`${Ce}=`));if(!Ue)return null;let _e=Ue.indexOf("="),Le=Ue.slice(_e+1).trim();if(!Se)return Le;let je=atob(Le);return JSON.parse(je)}function ze(we){return`state_${we}`}async function Be(we,de){if(!fe)throw Error("ionite SSO Manager not initialized");let{loginUrl:Se,userUrl:ke,tokenUrl:Ce,refreshUrl:Ue,logoutUrl:_e,logoutBackChannelUrl:Le,jwksUrl:je,redirectUri:Ee}={...fe,...de},Ke=new URL(we.url).pathname;if(Ee){let be;try{be=new URL(Ee).pathname}catch{try{let he=new URL(we.url),ve=Ee.startsWith("//")?Ee.slice(1):Ee;be=new URL(ve,he.origin).pathname}catch{be=Ee.startsWith("/")?Ee:`/${Ee}`}}if(be===Ke)return ut(we)}if(Se===Ke)return Oe(we);if(ke===Ke){if((fe.userEndpoint??"full")==="off")return new Response("Not Found",{status:404,headers:Ge(we)});try{let{tokens:be,session:he,refreshedUser:ve,refreshHeaders:Ie}=await Rt(we);if(!be)return new Response("User not logged in",{status:401,headers:Ie});let Ae=ve??(he?.claims?gt(he.claims,be,_t(he.expiresAt)):void 0);if(!Ae)return new Response("User not logged in",{status:401,headers:Ie});let Me=await wt(Ae),Ve=`${fe.cookiesPrefix}.profile`,De=_t(he?.expiresAt),qe=fe.displayCookie?.enabled===!0&&De&&!Ze("profile",we)&&!Ie.some(([,Qe])=>Qe.startsWith(`${Ve}=`))?await Ne(we,Me,De):[],Ye=fe.userEndpoint==="display"?m(Me,fe.displayUser):Me;return new Response(JSON.stringify(Ye),{headers:[["Content-Type",s],...Ie,...qe]})}catch(be){if(Is(be))return new Response("User not logged in",{status:401});return E.error("Error resolving SSO user",{"ion.operation":"sso.user","ion.outcome":"degraded"},be),new Response(JSON.stringify({error:"auth_unavailable"}),{status:503,headers:r})}}if(Ce===Ke){let{tokens:be,refreshHeaders:he}=await Rt(we);if(!be)return new Response("User not logged in",{status:401,headers:he});return new Response(JSON.stringify({token:be.access_token,expires:be.expires}),{headers:[["Content-Type",s],...he]})}if(Ue===Ke){let{tokens:be,refreshHeaders:he}=await Rt(we,!0);if(!be)return new Response("User not logged in",{status:401});return new Response("Refresh Complete",{status:200,headers:he})}if(_e===Ke)return rt(we);if(Le===Ke)return ot(we);if(je===Ke){let be=await ln();return new Response(JSON.stringify(be),{headers:[["Content-Type",s]]})}return new Response("Not Found",{status:404})}return{...fe,getUser:He,resolveUser:it,getJwt:At,initiateLogin:Oe,logout:rt,logoutBackChannel:ot,callbackHandler:ut,handler:Be}}function jo(T){let E={},M=T.split(";");for(let J of M){let ue=J.trim();if(!ue)continue;let pe=ue.indexOf("=");if(pe===-1)continue;let me=ue.slice(0,pe).trim(),ge=ue.slice(pe+1).trim();E[me]=ge}return E}function Is(T){if(!(T instanceof Error))return!1;return["Public key not found","Invalid JWT","Invalid JWT signature","ID token expired","ID token issuer mismatch","ID token audience mismatch","ID token nonce mismatch","ID token missing exp","invalid_grant"].some((E)=>T.message.includes(E))}function Ts(T){return T=T??"SSO Unavailable",new Response(JSON.stringify({error:T}),{status:503,statusText:T,headers:r})}var zn="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.";async function Lo(T,E){return t(E,zn),E.sso?.getUser(T)}async function Dr(T,E){return t(E,zn),await E.sso?.resolveUser(T)??{status:"unauthenticated"}}async function No(T,E){t(E,zn);let M=E.sso;if(!M)return Ts();return M.initiateLogin(T)}async function $o(T,E){t(E,zn);let M=E.sso;if(!M)return Ts();return M.callbackHandler(T)}var _r="tenant.owner",Or="tenant.owner.",Wo="tenant:";function Vo(T){return{id:_r,name:"Tenant owner",description:"Administer one tenant resource",requestable:!1,permissionTypes:["Admin"],resourceTypes:["tenant"],assignableSubjectTypes:["customer"],...T}}function jr(T){let E=T.trim();if(!E)throw Error("tenantId is required");return`${Wo}${E}`}function qo(T){let E=T.trim();if(!E)throw Error("tenantId is required");return`${Or}${E}`}function ft(T){return{allow:!1,reason:T,response(){if(T==="not_found")return Response.json({error:"Not Found"},{status:404});if(T==="forbidden")return Response.json({error:"Forbidden"},{status:403});if(T==="unavailable")return Response.json({error:"Tenant runtime unavailable"},{status:503});return Response.json({error:"Unauthorized"},{status:401})}}}function Bn(T,E){if(!T.id)return ft("unavailable");return{allow:!0,session:{id:T.id,email:T.email,name:T.name,kind:E}}}function xs(T){return T==="access_index_not_configured"||T==="error"}async function Ps(T,E){let M;try{M=await En(T,E.rootIon)}catch{return ft("unavailable")}if(M.status==="degraded")return ft("unavailable");if(M.status==="unauthenticated")return ft("unauthenticated");if(!M.value.id)return ft("unavailable");try{let J=await E.rootIon.authz.hasPermission(M.value.id,E.ownerPermission??_r,jr(E.tenantId),"customer");if(J.allow)return Bn(M.value,"owner");return ft(xs(J.metadata?.reason)?"unavailable":"forbidden")}catch{return ft("unavailable")}}async function zo(T,E){let{tenantIon:M}=E;if(!M)return ft("not_found");if(M.isReady()){let ue;try{ue=await Dr(T,M)}catch{return ft("unavailable")}if(ue.status==="degraded")return ft("unavailable");if(ue.status==="authenticated"){if(!ue.value.id)return ft("unavailable");if(!E.permission)return Bn(ue.value,"sso");try{let pe=await M.authz.hasPermission(ue.value.id,E.permission,void 0,"user");if(pe.allow)return Bn(ue.value,"sso");return ft(xs(pe.metadata?.reason)?"unavailable":"forbidden")}catch{return ft("unavailable")}}if(E.allowTenantCustomer){let pe;try{pe=await En(T,M)}catch{return ft("unavailable")}if(pe.status==="degraded")return ft("unavailable");if(pe.status==="authenticated"){if(!pe.value.id)return ft("unavailable");return Bn(pe.value,"customer")}}}let J=await Ps(T,E);if(J.allow||J.reason==="unavailable")return J;if(!M.isReady())return ft("unavailable");return ft("unauthenticated")}async function Bo(T,E){let M=T.authz.accessStore;if(!M)throw Error("Cannot list owned tenants: no AccessAssignmentStore is wired.");let J=new Set;for await(let ue of c((pe,me)=>M.listBySubject(E,"customer",{start:pe,limit:me}))){let pe=typeof ue.target==="string"?ue.target:ue.target.id;if(ue.targetType!=="group"||!pe.startsWith(Or))continue;let me=pe.slice(Or.length);if(!me||!ue.resources?.includes(jr(me)))continue;J.add(me)}return[...J].sort()}function Ko(T,E){let M=E.redirectTo.trim()||"/",J=E.tenantIon?.sso?.isReady?.()===!0?`${E.tenantIonBasePath?.(T)??`/api/${encodeURIComponent(T)}/ionite`}/auth/login`:E.fallbackPath,ue=new URL(J,"http://localhost");return ue.searchParams.set("redirect",M),`${ue.pathname}${ue.search}`}export{Rn as CACHE_BOUNDS,Wr as CIAM_PROVIDER_PRESETS,X as CatalogAdjacencyCache,Re as InMemoryTenantStore,_r as TENANT_OWNER_PERMISSION,hi as allowHosts,yi as allowOrigins,rs as allowRelativePaths,ss as allowSameOrigin,ms as assertSubjectTypeAssignable,Qr as assertTrustedIdTokenClaims,wr as baseCustomerToScim,kr as baseUserToScimUser,Sr as baseWorkloadToScim,ns as blockDangerousUrls,ur as buildAuthorizationUrl,Er as buildLfvSigningInput,$o as callback,Si as captureRedirect,vi as ciam,li as clearDiscoveryCache,ti as clearJwksCache,xe as collectReferencedDefinitions,Ys as configureJwksCache,ki as defaultRedirectPolicies,pr as discoverOidcEndpoints,As as discoverSessionRecords,Rs as discoverSessions,hr as entitlementToScimGroup,dr as exchangeAuthorizationCode,Z as expandRoot,mr as fetchUserInfo,Nt as formatDisplayClearCookie,Qn as formatDisplaySetCookie,fr as generateAppleClientSecret,go as generateLfvEd25519KeyPair,or as getCachedVerificationKey,Ri as getCustomer,Po as getDiscoveredSessionUsers,gn as getJwks,Bo as getOwnedTenantIds,Hn as getProviderPreset,si as getPublicKeyForKid,ri as getPublicKeyFromJwks,Lo as getUser,ar as getVerificationKeyForKid,Ls as has,qs as hasAll,Ks as hasAllScope,Vs as hasAny,Bs as hasAnyScope,Ws as hasGroup,Ns as hasPermission,$s as hasRole,zs as hasScope,oo as iam,No as initiateLogin,is as isRedirectAllowed,Oo as listSsoClientIdsFromCookies,hn as normalizeOidcIssuer,Yn as orderedEnabledProviders,fs as parseLfvJwks,kn as pkceChallengeFromVerifier,Fs as planDiscoveredTenantCookies,an as planDisplayCookieClear,mn as planDisplayCookieHeaders,le as reconcileSubjectAccess,Gt as resolveAfterRedirect,yo as resolveCacheConfig,wi as resolveCapturedRedirect,Tn as resolveCiamProvider,En as resolveCustomer,ni as resolveJwkForKid,gs as resolveJwksCacheConfig,Fn as resolveProviderBranding,yr as resolveRedirect,ys as resolveSessionCacheConfig,Ps as resolveTenantOwner,zo as resolveTenantSession,Dr as resolveUser,gr as sameOriginRedirectRules,zr as selectDisplayCookies,Fe as sendTenantWebhook,di as setDiscoveryClock,Xs as setJwksClock,Zs as setJwksRetry,wo as signCompactJwt,fo as signLfvPayload,_o as sso,So as staticSigningKeyRing,uo as stringifyLfvJwks,Ko as tenantAccessLoginUrl,qo as tenantOwnerEntitlementId,Vo as tenantOwnerPermission,jr as tenantResourceId,Co as verifyCompactJwt,Kt as verifyIdToken,mo as verifyLfvSignature,lr as verifyLogoutToken,Mo as verifyUser,Yt as withSetCookies};