@ionite/core 0.0.23-beta.20260825.2 → 0.0.23-beta.20260828.1

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/index.d.ts CHANGED
@@ -2734,6 +2734,18 @@ type SSOConfig<
2734
2734
  * @default 60
2735
2735
  */
2736
2736
  rotationGraceSeconds?: number;
2737
+ /**
2738
+ * Fallback session window (seconds) used ONLY when the IdP's token response carries a
2739
+ * `refresh_token` but no `refresh_expires_in`. An IdP-provided `refresh_expires_in` ALWAYS wins —
2740
+ * this value never overrides it. `refresh_expires_in` is a Keycloak extension (standard OAuth
2741
+ * token responses carry no refresh-token expiry field), so for IdPs that omit it this bounds the
2742
+ * session cookie expiry and the session-store TTL. It re-arms on every successful refresh, so it
2743
+ * behaves as an idle window, not a max session lifetime. Ops-governed (ConfigSource); no upper
2744
+ * clamp (deliberate: windows longer than the default are honored); non-numeric or `< 1` values
2745
+ * fall back to the default.
2746
+ * @default 86400
2747
+ */
2748
+ sessionWindowSeconds?: number;
2737
2749
  } & SSOHandlerConfig;
2738
2750
  type StateCookie = {
2739
2751
  state: string;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{A as T0,B as A0,C as O0,D as _0,E as k0,F as f0,G as v0,H as w0,I as g0,J as y0,K as h0,L as p0,M as c0,N as m0,O as d0,P as u0,Q as l0,R as o0,U as a0,V as n0,W as i0,X as s0,Y as r0,Z as t0,a as H0,b as G0,c as F0,d as q0,e as j0,f as U0,g as z0,h as Y0,i as K0,j as W0,k as C0,l as M0,m as D0,n as P0,o as x0,t as b0,u as R0,v as L0,w as S0,x as E0,y as I0,z as N0}from"./shared/core-15896f6h.js";var f="0.0.23-beta.20260825.2";class Y extends Error{kind;recoverable;code;status;path;sourceType;constructor(J,X){super(J,X.cause!==void 0?{cause:X.cause}:void 0);this.name="ConfigSourceError",this.kind=X.kind,this.recoverable=X.recoverable,this.code=X.code,this.status=X.status,this.path=X.path,this.sourceType=X.sourceType,Object.setPrototypeOf(this,Y.prototype)}}function v(J){return J instanceof Y}var F=["workload"],W={id:"ion:iam:read",name:"Read Identities (SCIM)",description:"Authorizes a workload to list and read Users and Groups via the SCIM endpoints.",requestable:!1,permissionTypes:["DataRead"],assignableSubjectTypes:F,recommendedSubjectTypes:F},C={id:"ion:iam:users:write",name:"Manage Identities (SCIM Users)",description:"Authorizes a workload to create, replace, modify (including attribute changes), and delete Users via SCIM, including access-root revocation on user delete.",requestable:!1,permissionTypes:["DataCreate","DataWrite","DataDelete"],assignableSubjectTypes:F,recommendedSubjectTypes:F},M={id:"ion:iam:groups:write",name:"Manage Groups & Access (SCIM Groups)",description:"Authorizes a workload to create, replace, modify, and delete Groups via SCIM, including membership changes that grant or revoke entitlements.",requestable:!1,permissionTypes:["DataCreate","DataWrite","DataDelete"],assignableSubjectTypes:F,recommendedSubjectTypes:F},D={id:"ion:capabilitiez:read",name:"Read Capability Manifest",description:"Authorizes a workload to read the capability manifest at the capabilitiez endpoint (only when RemoteConfig.capabilitiez is enabled).",requestable:!1,permissionTypes:["DataRead"],assignableSubjectTypes:F,recommendedSubjectTypes:F},P={id:"ion:ciam:magic-link:create",name:"Issue CIAM Magic Links",description:"Authorizes a caller to mint customer magic-link login credentials via the magic-link endpoint. Grant narrowly.",requestable:!1,permissionTypes:["DataCreate"],assignableSubjectTypes:["workload","user"],recommendedSubjectTypes:F},x={id:"ion:authz:oaa:sync",name:"Trigger OAA Full Sync",description:"Authorizes a workload (Ops/ECI client) to trigger a full OAA reconcile via the authz OAA sync endpoint (only when RemoteConfig.authz.oaa.fullSync.enabled is true).",requestable:!1,permissionTypes:["DataWrite"],assignableSubjectTypes:F,recommendedSubjectTypes:F},b={id:"ion:tenant:manage",name:"Manage Tenants",description:"Authorizes a workload (ECI/TMS client) to create, read, update, and delete tenant records via the tenant-management endpoints.",requestable:!1,permissionTypes:["DataCreate","DataRead","DataWrite","DataDelete"],assignableSubjectTypes:F,recommendedSubjectTypes:F},w=[W,C,M,D,P,x,b],g={"iam.read":{permission:W,subjectType:["workload"]},"iam.users.write":{permission:C,subjectType:["workload"]},"iam.groups.write":{permission:M,subjectType:["workload"]},"capabilitiez.read":{permission:D,subjectType:["workload"]},"ciam.magic-link.create":{permission:P,subjectType:["workload","user"]},"authz.oaa.sync":{permission:x,subjectType:["workload"]},"tenant.manage":{permission:b,subjectType:["workload"]}};var y=["sessionStore","userStore","customerStore","accessStore","tokenStore","magicLinkStore"];function S(J){if(J===null||typeof J!=="object")return J;let X={};for(let[Q,$]of Object.entries(J)){if(y.includes(Q)||Q==="validators"||Q==="setStores")continue;X[Q]=$!==null&&typeof $==="object"&&!Array.isArray($)&&Object.getPrototypeOf($)===Object.prototype?S($):$}return X}function h(J){return S(J)}function K(J,X){if(!J||typeof J!=="object"||Array.isArray(J))throw Error(`${X} must be an object.`);return J}function j(J,X){if(J===void 0)return;if(typeof J!=="string"||J.length===0||!Number.isFinite(Date.parse(J)))throw Error(`${X} must be a valid timestamp string.`);return J}function E(J,X,Q){if(!Array.isArray(J)||!Q.allowEmpty&&J.length===0)throw Error(`${X} keys must be ${Q.allowEmpty?"an":"a non-empty"} array.`);let $=new Set;return J.map((Z,B)=>{let V=K(Z,`${X} keys[${B}]`);if(typeof V.id!=="string"||V.id.length===0)throw Error(`${X} keys[${B}].id must be a non-empty string.`);if($.has(V.id))throw Error(`${X} contains duplicate key id "${V.id}".`);if($.add(V.id),!["pending","active","deprecated","rotated","revoked"].includes(String(V.state)))throw Error(`${X} keys[${B}].state is invalid.`);if(V.value!==void 0&&(typeof V.value!=="string"||V.value.length===0))throw Error(`${X} keys[${B}].value must be a non-empty string when present.`);let G=V.meta===void 0?void 0:K(V.meta,`${X} keys[${B}].meta`);return{id:V.id,state:V.state,...V.value===void 0?{}:{value:V.value},...V.notBefore===void 0?{}:{notBefore:j(V.notBefore,`${X} keys[${B}].notBefore`)},...V.notAfter===void 0?{}:{notAfter:j(V.notAfter,`${X} keys[${B}].notAfter`)},...V.createdAt===void 0?{}:{createdAt:j(V.createdAt,`${X} keys[${B}].createdAt`)},...V.activatedAt===void 0?{}:{activatedAt:j(V.activatedAt,`${X} keys[${B}].activatedAt`)},...V.deprecatedAt===void 0?{}:{deprecatedAt:j(V.deprecatedAt,`${X} keys[${B}].deprecatedAt`)},...V.rotatedAt===void 0?{}:{rotatedAt:j(V.rotatedAt,`${X} keys[${B}].rotatedAt`)},...V.revokedAt===void 0?{}:{revokedAt:j(V.revokedAt,`${X} keys[${B}].revokedAt`)},...G?{meta:{...G}}:{}}})}function p(J,X,Q){if(J===void 0)return;if(!Array.isArray(J))throw Error(`${Q} slots must be an array.`);let $=new Set,Z=J.map((B,V)=>{if(B===null)return null;if(typeof B!=="string"||B.length===0)throw Error(`${Q} slots[${V}] must be a non-empty key id or null.`);if($.has(B))throw Error(`${Q} slots contain duplicate key id "${B}".`);$.add(B);let G=X.find((H)=>H.id===B);if(!G)throw Error(`${Q} slot key "${B}" is not present in keys.`);if(G.state!=="active")throw Error(`${Q} slot key "${B}" must have state "active".`);if(!G.value)throw Error(`${Q} slot key "${B}" must include a value.`);return B});if(X.length===0&&Z.some((B)=>B!==null))throw Error(`${Q} slots must be omitted or all-null when keys is empty.`);return Z}function c(J){let Q=K(J,"KMS pool");if(Q.kind!=="kms")throw Error('KMS pool kind must be "kms".');let $=E(Q.keys,"KMS pool",{allowEmpty:!0}),Z=p(Q.slots,$,"KMS pool");return Z?{kind:"kms",slots:Z,keys:$}:{kind:"kms",keys:$}}function m(J){let Q=K(J,"KMS pool control document");if(Q.kind!=="kms")throw Error('KMS pool control document kind must be "kms".');return{kind:"kms",keys:E(Q.keys,"KMS pool control document",{allowEmpty:!0})}}var I={trace:()=>{},debug:()=>{},info:()=>{},warn:()=>{},error:()=>{}},d=I,u={trace:()=>{},debug:console.debug,info:console.info,warn:console.warn,error:console.error},l={trace:()=>{},debug:()=>{},info:console.info,warn:console.warn,error:console.error},o={trace:()=>{},debug:()=>{},info:()=>{},warn:console.warn,error:console.error};function a(J,X){if(typeof X!=="number"||X<=0)return J;return new Promise((Q,$)=>{let Z=setTimeout(()=>{$(Error(`Authz catalog entry did not become ready within ${X}ms`))},X);J.then(()=>{clearTimeout(Z),Q()},(B)=>{clearTimeout(Z),$(B)})})}function n(J,X){let Q=!1,$,Z=X.then(()=>{Q=!0},(V)=>{Q=!1,$=V}),B=J;return Object.defineProperty(B,"ready",{enumerable:!1,configurable:!0,value:(V)=>a(Z.then(()=>{if(!Q)throw $}),V)}),Object.defineProperty(B,"isReady",{enumerable:!1,configurable:!0,value:()=>Q}),B}var R=Object.freeze({jsonc:"application/json",env:"text/x-dotenv",text:"text/plain",binary:"application/octet-stream",yaml:"application/yaml",toml:"application/toml",xml:"application/xml"});function L(J){if(!J.id.trim())throw Error("defineSecretType: id is required");let X=J.mimeType?.trim()||R[J.format],Q=Object.freeze({id:J.id,...J.label?{label:J.label}:{},format:J.format,mimeType:X,...J.schemaUrl?{schemaUrl:J.schemaUrl}:{},typeId:J.id});return Object.freeze({id:J.id,...J.label?{label:J.label}:{},format:J.format,mimeType:X,...J.schemaUrl?{schemaUrl:J.schemaUrl}:{},...J.schema?{schema:J.schema}:{},toRegistryEntry:()=>Q})}function i(J="jsonc"){return{format:J,mimeType:R[J],typeId:J}}class N extends Error{expected;received;constructor(J,X){super(`Secret content type mismatch: expected "${J.mimeType}" (${J.format}) but received "${X.mimeType}" (${X.format})`);this.name="SecretContentTypeMismatchError",this.expected=J,this.received=X}}var s=L({id:"ionite-remote-config",label:"ionite RemoteConfig",format:"jsonc",mimeType:"application/vnd.ionite.remote-config+json",schemaUrl:"https://ionite.com/schemas/remote-config.json"});var A={beforeTenantSegments:["ui"]},O={beforeTenantSegments:["api"]};function T(J){return(J??[]).map((X)=>X.trim()).filter(Boolean)}function r(J){let X=J.trim();if(!X)return"/";let Q=X.replace(/\\/g,"/").replace(/\/+/g,"/");return Q.startsWith("/")?Q:`/${Q}`}function _(J){return r(J).split("/").filter(Boolean)}function z(J){return{beforeTenantSegments:T(J?.beforeTenantSegments),afterTenantSegments:T(J?.afterTenantSegments)}}function t(J){return{type:"path",ui:z(J?.ui??A),api:z(J?.api??O)}}function e(J,X){let Q=z(X),$=Q.beforeTenantSegments??[],Z=Q.afterTenantSegments??[],B=_(J),V=$.length+1+Z.length;if(B.length<V)return null;for(let q=0;q<$.length;q++)if(B[q]!==$[q])return null;let G=$.length,H=B[G];if(!H)return null;for(let q=0;q<Z.length;q++)if(B[G+1+q]!==Z[q])return null;let U=B.slice(G+1+Z.length);return{id:decodeURIComponent(H),restSegments:U,restPath:U.length>0?`/${U.join("/")}`:"/"}}function J0(J,X="/",Q){let $=z(Q),Z=$.beforeTenantSegments??[],B=$.afterTenantSegments??[],V=_(X),G=[...Z,encodeURIComponent(J),...B,...V];return G.length>0?`/${G.join("/")}`:"/"}function Q0(J){return{"~standard":{version:1,vendor:J,validate:(X)=>{if(typeof X!=="object"||X===null)return{issues:[{message:"Expected an object"}]};let Q=X,$=[],Z={...Q},B=["iss","sub"];for(let H of B)if(H in Q){if(typeof Q[H]!=="string")$.push({message:`${H} must be a string`,path:[H]})}else $.push({message:`${H} is required`,path:[H]});if("aud"in Q&&Q.aud!==void 0){let H=Q.aud;if(typeof H!=="string"&&!Array.isArray(H))$.push({message:"aud must be a string or array of strings",path:["aud"]});else if(Array.isArray(H)&&!H.every((U)=>typeof U==="string"))$.push({message:"aud array must contain only strings",path:["aud"]})}let V=["jti","scope"];for(let H of V)if(H in Q&&Q[H]!==void 0){if(typeof Q[H]!=="string")$.push({message:`${H} must be a string`,path:[H]})}let G=["exp","iat"];for(let H of G)if(H in Q){if(typeof Q[H]!=="number")$.push({message:`${H} must be a number`,path:[H]})}else $.push({message:`${H} is required`,path:[H]});if($.length>0)return{issues:$};return{value:Z}}}}}function X0(J){return{"~standard":{version:1,vendor:J,validate:(X)=>{if(typeof X!=="object"||X===null)return{issues:[{message:"Expected an object"}]};let Q=X,$=[],Z={};if("access_token"in Q)if(typeof Q.access_token==="string")Z.access_token=Q.access_token;else $.push({message:"access_token must be a string",path:["access_token"]});else $.push({message:"access_token is required",path:["access_token"]});if("token_type"in Q)if(typeof Q.token_type==="string")Z.token_type=Q.token_type;else $.push({message:"token_type must be a string",path:["token_type"]});else $.push({message:"token_type is required",path:["token_type"]});if("scope"in Q)if(typeof Q.scope==="string"||Q.scope===void 0)Z.scope=Q.scope;else $.push({message:"scope must be a string",path:["scope"]});if("refresh_token"in Q)if(typeof Q.refresh_token==="string"||Q.refresh_token===void 0)Z.refresh_token=Q.refresh_token;else $.push({message:"refresh_token must be a string",path:["refresh_token"]});if("expires"in Q)if(typeof Q.expires==="string"||Q.expires===void 0)Z.expires=Q.expires;else $.push({message:"expires must be a string",path:["expires"]});if("expires_in"in Q)if(typeof Q.expires_in==="number"||Q.expires_in===void 0)Z.expires_in=Q.expires_in;else $.push({message:"expires_in must be a number",path:["expires_in"]});if($.length>0)return{issues:$};return{value:Z}}}}}function $0(J){let X=new Uint8Array(J);return crypto.getRandomValues(X),X}function B0(J){let X="",Q=$0(J);for(let $=0;$<J;$++){let Z=Q[$]%32;X+="0123456789ABCDEFGHJKMNPQRSTVWXYZ".charAt(Z)}return X}function V0(J,X){let Q="";for(let $=X;$>0;$--){let Z=J%32;Q="0123456789ABCDEFGHJKMNPQRSTVWXYZ".charAt(Z)+Q,J=Math.floor(J/32)}return Q}function Z0(J){let X=Date.now(),Q=V0(X,10),$=B0(16);return`${J??""}${Q}${$}`}export{X0 as workloadTokenResponseSchema,O0 as withValidate,o as warnLogger,p0 as waitOn,f as version,k0 as validationFailureResponse,r0 as userSchema,D0 as unionCatalogRead,H0 as trustedClientPermissionsForPrincipal,g0 as trimTrailingSlash,T0 as tokenResponseSchema,U0 as toCodeCatalog,v0 as stripJsonComments,h0 as stableConfigHash,I as silentLogger,h as serializeConfig,s as remoteConfigSecretType,n as readyCatalogEntry,c as parseKmsPoolDocument,m as parseKmsPoolControlDocument,w0 as parseJsonc,E0 as parseEcid,N0 as oidcCallbackSchema,t as normalizeTenantRoutingStrategy,z as normalizeTenantPathNamespace,_0 as must,f0 as mergeConfig,W0 as mergeCodeCatalogEntity,C0 as materializeCodeCatalogEntity,e as matchTenantPath,q0 as listGenerator,F0 as list,Q0 as jwtAssertionClaimsSchema,u0 as isStoreConflictError,L0 as isEcid,v as isConfigSourceError,o0 as isConfigLocator,j0 as isCodeCatalog,l as infoLogger,A0 as idTokenClaimsSchema,t0 as groupResourceSchema,Y0 as getCodeCatalogEntity,Z0 as generateULID,S0 as formatEcid,M0 as deprecateRetiredCodeCatalogRows,L as defineSecretType,z0 as defineCatalog,i as defaultSecretContentType,d as defaultLogger,y0 as deepEqualPlain,m0 as decodeUser,u as debugLogger,G0 as configTrustedClientGrants,c0 as claimsToUser,K0 as catalogEntityStore,J0 as buildTenantPath,i0 as assertValidSubjectTypeScoping,I0 as assertEcid,x0 as accessRootId,P0 as accessRefId,d0 as StoreConflictError,N as SecretContentTypeMismatchError,n0 as PLATFORM_ASSIGNABLE_SUBJECT_TYPES,l0 as IoniteError,b as ION_TENANT_MANAGE,w as ION_SDK_PERMISSIONS,s0 as ION_SCIM_USER_EXTENSION_URN,C as ION_IAM_USERS_WRITE,W as ION_IAM_READ,M as ION_IAM_GROUPS_WRITE,g as ION_ENDPOINT_PERMISSIONS,P as ION_CIAM_MAGIC_LINK_CREATE,D as ION_CAPABILITIEZ_READ,x as ION_AUTHZ_OAA_SYNC,a0 as ION_AUTHZ_GROUP_SCHEMA,R0 as EcidFormatError,b0 as ECID_SCHEME,A as DEFAULT_TENANT_UI_NAMESPACE,O as DEFAULT_TENANT_API_NAMESPACE,R as DEFAULT_SECRET_MIME_TYPES,Y as ConfigSourceError};
1
+ import{A as T0,B as A0,C as O0,D as _0,E as k0,F as f0,G as v0,H as w0,I as g0,J as y0,K as h0,L as p0,M as c0,N as m0,O as d0,P as u0,Q as l0,R as o0,U as a0,V as n0,W as i0,X as s0,Y as r0,Z as t0,a as H0,b as G0,c as F0,d as q0,e as j0,f as U0,g as z0,h as Y0,i as K0,j as W0,k as C0,l as M0,m as D0,n as P0,o as x0,t as b0,u as R0,v as L0,w as S0,x as E0,y as I0,z as N0}from"./shared/core-15896f6h.js";var f="0.0.23-beta.20260828.1";class Y extends Error{kind;recoverable;code;status;path;sourceType;constructor(J,X){super(J,X.cause!==void 0?{cause:X.cause}:void 0);this.name="ConfigSourceError",this.kind=X.kind,this.recoverable=X.recoverable,this.code=X.code,this.status=X.status,this.path=X.path,this.sourceType=X.sourceType,Object.setPrototypeOf(this,Y.prototype)}}function v(J){return J instanceof Y}var F=["workload"],W={id:"ion:iam:read",name:"Read Identities (SCIM)",description:"Authorizes a workload to list and read Users and Groups via the SCIM endpoints.",requestable:!1,permissionTypes:["DataRead"],assignableSubjectTypes:F,recommendedSubjectTypes:F},C={id:"ion:iam:users:write",name:"Manage Identities (SCIM Users)",description:"Authorizes a workload to create, replace, modify (including attribute changes), and delete Users via SCIM, including access-root revocation on user delete.",requestable:!1,permissionTypes:["DataCreate","DataWrite","DataDelete"],assignableSubjectTypes:F,recommendedSubjectTypes:F},M={id:"ion:iam:groups:write",name:"Manage Groups & Access (SCIM Groups)",description:"Authorizes a workload to create, replace, modify, and delete Groups via SCIM, including membership changes that grant or revoke entitlements.",requestable:!1,permissionTypes:["DataCreate","DataWrite","DataDelete"],assignableSubjectTypes:F,recommendedSubjectTypes:F},D={id:"ion:capabilitiez:read",name:"Read Capability Manifest",description:"Authorizes a workload to read the capability manifest at the capabilitiez endpoint (only when RemoteConfig.capabilitiez is enabled).",requestable:!1,permissionTypes:["DataRead"],assignableSubjectTypes:F,recommendedSubjectTypes:F},P={id:"ion:ciam:magic-link:create",name:"Issue CIAM Magic Links",description:"Authorizes a caller to mint customer magic-link login credentials via the magic-link endpoint. Grant narrowly.",requestable:!1,permissionTypes:["DataCreate"],assignableSubjectTypes:["workload","user"],recommendedSubjectTypes:F},x={id:"ion:authz:oaa:sync",name:"Trigger OAA Full Sync",description:"Authorizes a workload (Ops/ECI client) to trigger a full OAA reconcile via the authz OAA sync endpoint (only when RemoteConfig.authz.oaa.fullSync.enabled is true).",requestable:!1,permissionTypes:["DataWrite"],assignableSubjectTypes:F,recommendedSubjectTypes:F},b={id:"ion:tenant:manage",name:"Manage Tenants",description:"Authorizes a workload (ECI/TMS client) to create, read, update, and delete tenant records via the tenant-management endpoints.",requestable:!1,permissionTypes:["DataCreate","DataRead","DataWrite","DataDelete"],assignableSubjectTypes:F,recommendedSubjectTypes:F},w=[W,C,M,D,P,x,b],g={"iam.read":{permission:W,subjectType:["workload"]},"iam.users.write":{permission:C,subjectType:["workload"]},"iam.groups.write":{permission:M,subjectType:["workload"]},"capabilitiez.read":{permission:D,subjectType:["workload"]},"ciam.magic-link.create":{permission:P,subjectType:["workload","user"]},"authz.oaa.sync":{permission:x,subjectType:["workload"]},"tenant.manage":{permission:b,subjectType:["workload"]}};var y=["sessionStore","userStore","customerStore","accessStore","tokenStore","magicLinkStore"];function S(J){if(J===null||typeof J!=="object")return J;let X={};for(let[Q,$]of Object.entries(J)){if(y.includes(Q)||Q==="validators"||Q==="setStores")continue;X[Q]=$!==null&&typeof $==="object"&&!Array.isArray($)&&Object.getPrototypeOf($)===Object.prototype?S($):$}return X}function h(J){return S(J)}function K(J,X){if(!J||typeof J!=="object"||Array.isArray(J))throw Error(`${X} must be an object.`);return J}function j(J,X){if(J===void 0)return;if(typeof J!=="string"||J.length===0||!Number.isFinite(Date.parse(J)))throw Error(`${X} must be a valid timestamp string.`);return J}function E(J,X,Q){if(!Array.isArray(J)||!Q.allowEmpty&&J.length===0)throw Error(`${X} keys must be ${Q.allowEmpty?"an":"a non-empty"} array.`);let $=new Set;return J.map((Z,B)=>{let V=K(Z,`${X} keys[${B}]`);if(typeof V.id!=="string"||V.id.length===0)throw Error(`${X} keys[${B}].id must be a non-empty string.`);if($.has(V.id))throw Error(`${X} contains duplicate key id "${V.id}".`);if($.add(V.id),!["pending","active","deprecated","rotated","revoked"].includes(String(V.state)))throw Error(`${X} keys[${B}].state is invalid.`);if(V.value!==void 0&&(typeof V.value!=="string"||V.value.length===0))throw Error(`${X} keys[${B}].value must be a non-empty string when present.`);let G=V.meta===void 0?void 0:K(V.meta,`${X} keys[${B}].meta`);return{id:V.id,state:V.state,...V.value===void 0?{}:{value:V.value},...V.notBefore===void 0?{}:{notBefore:j(V.notBefore,`${X} keys[${B}].notBefore`)},...V.notAfter===void 0?{}:{notAfter:j(V.notAfter,`${X} keys[${B}].notAfter`)},...V.createdAt===void 0?{}:{createdAt:j(V.createdAt,`${X} keys[${B}].createdAt`)},...V.activatedAt===void 0?{}:{activatedAt:j(V.activatedAt,`${X} keys[${B}].activatedAt`)},...V.deprecatedAt===void 0?{}:{deprecatedAt:j(V.deprecatedAt,`${X} keys[${B}].deprecatedAt`)},...V.rotatedAt===void 0?{}:{rotatedAt:j(V.rotatedAt,`${X} keys[${B}].rotatedAt`)},...V.revokedAt===void 0?{}:{revokedAt:j(V.revokedAt,`${X} keys[${B}].revokedAt`)},...G?{meta:{...G}}:{}}})}function p(J,X,Q){if(J===void 0)return;if(!Array.isArray(J))throw Error(`${Q} slots must be an array.`);let $=new Set,Z=J.map((B,V)=>{if(B===null)return null;if(typeof B!=="string"||B.length===0)throw Error(`${Q} slots[${V}] must be a non-empty key id or null.`);if($.has(B))throw Error(`${Q} slots contain duplicate key id "${B}".`);$.add(B);let G=X.find((H)=>H.id===B);if(!G)throw Error(`${Q} slot key "${B}" is not present in keys.`);if(G.state!=="active")throw Error(`${Q} slot key "${B}" must have state "active".`);if(!G.value)throw Error(`${Q} slot key "${B}" must include a value.`);return B});if(X.length===0&&Z.some((B)=>B!==null))throw Error(`${Q} slots must be omitted or all-null when keys is empty.`);return Z}function c(J){let Q=K(J,"KMS pool");if(Q.kind!=="kms")throw Error('KMS pool kind must be "kms".');let $=E(Q.keys,"KMS pool",{allowEmpty:!0}),Z=p(Q.slots,$,"KMS pool");return Z?{kind:"kms",slots:Z,keys:$}:{kind:"kms",keys:$}}function m(J){let Q=K(J,"KMS pool control document");if(Q.kind!=="kms")throw Error('KMS pool control document kind must be "kms".');return{kind:"kms",keys:E(Q.keys,"KMS pool control document",{allowEmpty:!0})}}var I={trace:()=>{},debug:()=>{},info:()=>{},warn:()=>{},error:()=>{}},d=I,u={trace:()=>{},debug:console.debug,info:console.info,warn:console.warn,error:console.error},l={trace:()=>{},debug:()=>{},info:console.info,warn:console.warn,error:console.error},o={trace:()=>{},debug:()=>{},info:()=>{},warn:console.warn,error:console.error};function a(J,X){if(typeof X!=="number"||X<=0)return J;return new Promise((Q,$)=>{let Z=setTimeout(()=>{$(Error(`Authz catalog entry did not become ready within ${X}ms`))},X);J.then(()=>{clearTimeout(Z),Q()},(B)=>{clearTimeout(Z),$(B)})})}function n(J,X){let Q=!1,$,Z=X.then(()=>{Q=!0},(V)=>{Q=!1,$=V}),B=J;return Object.defineProperty(B,"ready",{enumerable:!1,configurable:!0,value:(V)=>a(Z.then(()=>{if(!Q)throw $}),V)}),Object.defineProperty(B,"isReady",{enumerable:!1,configurable:!0,value:()=>Q}),B}var R=Object.freeze({jsonc:"application/json",env:"text/x-dotenv",text:"text/plain",binary:"application/octet-stream",yaml:"application/yaml",toml:"application/toml",xml:"application/xml"});function L(J){if(!J.id.trim())throw Error("defineSecretType: id is required");let X=J.mimeType?.trim()||R[J.format],Q=Object.freeze({id:J.id,...J.label?{label:J.label}:{},format:J.format,mimeType:X,...J.schemaUrl?{schemaUrl:J.schemaUrl}:{},typeId:J.id});return Object.freeze({id:J.id,...J.label?{label:J.label}:{},format:J.format,mimeType:X,...J.schemaUrl?{schemaUrl:J.schemaUrl}:{},...J.schema?{schema:J.schema}:{},toRegistryEntry:()=>Q})}function i(J="jsonc"){return{format:J,mimeType:R[J],typeId:J}}class N extends Error{expected;received;constructor(J,X){super(`Secret content type mismatch: expected "${J.mimeType}" (${J.format}) but received "${X.mimeType}" (${X.format})`);this.name="SecretContentTypeMismatchError",this.expected=J,this.received=X}}var s=L({id:"ionite-remote-config",label:"ionite RemoteConfig",format:"jsonc",mimeType:"application/vnd.ionite.remote-config+json",schemaUrl:"https://ionite.com/schemas/remote-config.json"});var A={beforeTenantSegments:["ui"]},O={beforeTenantSegments:["api"]};function T(J){return(J??[]).map((X)=>X.trim()).filter(Boolean)}function r(J){let X=J.trim();if(!X)return"/";let Q=X.replace(/\\/g,"/").replace(/\/+/g,"/");return Q.startsWith("/")?Q:`/${Q}`}function _(J){return r(J).split("/").filter(Boolean)}function z(J){return{beforeTenantSegments:T(J?.beforeTenantSegments),afterTenantSegments:T(J?.afterTenantSegments)}}function t(J){return{type:"path",ui:z(J?.ui??A),api:z(J?.api??O)}}function e(J,X){let Q=z(X),$=Q.beforeTenantSegments??[],Z=Q.afterTenantSegments??[],B=_(J),V=$.length+1+Z.length;if(B.length<V)return null;for(let q=0;q<$.length;q++)if(B[q]!==$[q])return null;let G=$.length,H=B[G];if(!H)return null;for(let q=0;q<Z.length;q++)if(B[G+1+q]!==Z[q])return null;let U=B.slice(G+1+Z.length);return{id:decodeURIComponent(H),restSegments:U,restPath:U.length>0?`/${U.join("/")}`:"/"}}function J0(J,X="/",Q){let $=z(Q),Z=$.beforeTenantSegments??[],B=$.afterTenantSegments??[],V=_(X),G=[...Z,encodeURIComponent(J),...B,...V];return G.length>0?`/${G.join("/")}`:"/"}function Q0(J){return{"~standard":{version:1,vendor:J,validate:(X)=>{if(typeof X!=="object"||X===null)return{issues:[{message:"Expected an object"}]};let Q=X,$=[],Z={...Q},B=["iss","sub"];for(let H of B)if(H in Q){if(typeof Q[H]!=="string")$.push({message:`${H} must be a string`,path:[H]})}else $.push({message:`${H} is required`,path:[H]});if("aud"in Q&&Q.aud!==void 0){let H=Q.aud;if(typeof H!=="string"&&!Array.isArray(H))$.push({message:"aud must be a string or array of strings",path:["aud"]});else if(Array.isArray(H)&&!H.every((U)=>typeof U==="string"))$.push({message:"aud array must contain only strings",path:["aud"]})}let V=["jti","scope"];for(let H of V)if(H in Q&&Q[H]!==void 0){if(typeof Q[H]!=="string")$.push({message:`${H} must be a string`,path:[H]})}let G=["exp","iat"];for(let H of G)if(H in Q){if(typeof Q[H]!=="number")$.push({message:`${H} must be a number`,path:[H]})}else $.push({message:`${H} is required`,path:[H]});if($.length>0)return{issues:$};return{value:Z}}}}}function X0(J){return{"~standard":{version:1,vendor:J,validate:(X)=>{if(typeof X!=="object"||X===null)return{issues:[{message:"Expected an object"}]};let Q=X,$=[],Z={};if("access_token"in Q)if(typeof Q.access_token==="string")Z.access_token=Q.access_token;else $.push({message:"access_token must be a string",path:["access_token"]});else $.push({message:"access_token is required",path:["access_token"]});if("token_type"in Q)if(typeof Q.token_type==="string")Z.token_type=Q.token_type;else $.push({message:"token_type must be a string",path:["token_type"]});else $.push({message:"token_type is required",path:["token_type"]});if("scope"in Q)if(typeof Q.scope==="string"||Q.scope===void 0)Z.scope=Q.scope;else $.push({message:"scope must be a string",path:["scope"]});if("refresh_token"in Q)if(typeof Q.refresh_token==="string"||Q.refresh_token===void 0)Z.refresh_token=Q.refresh_token;else $.push({message:"refresh_token must be a string",path:["refresh_token"]});if("expires"in Q)if(typeof Q.expires==="string"||Q.expires===void 0)Z.expires=Q.expires;else $.push({message:"expires must be a string",path:["expires"]});if("expires_in"in Q)if(typeof Q.expires_in==="number"||Q.expires_in===void 0)Z.expires_in=Q.expires_in;else $.push({message:"expires_in must be a number",path:["expires_in"]});if($.length>0)return{issues:$};return{value:Z}}}}}function $0(J){let X=new Uint8Array(J);return crypto.getRandomValues(X),X}function B0(J){let X="",Q=$0(J);for(let $=0;$<J;$++){let Z=Q[$]%32;X+="0123456789ABCDEFGHJKMNPQRSTVWXYZ".charAt(Z)}return X}function V0(J,X){let Q="";for(let $=X;$>0;$--){let Z=J%32;Q="0123456789ABCDEFGHJKMNPQRSTVWXYZ".charAt(Z)+Q,J=Math.floor(J/32)}return Q}function Z0(J){let X=Date.now(),Q=V0(X,10),$=B0(16);return`${J??""}${Q}${$}`}export{X0 as workloadTokenResponseSchema,O0 as withValidate,o as warnLogger,p0 as waitOn,f as version,k0 as validationFailureResponse,r0 as userSchema,D0 as unionCatalogRead,H0 as trustedClientPermissionsForPrincipal,g0 as trimTrailingSlash,T0 as tokenResponseSchema,U0 as toCodeCatalog,v0 as stripJsonComments,h0 as stableConfigHash,I as silentLogger,h as serializeConfig,s as remoteConfigSecretType,n as readyCatalogEntry,c as parseKmsPoolDocument,m as parseKmsPoolControlDocument,w0 as parseJsonc,E0 as parseEcid,N0 as oidcCallbackSchema,t as normalizeTenantRoutingStrategy,z as normalizeTenantPathNamespace,_0 as must,f0 as mergeConfig,W0 as mergeCodeCatalogEntity,C0 as materializeCodeCatalogEntity,e as matchTenantPath,q0 as listGenerator,F0 as list,Q0 as jwtAssertionClaimsSchema,u0 as isStoreConflictError,L0 as isEcid,v as isConfigSourceError,o0 as isConfigLocator,j0 as isCodeCatalog,l as infoLogger,A0 as idTokenClaimsSchema,t0 as groupResourceSchema,Y0 as getCodeCatalogEntity,Z0 as generateULID,S0 as formatEcid,M0 as deprecateRetiredCodeCatalogRows,L as defineSecretType,z0 as defineCatalog,i as defaultSecretContentType,d as defaultLogger,y0 as deepEqualPlain,m0 as decodeUser,u as debugLogger,G0 as configTrustedClientGrants,c0 as claimsToUser,K0 as catalogEntityStore,J0 as buildTenantPath,i0 as assertValidSubjectTypeScoping,I0 as assertEcid,x0 as accessRootId,P0 as accessRefId,d0 as StoreConflictError,N as SecretContentTypeMismatchError,n0 as PLATFORM_ASSIGNABLE_SUBJECT_TYPES,l0 as IoniteError,b as ION_TENANT_MANAGE,w as ION_SDK_PERMISSIONS,s0 as ION_SCIM_USER_EXTENSION_URN,C as ION_IAM_USERS_WRITE,W as ION_IAM_READ,M as ION_IAM_GROUPS_WRITE,g as ION_ENDPOINT_PERMISSIONS,P as ION_CIAM_MAGIC_LINK_CREATE,D as ION_CAPABILITIEZ_READ,x as ION_AUTHZ_OAA_SYNC,a0 as ION_AUTHZ_GROUP_SCHEMA,R0 as EcidFormatError,b0 as ECID_SCHEME,A as DEFAULT_TENANT_UI_NAMESPACE,O as DEFAULT_TENANT_API_NAMESPACE,R as DEFAULT_SECRET_MIME_TYPES,Y as ConfigSourceError};
package/dist/server.d.ts CHANGED
@@ -2648,6 +2648,18 @@ type SSOConfig<
2648
2648
  * @default 60
2649
2649
  */
2650
2650
  rotationGraceSeconds?: number;
2651
+ /**
2652
+ * Fallback session window (seconds) used ONLY when the IdP's token response carries a
2653
+ * `refresh_token` but no `refresh_expires_in`. An IdP-provided `refresh_expires_in` ALWAYS wins —
2654
+ * this value never overrides it. `refresh_expires_in` is a Keycloak extension (standard OAuth
2655
+ * token responses carry no refresh-token expiry field), so for IdPs that omit it this bounds the
2656
+ * session cookie expiry and the session-store TTL. It re-arms on every successful refresh, so it
2657
+ * behaves as an idle window, not a max session lifetime. Ops-governed (ConfigSource); no upper
2658
+ * clamp (deliberate: windows longer than the default are honored); non-numeric or `< 1` values
2659
+ * fall back to the default.
2660
+ * @default 86400
2661
+ */
2662
+ sessionWindowSeconds?: number;
2651
2663
  } & SSOHandlerConfig;
2652
2664
  type StateCookie = {
2653
2665
  state: string;
package/dist/server.js CHANGED
@@ -1 +1 @@
1
- import{A as g9,B as M1,C as c5,D as l,E as X2,I as _1,M as $2,O as M9,P as $9,S as BJ,T as WJ,U as p,V as Z9,X as N5,a as O9,d as a9,h as W9,i as G9,k as L9,l as i9,m as F9,n as G5,o as W1,p as V9,q as H9,r as D9,s as YJ,y as j1,z as h9}from"./shared/core-15896f6h.js";var K2="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.",_9=["user","customer","workload"],Y2={user:async(J,$)=>$.sso?.getUser(J),customer:async(J,$)=>$.ciam?.getCustomer(J),workload:async(J,$)=>{let Z=await $.workload?.getWorkloadIdentity?.(J);if(!Z)return;let X=Z.clientId??Z.workloadId??Z.claims.sub;return X?{...Z,id:X}:void 0}};function B2(J){if(J==="any")return _9;let $=Array.isArray(J)?J:[J];return _9.filter((Z)=>$.includes(Z))}function W2(J){let $=J.headers.get("cookie");if(!$)return[];return $.split(";").map((Z)=>Z.slice(0,Z.indexOf("=")===-1?Z.length:Z.indexOf("=")).trim()).filter(Boolean)}function G2(J,$){let Z=J.headers.get("authorization")?.toLowerCase().startsWith("bearer ")??!1,X=W2(J),Q=new Set;for(let B of X){if(B.startsWith("ion.sso"))Q.add("user");if(B.startsWith("ion.ciam"))Q.add("customer")}let G=X.length>0&&!Q.has("user")&&!Q.has("customer");return $.filter((B)=>{if(B==="workload")return Z;if(X.length===0)return!1;return Q.has(B)||G})}function e(J){return typeof J==="string"?J:J.id}function j9(J){let{subject:$,subjectType:Z}=J,X;if(Z==="user")X=$.sso?.scope;else if(Z==="customer")X=$.ciam?.scope;else if(Z==="workload")X=$.scope;return new Set((X??"").split(/\s+/).filter(Boolean))}function x1(J,$,Z){let X=j9(J),Q=$.filter((B)=>X.has(B));return{allow:Z==="any"?Q.length>0:$.length>0&&Q.length===$.length,metadata:{reason:"scope",wantedScopes:$,matchedScopes:Q}}}function l5(J,$){return(Z)=>{if(J.length===0)return;let X=j9(Z),Q=J.filter((B)=>X.has(B));return($==="any"?Q.length>0:Q.length===J.length)?Q:void 0}}function F1(J,$,Z){return(X)=>{if($.length===0||X.subjectType!=="workload")return;let Q=O9(J.config?.authz,X.subject);if(!Q)return;let G=$.filter((L)=>Q.has(L));return(Z==="any"?G.length>0:G.length===$.length)?G:void 0}}function L2(J,$){if(J.subjectType==="workload"){let Z=J.subject.scopesAsEntitlements;if(typeof Z==="boolean")return Z}return $.config?.authz?.scopesAsEntitlements===!0}function S1(J,$,Z,X,Q){return{allow:Z==="ok",subject:$?.subject,subjectType:$?.subjectType,reason:Z,decision:X,response(){if(Z==="ok")return new Response(null,{status:204});if(Z==="unauthenticated")return J.log.warn("authz.denied",{reason:Z,...Q()}),Response.json({error:"Unauthorized"},{status:401});if(Z==="not_configured")return J.log.warn("authz.denied",{reason:Z,subject:$?.subject?.id,subjectType:$?.subjectType,...Q()}),Response.json({error:"not_configured"},{status:503});return J.log.warn("authz.denied",{reason:Z,subject:$?.subject?.id,subjectType:$?.subjectType,...Q()}),Response.json({error:"Forbidden"},{status:403})}}}function F2(J,$,Z){return new Promise((X)=>{let Q=[],G=J.length,B=!1,L=()=>{if(G-=1,G===0&&!B)B=!0,X({outcomes:Q})};for(let M of J)$(M).then((H)=>{if(Q.push({principal:M,decision:H}),!B&&H.allow){B=!0,X({matched:{principal:M,decision:H},outcomes:Q});return}L()},(H)=>{Z?.(M,H),Q.push({principal:M,decision:{allow:!1,metadata:{reason:"error"}}}),L()})})}async function j5(J,$,Z,X,Q,G,B){l($,K2);let L=G2(J,B2(Z)),H=(await Promise.all(L.map(async(C)=>{let t=await Y2[C](J,$);return t?.id?{subject:t,subjectType:C,subjectId:t.id}:void 0}))).filter((C)=>C!==void 0);if(H.length===0)return S1($,void 0,"unauthenticated",void 0,Q);let h=async(C)=>{let t=$.authz.accessIndex;if(!t?.isSubjectDisabled)return!1;return t.isSubjectDisabled(C.subjectId,C.subjectType)},i=async(C)=>{if(B){let t=B(C);if(t&&t.length>0){if(await h(C))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"trusted-client",matchedPermissions:t}}}}if(G&&L2(C,$)){let t=G(C);if(t&&t.length>0){if(await h(C))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"scope",matchedScopes:t}}}}return X(C)},{matched:c,outcomes:s}=await F2(H,i,(C,t)=>{$.log.warn("authz.check_error",{"ion.operation":"authz.check","ion.outcome":"error",subject:C.subjectId,subjectType:C.subjectType,error:t instanceof Error?t.message:String(t),...Q()})});if(c){if(c.decision.metadata?.reason==="scope")$.log.info("authz.scope_honor",{"ion.operation":"authz.scope_honor","ion.outcome":"allow",subject:c.principal.subjectId,subjectType:c.principal.subjectType,matchedScopes:c.decision.metadata.matchedScopes,...Q()});return S1($,c.principal,"ok",c.decision,Q)}let X5=s.length>0&&s.every((C)=>{let t=C.decision.metadata?.reason;return t==="access_index_not_configured"||t==="error"}),f=s[0],K5=X5?"not_configured":"forbidden";return S1($,f?.principal,K5,f?.decision,Q)}async function V2(J,$,Z,X,Q,G="any"){return j5(J,$,G,(B)=>$.authz.has(B.subjectId,Z,X,Q,B.subjectType),()=>({targetType:Z,target:e(X),resource:Q?e(Q):void 0}),Q?void 0:l5([e(X)],"any"),Z==="permission"&&!Q?F1($,[e(X)],"any"):void 0)}async function H2(J,$,Z,X,Q="any"){return j5(J,$,Q,(G)=>$.authz.hasPermission(G.subjectId,Z,X,G.subjectType),()=>({targetType:"permission",target:e(Z),resource:X?e(X):void 0}),X?void 0:l5([e(Z)],"any"),X?void 0:F1($,[e(Z)],"any"))}async function D2(J,$,Z,X,Q="any"){return j5(J,$,Q,(G)=>$.authz.hasRole(G.subjectId,Z,X,G.subjectType),()=>({targetType:"role",target:e(Z),resource:X?e(X):void 0}),X?void 0:l5([e(Z)],"any"))}async function M2(J,$,Z,X,Q="any"){return j5(J,$,Q,(G)=>$.authz.hasGroup(G.subjectId,Z,X,G.subjectType),()=>({targetType:"group",target:e(Z),resource:X?e(X):void 0}),X?void 0:l5([e(Z)],"any"))}async function N2(J,$,Z,X="any"){let Q=Z.filter((B)=>!B.resource).map((B)=>e(B.target)),G=Z.filter((B)=>!B.resource&&B.targetType==="permission").map((B)=>e(B.target));return j5(J,$,X,(B)=>$.authz.hasAny(B.subjectId,Z,B.subjectType),()=>({targets:Z.map((B)=>`${B.targetType}:${e(B.target)}`)}),Q.length>0?l5(Q,"any"):void 0,G.length>0?F1($,G,"any"):void 0)}async function z2(J,$,Z,X="any"){let Q=Z.length>0&&Z.every((L)=>!L.resource),G=Z.length>0&&Z.every((L)=>!L.resource&&L.targetType==="permission"),B=Z.map((L)=>e(L.target));return j5(J,$,X,(L)=>$.authz.hasAll(L.subjectId,Z,L.subjectType),()=>({targets:Z.map((L)=>`${L.targetType}:${e(L.target)}`)}),Q?l5(B,"all"):void 0,G?F1($,B,"all"):void 0)}async function _2(J,$,Z,X="any"){return j5(J,$,X,(Q)=>Promise.resolve(x1(Q,[Z],"any")),()=>({scope:Z}))}async function O2(J,$,Z,X="any"){return j5(J,$,X,(Q)=>Promise.resolve(x1(Q,Z,"any")),()=>({scopes:Z}))}async function j2(J,$,Z,X="any"){return j5(J,$,X,(Q)=>Promise.resolve(x1(Q,Z,"all")),()=>({scopes:Z}))}function $5(J){return typeof J==="string"&&J.length>0?J:void 0}function A9(J){let $=$5(J.email);return{sub:String(J.sub??""),email:$,name:$5(J.name),userName:$5(J.preferred_username)??$,avatar:$5(J.picture)}}var E9={oidc:{flow:"id_token",scope:"openid profile email",branding:{displayName:"Single sign-on"},mapClaims:A9},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:A9},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:(J)=>{let $=$5(J.email)??$5(J.preferred_username);return{sub:String(J.sub??J.oid??""),email:$,name:$5(J.name),userName:$5(J.preferred_username)??$,avatar:$5(J.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:(J)=>{let $=$5(J.email);return{sub:String(J.sub??""),email:$,name:$5(J.name),userName:$}}},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:(J)=>({sub:String(J.id??J.node_id??""),email:$5(J.email),name:$5(J.name)??$5(J.login),userName:$5(J.login),avatar:$5(J.avatar_url)})}};function R1(J){if(J==="magic-link")return;return E9[J]}function V1(J,$){if($.type==="magic-link")return;let Z=R1($.type);if(!Z)return;return{name:J,type:$.type,flow:Z.flow,authorizationUrl:$.authorizationUrl??Z.authorizationUrl,tokenUrl:$.tokenUrl??Z.tokenUrl,jwksUri:$.jwksUri??Z.jwksUri,userInfoUrl:$.userInfoUrl??Z.userInfoUrl,scope:$.scope??Z.scope,clientId:$.clientId,clientSecret:$.clientSecret,extraAuthParams:Z.extraAuthParams,branding:{...Z.branding,...$.branding},mapClaims:Z.mapClaims,config:$}}function b1(J){return{...R1(J.type)?.branding??{displayName:J.type},...J.branding}}function y1(J){if(!J)return[];return Object.entries(J).filter(([,$])=>$.enabled!==!1).map(([$,Z],X)=>({name:$,config:Z,index:X})).sort(($,Z)=>{let X=$.config.order??Number.MAX_SAFE_INTEGER,Q=Z.config.order??Number.MAX_SAFE_INTEGER;if(X!==Q)return X-Q;return $.index-Z.index}).map(({name:$,config:Z})=>({name:$,config:Z}))}var P9=600000,q1=256,B5=new Map;function A2(J){if(typeof J?.ttlMs==="number"&&Number.isFinite(J.ttlMs))P9=Math.min(Math.max(J.ttlMs,60000),86400000);if(typeof J?.maxEntries==="number"&&Number.isFinite(J.maxEntries)){q1=Math.max(1,Math.floor(J.maxEntries));while(B5.size>q1){let $=B5.keys().next().value;if($===void 0)break;B5.delete($)}}}function w9(J,$){B5.delete(J),B5.set(J,$);while(B5.size>q1){let Z=B5.keys().next().value;if(Z===void 0)break;B5.delete(Z)}}var o5=new Map,U1=()=>Date.now();function E2(J){U1=J??(()=>Date.now())}var C1={};function w2(J){C1=J??{}}function P2(J){if(!J)return;if(/\bno-store\b/i.test(J))return 60000;let $=/max-age\s*=\s*(\d+)/i.exec(J);if(!$)return;let Z=Number($[1]);return Number.isFinite(Z)?Z*1000:void 0}function I2(J){let Z=P2(J)??P9;return Math.min(Math.max(Z,60000),86400000)}async function k1(J,$=3,Z=1000,X=30000,Q){let G=Error("Placeholder Error");for(let B=0;B<=$;B++)try{return await J()}catch(L){if(G=L instanceof Error?L:Error(String(L)),L instanceof Error&&L.message.includes("400"))throw L;if(B===$)throw G;let M=Math.min(Z*2**B,X),H=Math.random()*0.1*M;await new Promise((h)=>setTimeout(h,M+H)),Q?.warn(`Retry attempt ${B+1} after ${M+H}ms delay`)}throw G}async function r5(J,$,Z){let X=B5.get(J);if(!Z?.forceRefresh&&X&&X.expiresAt>U1())return w9(J,X),X.jwks;let Q=o5.get(J);if(Q)return Q;let G=(async()=>{try{return await k1(async()=>{let B=await fetch(J);if(!B.ok)throw Error("Failed to fetch JWKS");let L=await B.json(),M=I2(B.headers.get("cache-control"));return w9(J,{jwks:L,expiresAt:U1()+M,importedKeys:new Map}),L},C1.maxRetries,C1.baseDelayMs,void 0,$)}catch(B){let L=B5.get(J);if(L)return $?.warn("JWKS refresh failed; serving last-known-good keys",{"ion.operation":"jwks.refresh","ion.outcome":"degraded"}),L.jwks;throw B}finally{o5.delete(J)}})();return o5.set(J,G),G}function T2(J){if(J){B5.delete(J),o5.delete(J);return}B5.clear(),o5.clear()}async function S2(J,$,Z){return(await I9(J,$,Z)).jwk}async function I9(J,$,Z){if(!$?.trim())throw Error("JWT header missing kid");await r5(J,Z);let X=B5.get(J),Q=X?.jwks.keys.find((G)=>G.kid===$);if(!Q)await r5(J,Z,{forceRefresh:!0}),X=B5.get(J),Q=X?.jwks.keys.find((G)=>G.kid===$);if(!X||!Q)throw Error("Public key not found");return{jwk:Q,entry:X}}async function f1(J,$,Z,X,Q){let{jwk:G,entry:B}=await I9(J,$,Q),L=`${$}\x00${Z}`,M=B.importedKeys.get(L);if(M)return M;let H=X(G);return H.catch(()=>{if(B.importedKeys.get(L)===H)B.importedKeys.delete(L)}),B.importedKeys.set(L,H),H}async function x2(J,$){let Z=J.keys.find((X)=>X.kid===$);if(!Z)throw Error("Public key not found");return T9(Z)}function T9(J){return crypto.subtle.importKey("jwk",{kty:J.kty,n:J.n,e:J.e},{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},!1,["verify"])}async function R2(J,$,Z){return f1(J,$,"rs256",T9,Z)}var v1={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 h1(J,$,Z,X){if(typeof Z!=="string"||!(Z in v1))throw Error(`Unsupported JWT alg "${String(Z)}" (allowed: ${Object.keys(v1).join(", ")})`);let Q=v1[Z];return{key:await f1(J,$,`oidc:${Z}`,(B)=>{if(B.kty!==Q.kty)throw Error(`JWK type "${B.kty}" does not match token alg "${Z}"`);if(Q.kty==="EC"){let L=B;if(L.crv!==Q.crv)throw Error(`JWK curve "${String(L.crv)}" does not match token alg "${Z}"`);return crypto.subtle.importKey("jwk",{kty:"EC",crv:L.crv,x:L.x,y:L.y},Q.importParams,!1,["verify"])}return crypto.subtle.importKey("jwk",{kty:B.kty,n:B.n,e:B.e},Q.importParams,!1,["verify"])},X),algorithm:Q.verifyParams}}function V5(J=32){let $=new Uint8Array(J);return crypto.getRandomValues($),Array.from($,(Z)=>Z.toString(16).padStart(2,"0")).join("").substring(0,J)}function H1(J){let $="";return J.forEach((Z)=>{$+=String.fromCharCode(Z)}),btoa($).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function R9(J){let $=J.replace(/-/g,"+").replace(/_/g,"/"),Z=$.padEnd($.length+(4-$.length%4)%4,"="),X=atob(Z),Q=new Uint8Array(X.length);for(let G=0;G<X.length;G++)Q[G]=X.charCodeAt(G);return Q}function S9(J){let $=new TextDecoder().decode(R9(J));return JSON.parse($)}async function J1(J){let $=new TextEncoder().encode(J),Z=await crypto.subtle.digest("SHA-256",$);return H1(new Uint8Array(Z))}function m1(J){let $=new URL(J.authorizationUrl);if($.searchParams.set("client_id",J.clientId),$.searchParams.set("redirect_uri",J.redirectUri),$.searchParams.set("response_type","code"),$.searchParams.set("scope",J.scope),$.searchParams.set("state",J.state),J.codeChallenge)$.searchParams.set("code_challenge",J.codeChallenge),$.searchParams.set("code_challenge_method","S256");if(J.nonce)$.searchParams.set("nonce",J.nonce);for(let[Z,X]of Object.entries(J.extraParams??{}))$.searchParams.set(Z,X);return $.toString()}async function p1(J){let $=new URLSearchParams;if($.append("grant_type","authorization_code"),$.append("code",J.code),$.append("redirect_uri",J.redirectUri),$.append("client_id",J.clientId),J.clientSecret)$.append("client_secret",J.clientSecret);if(J.codeVerifier)$.append("code_verifier",J.codeVerifier);let Z=await fetch(J.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:$.toString()}),X=await Z.json();if(!Z.ok){let Q=X;throw J.log?.error("OIDC authorization-code exchange failed",{"ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":Z.status,oidc_error:Q.error}),Error(`Token exchange failed: ${Q.error||Z.statusText} - ${Q.error_description||""}`.trim())}if(typeof X.access_token!=="string")throw Error("Token exchange response missing access_token");return X}var b9=60;function e5(J){return J.trim().replace(/\/$/,"")}function y9(J){let{claims:$,audience:Z}=J,X=e5(J.issuer),Q=J.nowSec??Math.floor(Date.now()/1000),G=J.clockSkewSec??b9,B=$.iss;if(typeof B!=="string"||e5(B)!==X)throw Error("ID token issuer mismatch");let L=$.aud,M=Array.isArray(L)?L.includes(Z):typeof L==="string"&&L===Z,H=typeof $.azp==="string"&&$.azp===Z;if(!M&&!H)throw Error("ID token audience mismatch");if(typeof $.exp!=="number")throw Error("ID token missing exp");if($.exp<Q-G)throw Error("ID token expired");if(J.expectedNonce!==void 0){if($.nonce!==J.expectedNonce)throw Error("ID token nonce mismatch")}}async function v9(J,$,Z){let X=J.split(".");if(X.length!==3)throw Error("Invalid JWT");let Q=S9(X[0]),G=S9(X[1]),B=R9(X[2]),{key:L,algorithm:M}=await h1($,Q.kid,Q.alg,Z),H=new TextEncoder().encode(`${X[0]}.${X[1]}`);if(!await crypto.subtle.verify(M,L,B,H))throw Error("Invalid JWT signature");return{header:Q,payload:G}}async function P5(J){let{payload:$}=await v9(J.idToken,J.jwksUri,J.log);return y9({claims:$,issuer:J.issuer,audience:J.audience,clockSkewSec:J.clockSkewSec,expectedNonce:J.expectedNonce}),$}var b2="http://schemas.openid.net/event/backchannel-logout";async function u1(J){let{payload:$}=await v9(J.logoutToken,J.jwksUri,J.log),Z=e5(J.issuer),X=$.iss;if(typeof X!=="string"||e5(X)!==Z)throw Error("Logout token issuer mismatch");let Q=$.aud,G=Array.isArray(Q)?Q.includes(J.audience):typeof Q==="string"&&Q===J.audience,B=typeof $.azp==="string"&&$.azp===J.audience;if(!G&&!B)throw Error("Logout token audience mismatch");if($.nonce!=null)throw Error("Logout token must not contain a nonce");let L=$.events;if(!(typeof L==="object"&&L!==null&&!Array.isArray(L)&&Object.hasOwn(L,b2)))throw Error("Logout token missing back-channel logout event");let H=typeof $.sid==="string"&&$.sid.length>0,h=typeof $.sub==="string"&&$.sub.length>0;if(!H&&!h)throw Error("Logout token missing sid and sub");if(typeof $.exp==="number"){let i=Math.floor(Date.now()/1000),c=J.clockSkewSec??b9;if($.exp<i-c)throw Error("Logout token expired")}return $}var y2=3600000,v2=60000,q2=86400000,U2=256,A5=new Map,s5=new Map;function x9(J,$){A5.delete(J),A5.set(J,$);while(A5.size>U2){let Z=A5.keys().next().value;if(Z===void 0)break;A5.delete(Z)}}var g1=()=>Date.now();function C2(J){g1=J??(()=>Date.now())}function k2(J){if(J){A5.delete(J),s5.delete(J);return}A5.clear(),s5.clear()}function f2(J){let $=J?/max-age\s*=\s*(\d+)/i.exec(J):null,Z=$?Number($[1]):Number.NaN,X=Number.isFinite(Z)?Z*1000:y2;return Math.min(Math.max(X,v2),q2)}async function l1(J){let $=A5.get(J);if($&&$.expiresAt>g1())return x9(J,$),$.endpoints;let Z=s5.get(J);if(Z)return Z;let X=(async()=>{try{let Q=J.replace(/\/$/,""),G=await fetch(`${Q}/.well-known/openid-configuration`,{headers:{Accept:"application/json"}});if(!G.ok)throw Error(`OIDC discovery failed for ${J} with status ${G.status}`);let B=await G.json(),L={authorizationUrl:typeof B.authorization_endpoint==="string"?B.authorization_endpoint:void 0,tokenUrl:typeof B.token_endpoint==="string"?B.token_endpoint:void 0,jwksUri:typeof B.jwks_uri==="string"?B.jwks_uri:void 0,userInfoUrl:typeof B.userinfo_endpoint==="string"?B.userinfo_endpoint:void 0};return x9(J,{endpoints:L,expiresAt:g1()+f2(G.headers.get("cache-control"))}),L}catch(Q){let G=A5.get(J);if(G)return G.endpoints;throw Q}finally{s5.delete(J)}})();return s5.set(J,X),X}async function c1(J,$){let Z=await fetch(J,{headers:{Authorization:`Bearer ${$}`,Accept:"application/json","User-Agent":"ionite-ciam"}});if(!Z.ok)throw Error(`UserInfo request failed with status ${Z.status}`);return await Z.json()}function h2(J){let $=J.replace(/-----BEGIN [^-]+-----/g,"").replace(/-----END [^-]+-----/g,"").replace(/\s+/g,""),Z=atob($),X=new Uint8Array(Z.length);for(let Q=0;Q<Z.length;Q++)X[Q]=Z.charCodeAt(Q);return X}async function d1(J){let $=Math.floor(Date.now()/1000),Z={alg:"ES256",kid:J.keyId,typ:"JWT"},X={iss:J.teamId,iat:$,exp:$+(J.expiresInSeconds??3600),aud:"https://appleid.apple.com",sub:J.clientId},Q=H1(new TextEncoder().encode(JSON.stringify(Z))),G=H1(new TextEncoder().encode(JSON.stringify(X))),B=`${Q}.${G}`,L=await crypto.subtle.importKey("pkcs8",h2(J.privateKey),{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),M=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},L,new TextEncoder().encode(B));return`${B}.${H1(new Uint8Array(M))}`}function g2(J){for(let $=0;$<J.length;$++){let Z=J.charCodeAt($);if(Z<=31||Z===127)return!0}return!1}function m2(J,$){let Z=null;try{Z=new URL(J,$)}catch{Z=null}let X="";try{X=new URL($).origin}catch{X=""}return{candidate:J,url:Z,requestOrigin:X}}function q9(J,$,Z){let X=m2(J,Z),Q=!1;for(let G of $){let B=G(X);if(B==="deny")return!1;if(B==="allow")Q=!0}return Q}function U9(){return({candidate:J,url:$})=>{if(g2(J))return"deny";if(J.includes("\\"))return"deny";if(J.startsWith("//"))return"deny";if(!$)return"deny";if($.protocol!=="http:"&&$.protocol!=="https:")return"deny";if($.username||$.password)return"deny";return"abstain"}}function C9(){return({candidate:J})=>J.startsWith("/")&&!J.startsWith("//")&&!J.startsWith("/\\")?"allow":"abstain"}function k9(){return({url:J,requestOrigin:$})=>J&&$&&J.origin===$?"allow":"abstain"}function p2(...J){let $=new Set(J.map((Z)=>{try{return new URL(Z).origin}catch{return Z}}));return({url:Z})=>Z&&$.has(Z.origin)?"allow":"abstain"}function u2(...J){let $=J.map((Z)=>Z.toLowerCase());return({url:Z})=>{if(!Z)return"abstain";let X=Z.hostname.toLowerCase();for(let Q of $)if(Q.startsWith(".")){if(X===Q.slice(1)||X.endsWith(Q))return"allow"}else if(X===Q)return"allow";return"abstain"}}function n1(){return[U9(),C9(),k9()]}function f9(J,$,Z){if(!J)return!1;return q9(J,$,Z)}function a1(J,$){if(!J)return $.fallback;return q9(J,$.rules,$.requestUrl)?J:$.fallback}var l2={rules:n1(),fallback:"/"};function c2(J,$,Z="redirect"){let X=new URL(J.url).searchParams.get(Z)??void 0;return f9(X,$.rules,J.url)?{redirect:X}:void 0}function d2(J,$){let Z=J.context;return a1(Z?.redirect,{rules:$.rules,fallback:$.fallback,requestUrl:J.request.url})}function I5(J,$,Z){if(J instanceof Response)return{response:J};if(typeof J==="string")return{location:a1(J,{rules:n1(),fallback:$,requestUrl:Z})};return{location:$}}function x5(J,$){if($.length===0)return J;let Z=new Headers(J.headers);for(let X of $)Z.append("Set-Cookie",X);return new Response(J.body,{status:J.status,statusText:J.statusText,headers:Z})}var D1="ciam",n2="id_token",a2="access_token";function i2(J,$,Z,X,Q,G){if(!Z&&!X)return;let B=new WeakMap,L={...Z,...X},M={...L,magicLinkTtl:L.magicLinkTtl??3600,sessionTtl:L.sessionTtl??86400,cookiesSecure:L.cookiesSecure!==void 0?L.cookiesSecure:!0,cookiesSameSite:L.cookiesSameSite!==void 0?L.cookiesSameSite:"Strict",cookiesPrefix:L.cookiesPrefix??(L.ciamId?`ion.ciam.${L.ciamId}`:"ion.ciam"),cookiesPath:L.cookiesPath??"/"};function H(){if(!M.sessionStore)throw Error("Missing CIAM configuration field: sessionStore. CIAM sessionStore is required for server-side session tracking and first-party logout.");return M.sessionStore}function h(){H()}let i=J.callbackParams??c5(h9("ionite.ciam")),c=J.idTokenClaims??c5(M1("ionite.ciam")),s=J.tokenResponse??c5(g9("ionite.ciam"));function X5(K=32){let V=new Uint8Array(K);return crypto.getRandomValues(V),Array.from(V,(F)=>F.toString(16).padStart(2,"0")).join("").substring(0,K)}function f(K,V,F,O=M.cookiesSameSite??"Strict"){if(!M)throw Error("ionite CIAM Manager not initialized");if(K=`${M.cookiesPrefix}.${K}`,typeof V!=="string")V=btoa(JSON.stringify(V));let A;if(F instanceof Date)A=`Expires=${F.toUTCString()}`;else if(typeof F==="number")A=`Max-Age=${F}`;else throw Error("Invalid expires type",F);if(V.length>4000)throw Error(`Error setting cookie: ${K}. Cookie length is: ${V.length}`);return`${K}=${V}; ${A}; Path=${M.cookiesPath}; HttpOnly;${M.cookiesSecure?" Secure;":""} SameSite=${O};`}function K5(K){if(!M)throw Error("ionite CIAM Manager not initialized");return`${M.cookiesPrefix}.${K}=; Max-Age=0; Path=${M.cookiesPath}; HttpOnly;${M.cookiesSecure?" Secure;":""} SameSite=${M.cookiesSameSite};`}function C(K,V,F=!1){if(!M)throw Error("ionite CIAM Manager not initialized");let O=V.headers.get("cookie");if(!O)return null;let A=`${M.cookiesPrefix}.${K}`,P=O.split(";").find((x)=>x.trim().startsWith(`${A}=`));if(!P)return null;let R=P.indexOf("="),E=P.substring(R+1).trim();if(!F)return E;try{let x=atob(E);return JSON.parse(x)}catch(x){return $.error("[CIAM] Failed to parse cookie",{"ion.operation":"cookie.parse","ion.outcome":"failure",cookieName:A},x),null}}function t(K){return`cstate_${K}`}async function W5(K,V,F,O){let A=await M.afterLogin?.({...V,request:K,context:F}),P=I5(A,"/",K.url);if(P.response)return x5(P.response,O.map(([,R])=>R));return new Response(V.ok?"Authentication successful, redirecting":"Authentication failed, redirecting",{status:302,headers:[["Location",P.location],...O]})}function q5(K,V){return["Set-Cookie",f("session",K,V)]}function O5(K){if(!K)return;if(K instanceof Date)return K;let V=new Date(K);return Number.isNaN(V.getTime())?void 0:V}async function T5(K){let V=C("session",K);if(!V)return;let F=await H().get(V);if(F&&M.tenantId&&F.tenantId&&F.tenantId!==M.tenantId)return;if(F?.authType!=="ciam")return;let O=O5(F.expiresAt);if(O&&Date.now()>O.getTime()){await H().delete(V);return}return F}async function U5(K){if(!M)throw Error("ionite CIAM Manager not initialized");h();let V=B.get(K);if(V)return V;let F=C5(K);return B.set(K,F),F}async function C5(K){try{let V=await T5(K);if(!V?.claims?.sub)return{status:"unauthenticated"};return{status:"authenticated",value:M5(V.claims)}}catch(V){return $.error("CIAM session resolution failed",{"ion.operation":"ciam.session","ion.outcome":"degraded"},V),{status:"degraded",error:V instanceof Error?V:void 0}}}async function k5(K){let V=await U5(K);return V.status==="authenticated"?V.value:void 0}async function f5(K){if(!M)throw Error("ionite CIAM Manager not initialized");h();let V;try{V=await k5(K)}catch{V=void 0}let F=await M.beforeLogout?.({request:K,user:V});try{let T=C("session",K);if(T)await H().delete(T)}catch(T){$.warn("Failed to delete CIAM session",{"ion.operation":"session.delete","ion.outcome":"degraded"},T)}let O=[["Set-Cookie",K5("session")]],A=await M.afterLogout?.({request:K,context:F}),P=I5(A,"/",K.url);if(P.response)return x5(P.response,O.map(([,T])=>T));let R=P.location??"/",E=K.headers.get("accept");if(E?.includes("application/json")||E?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:R}),{status:200,headers:[["Content-Type","application/json"],...O]});return new Response("Logged out",{status:302,headers:[["Location",R],...O]})}function h5(K){return K.id||K.email||`ciam-${K.userName}`}function E5(K,V,F){return{sub:h5(K),iss:D1,aud:D1,typ:n2,exp:Math.floor(F.getTime()/1000),iat:Math.floor(Date.now()/1000),email:K.email,name:K.name,preferred_username:K.userName,picture:K.avatar,sid:V}}function S5(K,V,F){return{sub:K,iss:D1,aud:D1,typ:a2,exp:Math.floor(F.getTime()/1000),iat:Math.floor(Date.now()/1000),sid:V,scope:"openid profile email"}}function M5(K){let V=K.exp?new Date(K.exp*1000):new Date;return{id:K.sub,userName:K.preferred_username??"",name:K.name??"",email:K.email??"",avatar:K.picture,userType:"customer",ciam:{profile:K,scope:"openid profile email",tokenType:"Bearer",expires:V}}}async function g5(K){if(!M)throw Error("ionite CIAM Manager not initialized");if(!Q)return new Response(JSON.stringify({error:"Workload authentication required"}),{status:401,headers:{"Content-Type":"application/json"}});if(!await Q.getWorkloadIdentity(K))return new Response(JSON.stringify({error:"Unauthorized: Valid workload token required"}),{status:401,headers:{"Content-Type":"application/json"}});let F,O;try{if(!K.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 _=await K.text(),z=JSON.parse(_);O=typeof z?.redirect==="string"&&z.redirect.length>0?z.redirect:void 0;let I={userName:z.userName,name:z.name,email:z.email,avatar:z.avatar},b=await J.customer.validate(I);if(b.issues)return new Response(JSON.stringify({error:"Missing required fields: userName, name, email"}),{status:400,headers:{"Content-Type":"application/json"}});F=b.value}catch(D){return new Response(JSON.stringify({error:"Invalid JSON in request body"}),{status:400,headers:{"Content-Type":"application/json"}})}let P=new URL(K.url).searchParams.get("ttl"),R=P?parseInt(P,10):M.magicLinkTtl??3600;if(Number.isNaN(R)||R<=0)return new Response(JSON.stringify({error:"Invalid TTL parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let E=X5(32),x=new Date(Date.now()+R*1000);if(!M.magicLinkStore)return new Response(JSON.stringify({error:"Magic link store not configured"}),{status:500,headers:{"Content-Type":"application/json"}});try{await M.magicLinkStore.create(E,F,x)}catch(D){return $.error("Error creating magic link",{"ion.operation":"magic_link.create","ion.outcome":"failure"},D),new Response(JSON.stringify({error:"Failed to create magic link"}),{status:500,headers:{"Content-Type":"application/json"}})}let T=new URL(K.url),N=M.magicLinkLoginUrl||"/magic-link/login",Y=new URL(N,T.origin);if(Y.searchParams.set("token",E),O)Y.searchParams.set("redirect",O);return new Response(JSON.stringify({magicLink:Y.toString(),expiresAt:x.toISOString()}),{status:200,headers:{"Content-Type":"application/json"}})}async function m5(K){if(!M)throw Error("ionite CIAM Manager not initialized");h();let F=new URL(K.url).searchParams.get("token");if(!F)return W5(K,{ok:!1,error:Error("Missing magic-link token")},void 0,[]);if(!M.magicLinkStore)return W5(K,{ok:!1,error:Error("Magic link store not configured")},void 0,[]);let O=await M.magicLinkStore.getAndDelete(F);if(!O)return W5(K,{ok:!1,error:Error("Magic link invalid, expired, or already used")},void 0,[]);let A=new Date(Date.now()+(M.sessionTtl??86400)*1000),P=X5(32),R=h5(O.customer),E=E5(O.customer,P,A),x=S5(R,P,A),T=M5(E),N;try{let D={sid:P,sub:R,authType:"ciam",tenantId:M.tenantId,expiresAt:A,claims:E,accessClaims:x,createdAt:new Date};await H().create(D),N=D}catch(D){throw $.warn("Failed to create session",{"ion.operation":"session.create","ion.outcome":"degraded"},D),D}if(M.customerStore)try{let D=T.id;if(D){let _=new Date,z=await M.customerStore.get(D);if(z||M.enableJitUserProvisioning){let I={...z??{},...T,id:D,tenantId:z?.tenantId,createdAt:z?.createdAt??_,updatedAt:_,userType:z?.userType??"customer"};await M.customerStore.upsert(I)}}}catch(D){$.warn("Failed to store customer",{"ion.operation":"customer.store","ion.outcome":"degraded"},D)}let Y=[q5(P,A)];return W5(K,{ok:!0,user:T,session:N},void 0,Y)}function L5(K,V=200,F=[]){return new Response(JSON.stringify(K),{status:V,headers:[["Content-Type","application/json"],...F]})}function Y5(K,V){try{return new URL(K).toString()}catch{let F=new URL(V).origin,O=M.cookiesSecure?F.replace(/^http:\/\//,"https://"):F;return new URL(K,O).toString()}}function p5(){let K=M.customerLoginUrl||"/auth/customer/login",V=K.includes("?")?"&":"?";return y1(M.providers).map(({name:F,config:O})=>{let A=b1(O);return{name:F,type:O.type,displayName:A.displayName,loginUrl:`${K}${V}provider=${encodeURIComponent(F)}`,iconUrl:A.iconUrl,colors:A.colors,url:A.url}})}async function y(K){if(!K)return{};let{authorizationUrl:V,tokenUrl:F,jwksUri:O,userInfoUrl:A}=K,P=K.config.authority;if(P&&(!V||!F||K.flow==="id_token"&&!O))try{let E=await l1(P);V=V??E.authorizationUrl,F=F??E.tokenUrl,O=O??E.jwksUri,A=A??E.userInfoUrl}catch(E){$.error("CIAM provider OIDC discovery failed",{"ion.operation":"ciam.oidc.discovery","ion.outcome":"failure"},E)}return{authorizationUrl:V,tokenUrl:F,jwksUri:O,userInfoUrl:A}}async function U(K){if(K.type==="apple"){let{teamId:V,keyId:F,privateKey:O,clientId:A}=K.config;if(V&&F&&O&&A)return d1({teamId:V,keyId:F,privateKey:O,clientId:A})}return K.clientSecret}async function m(K){H();let F=new URL(K.url).searchParams.get("provider");if(!F)return L5({error:"Missing required query parameter: provider"},400);let O=M.providers?.[F];if(!O||O.enabled===!1||O.type==="magic-link")return L5({error:`Unknown or disabled CIAM provider: ${F}`},404);let A=V1(F,O);if(!A?.clientId)return L5({error:`CIAM provider ${F} is not fully configured`},500);let P=await y(A);if(!P.authorizationUrl)return L5({error:`CIAM provider ${F} is missing an authorization endpoint`},500);let R=M.customerCallbackUrl||"/auth/customer/callback",E=Y5(R,K.url),x=V5(),T=V5(64),N=V5(),Y=A.flow==="id_token",D=Y?await J1(T):void 0,_=await M.beforeLogin?.({request:K}),z=m1({authorizationUrl:P.authorizationUrl,clientId:A.clientId,redirectUri:E,scope:A.scope,state:x,codeChallenge:D,nonce:N,extraParams:A.extraAuthParams}),I={provider:F,state:x,codeVerifier:Y?T:void 0,nonce:N,redirectUri:E,..._===void 0?{}:{context:_}};return new Response("Redirecting to CIAM provider",{status:302,headers:[["Location",z],["Set-Cookie",f(t(x),I,M.loginStateTtl??600,"Lax")]]})}async function d(K){if(K.method==="POST"){if((K.headers.get("content-type")??"").includes("application/x-www-form-urlencoded")){let F=await K.text();return Object.fromEntries(new URLSearchParams(F).entries())}}return Object.fromEntries(new URL(K.url).searchParams.entries())}async function o(K,V){let F=K.mapClaims(V);if(!F.sub)return{ok:!1};let O=`${K.name}:${F.sub}`,A={id:O,userName:F.userName||F.email||O,name:F.name||"",email:F.email||"",avatar:F.avatar,userType:"customer"},P=O;if(M.customerStore){let Y=await M.customerStore.lookup(A)??await M.customerStore.get(O);if(P=Y?.id??O,!Y&&!M.enableJitUserProvisioning)return $.warn("CIAM JIT customer provisioning disabled: unknown customer rejected",{"ion.operation":"customer.store","ion.outcome":"skipped"}),{ok:!1};let D=new Date,_={...Y??{},...A,id:P,tenantId:Y?.tenantId,createdAt:Y?.createdAt??D,updatedAt:D,userType:Y?.userType??"customer"};await M.customerStore.upsert(_)}let R=new Date(Date.now()+(M.sessionTtl??86400)*1000),E=V5(32),x={sub:P,iss:K.name,aud:K.clientId,exp:Math.floor(R.getTime()/1000),iat:Math.floor(Date.now()/1000),email:F.email,name:F.name,preferred_username:F.userName??F.email,picture:F.avatar,sid:E},T={sid:E,sub:P,authType:"ciam",tenantId:M.tenantId,expiresAt:R,claims:x,accessClaims:{sub:P,sid:E,scope:K.scope},createdAt:new Date},N=H();try{await N.create(T)}catch(Y){if(!await N.get(E))throw Y;await N.update(E,T)}return{ok:!0,claims:x,sid:E,expires:R}}async function W(K){H();let V,F,O=(A)=>{let P=V?[["Set-Cookie",K5(V)]]:[];return W5(K,{ok:!1,error:A},F,P)};try{let A=await d(K),P=await i.validate(A);if(P.issues||!P.value)return O(Error("Invalid CIAM callback parameters"));let{code:R,state:E}=P.value;if(!E)return O(Error("Missing CIAM callback state"));V=t(E);let x=C(V,K,!0);if(F=x?.context,!x?.provider||!x.state||x.state!==E)return $.warn("CIAM callback state verification failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),O(Error("CIAM callback state verification failed"));let T=M.providers?.[x.provider];if(!T)return O(Error("Unknown CIAM provider"));let N=V1(x.provider,T);if(!N?.clientId)return O(Error("CIAM provider not configured"));let Y=await y(N);if(!Y.tokenUrl)return O(Error("CIAM provider missing token endpoint"));let D=await U(N),_=await p1({tokenUrl:Y.tokenUrl,clientId:N.clientId,clientSecret:D,redirectUri:x.redirectUri||Y5(M.customerCallbackUrl||"/auth/customer/callback",K.url),code:R,codeVerifier:N.flow==="id_token"?x.codeVerifier:void 0,log:$}),z;if(N.flow==="id_token"){let v=N.config.authority;if(!_.id_token||!Y.jwksUri||!v)return O(Error("CIAM id_token flow misconfigured"));if(!x.nonce)return O(Error("CIAM callback state cookie missing nonce"));if((await s.validate(_)).issues)return $.warn("CIAM token response validation failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),O(Error("CIAM token response validation failed"));z=await P5({idToken:_.id_token,jwksUri:Y.jwksUri,issuer:v,audience:N.clientId,expectedNonce:x.nonce,log:$});let k=await c.validate(z);if(!k.issues)z=k.value}else{if(!Y.userInfoUrl)return O(Error("CIAM provider missing userinfo endpoint"));z=await c1(Y.userInfoUrl,_.access_token);let v=N.config.authority;if(_.id_token&&Y.jwksUri&&v){let q=await P5({idToken:_.id_token,jwksUri:Y.jwksUri,issuer:v,audience:N.clientId,expectedNonce:x.nonce||void 0,log:$}),k=typeof q.sub==="string"?q.sub:"";if(k){if(typeof z.sub==="string"&&z.sub.length>0&&z.sub!==k)return $.warn("CIAM UserInfo sub does not match verified id_token sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),O(Error("CIAM UserInfo sub mismatch"));z.sub=k}}if(typeof z.sub!=="string"||z.sub.length===0)return $.warn("CIAM UserInfo response missing sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),O(Error("CIAM UserInfo response missing sub"))}let I=await o(N,z);if(!I.ok)return O(Error("Failed to persist CIAM customer"));let b=M5(I.claims);$.info("CIAM third-party sign-in succeeded",{"ion.operation":"ciam.oidc.callback","ion.outcome":"success",provider:N.name});let S=[["Set-Cookie",K5(V)],q5(I.sid,I.expires)];return W5(K,{ok:!0,user:b,session:void 0},F,S)}catch(A){return $.error("Error during CIAM third-party sign-in callback",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"},A),O(A)}}async function j(K){if(!M)throw Error("ionite CIAM Manager not initialized");h();let V=M.magicLinkUrl||"/magic-link",F=M.magicLinkLoginUrl||"/magic-link/login",O=M.logoutUrl||"/auth/customer/logout",A=M.customerLoginUrl||"/auth/customer/login",P=M.customerCallbackUrl||"/auth/customer/callback",R=M.customerProvidersUrl||"/auth/customer/providers",E=new URL(K.url).pathname,x=(I)=>{if(!I)return;try{return new URL(I).pathname}catch{return I.startsWith("/")?I:`/${I}`}};if(x(V)===E&&K.method==="POST")return g5(K);if(x(F)===E&&K.method==="GET")return m5(K);if(x(O)===E&&K.method==="GET")return f5(K);if(x(R)===E&&K.method==="GET")return L5({providers:p5()});if(x(A)===E&&K.method==="GET")return m(K);if(x(P)===E&&(K.method==="GET"||K.method==="POST"))return W(K);return new Response("Not Found",{status:404})}return{...M,getCustomer:k5,resolveCustomer:U5,logout:f5,handler:j,listCustomerProviders:p5}}async function t2(J,$){return l($,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),$.ciam?.getCustomer(J)}async function o2(J,$){return l($,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),await $.ciam?.resolveCustomer(J)??{status:"unauthenticated"}}var r2="urn:ietf:params:scim:schemas:core:2.0:User",m9="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",s2="urn:ietf:params:scim:schemas:core:2.0:Group";function i1(J,$,Z){let Q=($==="group"?J.resources:void 0)?.map((G)=>typeof G==="string"?G:G.id).filter(Boolean);return{schemas:[s2,p],id:J.id,externalId:J.providerId,displayName:J.displayName??J.name,members:Z,[p]:{type:$,requestable:J.requestable,providerId:J.providerId,requestUrl:J.requestUrl,source:J.source,deprecated:J.deprecated,description:J.description,resources:Q&&Q.length>0?Q:void 0,assignableSubjectTypes:J.assignableSubjectTypes,recommendedSubjectTypes:J.recommendedSubjectTypes}}}function e2(J){if(J.scimName)return J.scimName;if(!J.name)return;let[$,...Z]=J.name.split(" ");return{givenName:$,familyName:Z.join(" ")||void 0}}function J4(J){let $={};if(J.ecid!==void 0)$.ecid=J.ecid;if(J.accountClass!==void 0)$.accountClass=J.accountClass;return $.ecid!==void 0||$.accountClass!==void 0?$:void 0}function $4(J){return Object.keys(J.scimSchemaExtensions??{}).filter(($)=>$.startsWith("urn:")&&J.scimSchemaExtensions?.[$]!==void 0)}function t1(J){let $=J.userName||J.email||J.id||"",Z=J.emails??(J.email?[{value:J.email,primary:!0}]:[]),X=new Set([r2]);if(J.scimEnterprise!==void 0)X.add(m9);let Q=J4(J);if(Q!==void 0)X.add(N5);for(let B of $4(J))X.add(B);let G={};if(J.scimEnterprise!==void 0)G[m9]=J.scimEnterprise;if(Q!==void 0)G[N5]=Q;for(let[B,L]of Object.entries(J.scimSchemaExtensions??{}))if(B.startsWith("urn:")&&B!==N5&&L!==void 0)G[B]=L;return{schemas:Array.from(X),id:J.id,externalId:J.externalId,userName:$,displayName:J.displayName??J.name??$,name:e2(J),nickName:J.nickName,profileUrl:J.avatar,title:J.title,userType:J.userType,preferredLanguage:J.preferredLanguage,locale:J.locale,timezone:J.timezone,active:J.active??!0,emails:Z,phoneNumbers:J.phoneNumbers,ims:J.ims,photos:J.photos,addresses:J.addresses,groups:J.groups,entitlements:J.entitlements,roles:J.roles,x509Certificates:J.x509Certificates,meta:{resourceType:"User",created:(J.createdAt??J.updatedAt??new Date).toISOString(),lastModified:(J.updatedAt??J.createdAt??new Date).toISOString()},...G}}var Q1="application/scim+json",Z4="urn:ietf:params:scim:api:messages:2.0:ListResponse",X9="urn:ietf:params:scim:api:messages:2.0:Error",Q9="urn:ietf:params:scim:schemas:core:2.0:User",K1="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",K9="urn:ietf:params:scim:schemas:core:2.0:Group",X4="urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig",p9="urn:ietf:params:scim:schemas:core:2.0:ResourceType",$1="urn:ietf:params:scim:schemas:core:2.0:Schema",Q4="00000000000000000000000000000000";function K4(J){let $={timestamp:new Date().toISOString()};if(J)$.actor=J;try{let Q=globalThis[Symbol.for("opentelemetry.js.api.1")]?.trace?.getActiveSpan?.()?.spanContext?.(),G=Q?.traceId;if(G&&G!==Q4){if($.traceId=G,Q?.spanId)$.spanId=Q.spanId}}catch{}return $}class Y1 extends Error{constructor(J){super(J);this.name="SubjectTypeNotAssignableError",Object.setPrototypeOf(this,Y1.prototype)}}async function Y4(J,$,Z,X){let Q=Z.subjectType??"user";if(!Z9.includes(Q))throw new Y1(`Cannot grant ${Z.targetType} "${G5(Z.target)}" to a "${Q}" principal: only [${Z9.join(", ")}] principals are assignable on this platform.`);let G=F9($,J);if(!G&&!X)return;let B=G5(Z.target),L;if(X)L=await X.getNode(Z.targetType,B);else if(G)L=await(Z.targetType==="group"?G.groups:Z.targetType==="role"?G.roles:G.permissions).get(B);let M=L?.assignableSubjectTypes;if(M&&M.length>0&&!M.includes(Q))throw new Y1(`Cannot grant ${Z.targetType} "${B}" to a "${Q}" principal: this entitlement restricts assignment to [${M.join(", ")}].`)}async function B4(J,$){let Z=W9(J.codeCatalog,G5($.target));if(!Z)return;if(Z.kind!==$.targetType)throw Error(`Cannot grant ${$.targetType} "${Z.entity.id}": code declares that id as ${Z.kind}.`);if(!J.catalogStore)throw Error(`Cannot grant code entitlement "${Z.entity.id}": no AccessCatalogStore is wired for materialization.`);await L9(Z.kind,Z.entity,G9(J.catalogStore,Z.kind))}async function W4(J,$,Z,X){await B4(J,$),await Y4(J.catalogStore,J.codeCatalog,$,X);let Q={...$,status:$.status??"active",provenance:$.provenance??K4()};if(Q.id=W1(Q),await J.accessStore?.grant(Q),J.accessIndex&&(J.catalogStore||J.codeCatalog)){let G=await H9(Q,{catalog:J.catalogStore,code:J.codeCatalog,resources:J.resources,cache:X});await J.accessIndex.materialize(Q.id,G)}return Z?.push({op:"add",change:Q}),Q}async function O1(J,$,Z){let X=$.id??W1($);await J.accessStore?.revoke($),await J.accessIndex?.removeByRoot(X),Z?.push({op:"delete",change:{...$,id:X}})}async function Y9(J,$){let Z=await G4(J,$),X=await F4(J,$);return{oaa:Z,delta:X}}async function G4(J,$){if($.length===0||!J.authz.oaa.isReady())return{status:"skipped"};return B1(J,"authz.oaa.push","OAA incremental access push failed after SCIM mutation; full sync will reconcile",()=>J.authz.oaa.pushAccessChanges($),{count:$.length})}async function B1(J,$,Z,X,Q){try{return await X(),{status:"ok"}}catch(G){return J.log?.warn(Z,{"ion.operation":$,"ion.outcome":"degraded",...Q,error:_5(G)}),{status:"degraded",reason:_5(G)}}}var L4=6;async function F4(J,$){let Z=J.iamDelta;if(!Z?.isReady()||$.length===0)return{status:"skipped"};let X=new Map;for(let M of $){let H=`${M.change.subjectType??"user"}:${G5(M.change.subject)}\x00${M.change.targetType}:${G5(M.change.target)}`;X.set(H,M)}let Q=[...X.values()],G=Q.map(({op:M,change:H})=>()=>M==="add"?Z.onGrant(H):Z.onRevoke(H)),L=(await V4(G,L4)).filter((M)=>M.status==="rejected");if(L.length>0)return J.log?.warn("IAM delta egress degraded after SCIM mutation; IAM server reconcile/aggregation will recover",{"ion.operation":"iam.delta.egress","ion.outcome":"degraded",failed:L.length,total:Q.length,error:_5(L[0]?.reason)}),{status:"degraded",reason:_5(L[0]?.reason)};return{status:"ok"}}async function V4(J,$){let Z=Array(J.length),X=0,Q=async()=>{while(!0){let B=X++;if(B>=J.length)return;let L=J[B];if(!L)continue;try{Z[B]={status:"fulfilled",value:await L()}}catch(M){Z[B]={status:"rejected",reason:M}}}},G=Array.from({length:Math.min($,J.length)},Q);return await Promise.all(G),Z}class A1 extends Error{constructor(J){super(J);this.name="DerivedRevokeError",Object.setPrototypeOf(this,A1.prototype)}}class i5 extends Error{summary;clientError;constructor(J,$,Z=!1){super(J);this.name="ScimMutationError",this.summary=$,this.clientError=Z,Object.setPrototypeOf(this,i5.prototype)}}function g(J,$,Z){return new Response(JSON.stringify({schemas:[X9],status:String(J),scimType:Z,detail:$}),{status:J,headers:{"Content-Type":Q1}})}function R5(J,$){let Z=$?.totalResults??J.length,X=$?.startIndex??1,Q=$?.itemsPerPage??J.length;return new Response(JSON.stringify({schemas:[Z4],totalResults:Z,startIndex:X,itemsPerPage:Q,Resources:J}),{status:200,headers:{"Content-Type":Q1}})}function H5(J,$=200,Z){let X=new Headers({"Content-Type":Q1});if(Z)X.set("Location",Z);return new Response(JSON.stringify(J),{status:$,headers:X})}function u9(J){return g(J.clientError?409:500,`${J.message}; authz mutation summary: ${JSON.stringify(J.summary)}`,J.clientError?"mutability":"invalidValue")}function X1(J){return W1(J)}function o1(J,$){return z1(l9(J),l9($))}function l9(J){let $=new Map;if(!J?.id)return $;for(let Z of J.groups??[]){let X={subject:J.id,targetType:"group",target:Z.value,metadata:Z.display||Z.type?{display:Z.display,type:Z.type}:void 0};$.set(X1(X),X)}for(let Z of J.roles??[]){let X={subject:J.id,targetType:"role",target:Z.value,metadata:Z.display||Z.type?{display:Z.display,type:Z.type,primary:Z.primary}:void 0};$.set(X1(X),X)}for(let Z of J.entitlements??[]){let X={subject:J.id,targetType:"permission",target:Z.value,metadata:Z.display||Z.type?{display:Z.display,type:Z.type,primary:Z.primary}:void 0};$.set(X1(X),X)}return $}function N1(J,$,Z,X){let Q=new Map,G=X&&X.length>0?X:void 0;for(let B of J??[]){let L={subject:B.value,targetType:$,target:Z,resources:G,metadata:B.display||B.type?{display:B.display,type:B.type}:void 0};Q.set(X1(L),L)}return Q}function r1(J){let $=J[p]?.resources;return $&&$.length>0?$:void 0}function H4(J,$){let Z=(Q,G)=>[...Q??[]].sort().join(",")===[...G??[]].sort().join(","),X=J[p];if(X?.type!==void 0&&X.type!==$.kind)return!0;if(X?.requestable!==void 0&&X.requestable!==$.entity.requestable)return!0;if(X?.resources!==void 0&&!Z(X.resources,B9($.entity)))return!0;if(X?.assignableSubjectTypes!==void 0&&!Z(X.assignableSubjectTypes,$.entity.assignableSubjectTypes))return!0;if(X?.recommendedSubjectTypes!==void 0&&!Z(X.recommendedSubjectTypes,$.entity.recommendedSubjectTypes))return!0;return!1}function D4(J,$){let Z=(G,B)=>[...G??[]].sort().join(",")===[...B??[]].sort().join(","),X=J[p],Q=$[p];if(X?.type!==void 0&&X.type!==Q?.type)return!0;if(X?.requestable!==void 0&&X.requestable!==Q?.requestable)return!0;if(X?.resources!==void 0&&!Z(X.resources,Q?.resources))return!0;if(X?.assignableSubjectTypes!==void 0&&!Z(X.assignableSubjectTypes,Q?.assignableSubjectTypes))return!0;if(X?.recommendedSubjectTypes!==void 0&&!Z(X.recommendedSubjectTypes,Q?.recommendedSubjectTypes))return!0;return!1}function M4(J){let $=new Map;for(let Z of J)$.set(X1(Z),Z);return $}async function y5(J,$,Z,X,Q,G){let B=[],L=new Set,M=(h,i)=>`${i}\x00${h}`,H=G?G.get(`${Z}:${X}`)??[]:$?(await $.listByTarget(Z,X)).items:[];for(let h of H){let i=G5(h.subject),c=h.metadata,s=h.subjectType==="workload"?"Workload":c?.type??"User",X5=M(i,s);if(L.has(X5))continue;L.add(X5),B.push({value:i,...c?.display?{display:c.display}:{},type:s})}for(let h of Q??[]){if(h.targetType!==Z||G5(h.target)!==X)continue;let i=G5(h.subject),c=M(i,"Workload");if(L.has(c))continue;L.add(c),B.push({value:i,type:"Workload"})}if(Z==="group"){let h=await J.groups.get(X);for(let i of h?.groups??[]){let c=G5(i),s=M(c,"Group");if(!c||L.has(s))continue;L.add(s),B.push({value:c,type:"Group"})}}return B.length>0?B:void 0}function z1(J,$){let Z=[];for(let[X,Q]of $)if(!J.has(X))Z.push({action:"grant",change:Q});for(let[X,Q]of J)if(!$.has(X))Z.push({action:"revoke",change:Q});return Z}async function s1(J,$){if(J.oaa.isReady())await J.oaa.pushUser($)}async function c9(J,$,Z){if($?.externalId&&$.externalId!==Z.externalId)await J?.onUserDelete($.externalId);await J?.onUserUpsert(Z)}async function d5(J,$,Z,X){let Q={metadataApplied:!1,access:[]},G={status:"skipped"},B=[],L=new V9(J.catalogStore,J.resources,J.codeCatalog);try{try{await $(),Q.metadataApplied=!0}catch(M){for(let H of Z)Q.access.push({change:H.change,status:"rolled_back"});throw Q.metadataApplied=!1,new i5(`SCIM metadata write failed: ${_5(M)}`,Q,!1)}if(X?.oaa)await B1(J,"authz.oaa.metadata","OAA metadata projection failed after SCIM write; full sync will reconcile",X.oaa);if(X?.delta&&J.iamDelta?.isReady())G=await B1(J,"iam.delta.egress","IAM delta metadata projection failed after SCIM write; full aggregation will reconcile",X.delta);for(let M=0;M<Z.length;M++){let H=Z[M];try{if(H.action==="grant")await W4(J,H.change,B,L);else await j4(J,H.change,B);Q.access.push({change:H.change,status:"applied"})}catch(h){Q.access.push({change:H.change,status:"failed",error:h});for(let c=M+1;c<Z.length;c++)Q.access.push({change:Z[c].change,status:"rolled_back"});let i=h instanceof A1||h instanceof Y1;if(!i)await _4(J,H.change,L);throw new i5(i?_5(h):`SCIM access mutation failed: ${_5(h)}`,Q,i)}}return Q}finally{await z4(J),Q.egress=await Y9(J,B),Q.egress.delta=N4(G,Q.egress.delta),O4(J,Q)}}function N4(J,$){if(J.status==="degraded")return J;if($.status==="degraded")return $;return J.status==="ok"||$.status==="ok"?{status:"ok"}:{status:"skipped"}}function _5(J){return J instanceof Error?J.message:String(J)}async function z4(J){try{await J.settleAuthz?.()}catch{}}async function _4(J,$,Z){if(!J.accessIndex||!J.catalogStore&&!J.codeCatalog||!J.accessStore)return;let X=G5($.subject);if(!X)return;let Q=$.subjectType??"user";try{await D9(X,Q,{accessStore:J.accessStore,accessIndex:J.accessIndex,catalogStore:J.catalogStore,code:J.codeCatalog,resources:J.resources},Z)}catch(G){J.log?.warn("Per-subject reconcile after failed SCIM access mutation failed",{"ion.operation":"authz.reconcile.subject.repair","ion.outcome":"degraded",subject:X,subjectType:Q,error:_5(G)})}}function O4(J,$){if(!J.onAccessMutation)return;try{J.onAccessMutation($)}catch{}}async function j4(J,$,Z){if(J.accessStore){let X=$.id??W1($);if(!await J.accessStore.get(X)){if((J.accessIndex?await J.accessIndex.has($.subject,$.targetType,$.target,$.resources?.[0],$.subjectType):{allow:!1}).allow)throw new A1(`Cannot revoke ${$.targetType} "${G5($.target)}" for "${G5($.subject)}": it is not a directly granted root (it is derived from group/role membership). Remove the granting group/role instead.`);await O1(J,$,Z);return}}await O1(J,$,Z)}function a5(J){let $=J[p]?.type??"group";if($==="group"||$==="role"||$==="permission")return $;throw Error(`Unsupported ionite SCIM Group authz type "${String($)}"`)}async function e1(J,$,Z){if(!J.oaa.isReady())return;if(Z==="role"){await J.oaa.pushRole($);return}if(Z==="permission"){await J.oaa.pushPermission($);return}await J.oaa.pushGroup($)}function B9(J){let $=J.resources;if(!$||$.length===0)return;let Z=$.map((X)=>typeof X==="string"?X:X.id).filter(Boolean);return Z.length>0?Z:void 0}function v5(J,$,Z){return i1(J,$,Z)}function A4(J,$){let Z=J[p],X={id:$,name:J.displayName,displayName:J.displayName,description:Z?.description??J.displayName,requestable:Z?.requestable,providerId:Z?.providerId??J.externalId,requestUrl:Z?.requestUrl};if(Z?.resources!==void 0)X.resources=Z.resources;return X}function E4(J){if(!J)return;let $=J.trim().match(/^requestable\s+eq\s+(true|false)$/i);if(!$)return;return{requestable:$[1]?.toLowerCase()==="true"}}function d9(J){if(!J)return;let $=J.trim().match(/^externalId\s+eq\s+"([^"]*)"$/i);return $?$[1]:void 0}async function w4(J,$,Z,X){let Q=[],G=[["group",J.groups],["role",J.roles],["permission",J.permissions]];for(let[L,M]of G)for await(let H of a9((h,i)=>M.list({start:h,limit:i,filter:{requestable:!0}})))if(H.providerId===Z)Q.push({entity:H,type:L});if(Q.length>1)throw new M9(`Ambiguous providerId "${Z}": ${Q.length} entitlements share it (${Q.map((L)=>`${L.type}:${L.entity.id}`).join(", ")})`,"unique_violation","providerId");let B=Q[0];if(B?.entity.requestable!==!0)return;return v5(B.entity,B.type,await y5(J,$,B.type,B.entity.id,X))}async function P4(J,$,Z,X){let Q=Math.max(0,Z.start),G=Z.limit!=null?Q+Z.limit:void 0,B={start:0,limit:G,filter:Z.filter},[L,M,H]=await Promise.all([J.groups.list(B),J.roles.list(B),J.permissions.list(B)]),h=[...L.items.map((f)=>({entity:f,type:"group"})),...M.items.map((f)=>({entity:f,type:"role"})),...H.items.map((f)=>({entity:f,type:"permission"}))],i=L.total+M.total+H.total,c=h.slice(Q,G),s=$?.listByTargets?await $.listByTargets(c.map(({entity:f,type:K5})=>({targetType:K5,target:f.id}))):void 0,X5=await Promise.all(c.map(async({entity:f,type:K5})=>v5(f,K5,await y5(J,$,K5,f.id,X,s))));return{resources:X5,total:i,count:X5.length}}async function Z1(J,$,Z,X){let[Q,G,B]=await Promise.all([J.groups.get(Z),J.roles.get(Z),J.permissions.get(Z)]);if(Q)return v5(Q,"group",await y5(J,$,"group",Z,X));if(G)return v5(G,"role",await y5(J,$,"role",Z,X));if(B)return v5(B,"permission",await y5(J,$,"permission",Z,X));return}async function J9(J,$,Z){let X=a5($),Q=X==="role"?await J.roles.get(Z):X==="permission"?await J.permissions.get(Z):await J.groups.get(Z),G={...Q??{},...A4($,Z),source:Q?.source??"scim"},B=X==="role"?J.roles.set(G):X==="permission"?J.permissions.set(G):J.groups.set(G);return await B.ready(),B}async function I4(J,$){await Promise.all([J.groups.delete($),J.roles.delete($),J.permissions.delete($)])}function n9(){return crypto.randomUUID()}function n5(J,$){let Z=J;if(typeof Z.validate==="function")return Z.validate($);return Promise.resolve(J["~standard"].validate($))}function T4(J){if(!J)return;try{return new URL(J).pathname}catch{return J.startsWith("/")?J:`/${J}`}}function b5(J){let $=T4(J);return $?_1($):void 0}function S4(J,$){let Z=b5(J);if(Z?.endsWith("/Users"))return Z.slice(0,-6);let X=b5($);if(X?.endsWith("/Groups"))return X.slice(0,-7);return}function z5(J,$){return new URL($,J.url).toString()}function w(J,$,Z,X){let{multiValued:Q=!1,...G}=X??{};return{name:J,type:$,description:Z,multiValued:Q,...G}}function x4(J,$){return{schemas:[X4],documentationUri:$?.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:z5(J.request,`${J.basePath}/ServiceProviderConfig`)}}}function R4(J){let $=[];if(J.supportsUsers)$.push({schemas:[p9],id:"User",name:"User",description:"User Account",endpoint:J.usersUrl,schema:Q9,schemaExtensions:[{schema:K1,required:!1},{schema:N5,required:!1}],meta:{resourceType:"ResourceType",location:z5(J.request,`${J.basePath}/ResourceTypes/User`)}});if(J.supportsGroups)$.push({schemas:[p9],id:"Group",name:"Group",description:"Group",endpoint:J.groupsUrl,schema:K9,schemaExtensions:[{schema:p,required:!1}],meta:{resourceType:"ResourceType",location:z5(J.request,`${J.basePath}/ResourceTypes/Group`)}});return $}function b4(J){let $=[];if(J.supportsUsers)$.push({schemas:[$1],id:Q9,name:"User",description:"User Account",meta:{resourceType:"Schema",location:z5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(Q9)}`)},attributes:[w("id","string","Unique identifier for the User.",{multiValued:!1,required:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),w("externalId","string","External identifier from the provisioning client.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",uniqueness:"none"}),w("userName","string","Unique identifier typically used for login.",{multiValued:!1,required:!0,caseExact:!1,mutability:"readWrite",returned:"default",uniqueness:"server"}),w("name","complex","The components of the user name.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",subAttributes:[w("formatted","string","The full name, including titles and suffixes.",{multiValued:!1}),w("familyName","string","The family name of the User.",{multiValued:!1}),w("givenName","string","The given name of the User.",{multiValued:!1}),w("middleName","string","The middle name(s) of the User.",{multiValued:!1}),w("honorificPrefix","string","The honorific prefix(es) of the User.",{multiValued:!1}),w("honorificSuffix","string","The honorific suffix(es) of the User.",{multiValued:!1})]}),w("displayName","string","The name of the User, suitable for display.",{multiValued:!1}),w("nickName","string","The casual way to address the user.",{multiValued:!1}),w("profileUrl","reference","A URL pointing to the User profile.",{multiValued:!1,referenceTypes:["external"]}),w("title","string","The user title, such as Vice President.",{multiValued:!1}),w("userType","string","The relationship between the organization and the User.",{multiValued:!1}),w("preferredLanguage","string","Preferred written or spoken language.",{multiValued:!1}),w("locale","string","Default location for localizing values.",{multiValued:!1}),w("timezone","string","The User time zone.",{multiValued:!1}),w("active","boolean","The User administrative status.",{multiValued:!1}),w("emails","complex","Email addresses for the User.",{multiValued:!0,subAttributes:[w("value","string","Email address value.",{multiValued:!1,required:!0}),w("display","string","Display label for the email.",{multiValued:!1}),w("type","string","Email type such as work or home.",{multiValued:!1}),w("primary","boolean","Primary email indicator.",{multiValued:!1})]}),w("phoneNumbers","complex","Phone numbers for the User.",{multiValued:!0,subAttributes:[w("value","string","Phone number value.",{multiValued:!1,required:!0}),w("display","string","Display label for the phone number.",{multiValued:!1}),w("type","string","Phone number type.",{multiValued:!1}),w("primary","boolean","Primary phone number indicator.",{multiValued:!1})]}),w("photos","complex","Photo URLs for the User.",{multiValued:!0,subAttributes:[w("value","reference","Photo URL.",{multiValued:!1,required:!0,referenceTypes:["external"]}),w("display","string","Display label for the photo.",{multiValued:!1}),w("type","string","Photo type.",{multiValued:!1}),w("primary","boolean","Primary photo indicator.",{multiValued:!1})]}),w("addresses","complex","Physical mailing addresses for the User.",{multiValued:!0,subAttributes:[w("formatted","string","Formatted mailing address.",{multiValued:!1}),w("streetAddress","string","Full street address component.",{multiValued:!1}),w("locality","string","City or locality.",{multiValued:!1}),w("region","string","State or region.",{multiValued:!1}),w("postalCode","string","Postal code.",{multiValued:!1}),w("country","string","Country.",{multiValued:!1}),w("type","string","Address type.",{multiValued:!1}),w("primary","boolean","Primary address indicator.",{multiValued:!1})]}),w("groups","complex","Groups to which the User belongs.",{multiValued:!0,mutability:"readOnly",subAttributes:[w("value","string","Group identifier.",{multiValued:!1,required:!0}),w("$ref","reference","Reference to the Group resource.",{multiValued:!1,referenceTypes:["Group"]}),w("display","string","Display name of the group.",{multiValued:!1}),w("type","string","Relationship type.",{multiValued:!1})]}),w("entitlements","complex","Entitlements for the User.",{multiValued:!0,subAttributes:[w("value","string","Entitlement value.",{multiValued:!1,required:!0}),w("display","string","Display value.",{multiValued:!1}),w("type","string","Entitlement type.",{multiValued:!1}),w("primary","boolean","Primary entitlement indicator.",{multiValued:!1})]}),w("roles","complex","Roles for the User.",{multiValued:!0,subAttributes:[w("value","string","Role value.",{multiValued:!1,required:!0}),w("display","string","Display value.",{multiValued:!1}),w("type","string","Role type.",{multiValued:!1}),w("primary","boolean","Primary role indicator.",{multiValued:!1})]}),w("x509Certificates","complex","Certificates issued to the User.",{multiValued:!0,subAttributes:[w("value","string","Certificate value.",{multiValued:!1,required:!0}),w("display","string","Display value.",{multiValued:!1}),w("type","string","Certificate type.",{multiValued:!1}),w("primary","boolean","Primary certificate indicator.",{multiValued:!1})]})]}),$.push({schemas:[$1],id:K1,name:"EnterpriseUser",description:"Enterprise User extension",meta:{resourceType:"Schema",location:z5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(K1)}`)},attributes:[w("employeeNumber","string","Numeric or alphanumeric identifier assigned to a person.",{multiValued:!1}),w("costCenter","string","Name of a cost center.",{multiValued:!1}),w("organization","string","Name of an organization.",{multiValued:!1}),w("division","string","Name of a division.",{multiValued:!1}),w("department","string","Name of a department.",{multiValued:!1}),w("manager","complex","The User manager.",{multiValued:!1,subAttributes:[w("value","string","Identifier of the manager User resource.",{multiValued:!1}),w("$ref","reference","Reference to the manager User resource.",{multiValued:!1,referenceTypes:["User"]}),w("displayName","string","Display name of the manager.",{multiValued:!1})]})]}),$.push({schemas:[$1],id:N5,name:"IoniteUser",description:"ionite User extension carrying the Enterprise Controlled ID (ECID) identity correlator and the account purpose (accountClass). See https://ionite.com/docs/llms-ecid.txt.",meta:{resourceType:"Schema",location:z5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(N5)}`)},attributes:[w("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}),w("accountClass","string","Account purpose (distinct from userType persona). Open value set: 'daily', 'privileged', 'break_glass', 'service'.",{multiValued:!1})]});if(J.supportsGroups)$.push({schemas:[$1],id:p,name:"IoniteAuthzGroup",description:"ionite authorization metadata for SCIM Group resources.",meta:{resourceType:"Schema",location:z5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(p)}`)},attributes:[w("type","string","Authorization entity kind: group, role, or permission.",{multiValued:!1,required:!1}),w("requestable","boolean","Whether this catalog entry is exposed as assignable access to IAM tooling. Only true entries are served.",{multiValued:!1,required:!1}),w("providerId","string","IAM service-provider id captured when this entitlement is materialized at the destination.",{multiValued:!1,required:!1,mutability:"readWrite"}),w("requestUrl","reference","IAM-owned deep link where a principal can request this entitlement.",{multiValued:!1,required:!1,mutability:"readWrite",referenceTypes:["external"]}),w("source","string","Provenance of the catalog row.",{multiValued:!1,required:!1,mutability:"readOnly",canonicalValues:["code","app","scim"]}),w("deprecated","boolean","Whether this retired entitlement may be deleted.",{multiValued:!1,required:!1,mutability:"readOnly"}),w("description","string","Human-readable authorization entity description.",{multiValued:!1,required:!1}),w("resources","string","Resource ids this entitlement is scoped to.",{multiValued:!0,required:!1}),w("assignableSubjectTypes","string","AppDev-owned hard ceiling of principal kinds (user, workload) that may hold this entitlement. Read-only to IAM tooling.",{multiValued:!0,required:!1,mutability:"readOnly",canonicalValues:["user","customer","workload"]}),w("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"]})]});if(J.supportsGroups)$.push({schemas:[$1],id:K9,name:"Group",description:"Group",meta:{resourceType:"Schema",location:z5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(K9)}`)},attributes:[w("id","string","Unique identifier for the Group.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),w("externalId","string","External identifier from the provisioning client.",{multiValued:!1,uniqueness:"none"}),w("displayName","string","Human-readable name for the Group.",{multiValued:!1,required:!0,uniqueness:"none"}),w("members","complex","Members of the Group.",{multiValued:!0,subAttributes:[w("value","string","Identifier of the member resource.",{multiValued:!1,required:!0}),w("$ref","reference","Reference to the member resource.",{multiValued:!1,referenceTypes:["User","Group"]}),w("display","string","Display name of the member.",{multiValued:!1}),w("type","string","Member type.",{multiValued:!1})]})]});return $}function y4(J,$,Z,X,Q,G,B,L,M,H,h,i,c,s,X5){let f={authz:X,settleAuthz:X5,accessStore:Q,accessIndex:G,catalogStore:B,codeCatalog:L,resources:M,log:$,iamDelta:i,onAccessMutation:c};if(!H&&!h)return;let C={...H,...h},t=C.users?.enabled!==!1,W5=C.groups?.enabled!==!1;if(Boolean(C.url||C.userStore||B||L)&&!Z)$.error("IAM requires workload identity for SCIM push/pull operations",{"ion.operation":"workload.require","ion.outcome":"failure"});function O5(){if(!Z)throw $.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 Z}async function T5(y){let U=O5(),m=y.headers.get("Authorization");if(!m?.startsWith("Bearer "))return!1;try{let d=m.substring(7);return(await U.validateToken(d)).valid}catch{return!1}}async function U5(){let y=O5(),U=typeof y.getServerToken==="function"?await y.getServerToken():await y.getToken();return new Headers({"Content-Type":Q1,Accept:Q1,Authorization:`Bearer ${U}`})}async function C5(y,U,m,d){if(!C.url)throw Error("IAM URL not configured for outgoing requests");let o=`${C.url}${U}`;try{let W=await U5(),j=await fetch(o,{method:y,headers:W,body:m?JSON.stringify(m):void 0}),K=await j.json();if(!j.ok)return{success:!1,error:K,status:j.status};let V=await d["~standard"].validate(K);if(V.issues)return $.error("SCIM response validation failed",{"ion.operation":"scim.response.validate","ion.outcome":"failure",validationIssues:V.issues}),{success:!1,error:{schemas:[X9],status:"400",scimType:"invalidValue",detail:`Response validation failed: ${V.issues.map((F)=>F.message).join("; ")}`},status:400};return{success:!0,data:V.value,status:j.status}}catch(W){return{success:!1,error:{schemas:[X9],status:"500",detail:W instanceof Error?W.message:"Unknown error occurred"},status:500}}}function k5(){return C.url}function f5(y,U){let m=b5(U?.usersUrl??C.usersUrl??"/api/iam/Users")??"/api/iam/Users",d=b5(U?.groupsUrl??C.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",o=b5(U?.discovery?.basePath??C.discovery?.basePath)??S4(m,d);if(!o)return;return{request:y,basePath:o,usersUrl:m,groupsUrl:d,supportsUsers:t&&Boolean(C.userStore),supportsGroups:W5&&Boolean(B||L)}}async function h5(y){let U=x4(y,C.discovery);return await C.discovery?.buildServiceProviderConfig?.(y,U)??U}async function E5(y){let U=R4(y);return await C.discovery?.buildResourceTypes?.(y,U)??U}async function S5(y){let U=b4(y);return await C.discovery?.buildSchemas?.(y,U)??U}async function M5(y,U){let m=f5(y,U);if(!m)return;let d=_1(new URL(y.url).pathname),{basePath:o}=m;if(d!==o&&!d.startsWith(`${o}/`))return;let W=_1(d.slice(o.length)||"/");if(!(W==="/ServiceProviderConfig"||W==="/ResourceTypes"||W.startsWith("/ResourceTypes/")||W==="/Schemas"||W.startsWith("/Schemas/")))return;if(y.method!=="GET")return g(405,"Method not allowed");if(!await T5(y))return g(401,"Authorization required");if(W==="/ServiceProviderConfig")return H5(await h5(m));if(W==="/ResourceTypes")return R5(await E5(m));if(W.startsWith("/ResourceTypes/")){let V=decodeURIComponent(W.slice(15)),F=(await E5(m)).find((O)=>O.id===V||O.name===V);return F?H5(F):g(404,"Resource not found")}if(W==="/Schemas")return R5(await S5(m));if(W.startsWith("/Schemas/")){let V=decodeURIComponent(W.slice(9)),F=(await S5(m)).find((O)=>O.id===V);return F?H5(F):g(404,"Resource not found")}return}let g5,m5;if(C.url)m5=async(U,m)=>{let d={...U,schemas:U.schemas??["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"]};return C5("POST","/Users",d,J.user)},g5={createGroup:async(U,m)=>{let d={schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],displayName:U,externalId:m?.id,members:m?.members};return C5("POST","/Groups",d,J.group)}};let L5;if(B||L){let y=F9(L,B),U=(N,Y,D)=>{let _=N[p]??{},z=a5(N),I=N.id,b=I?z5(Y,`${D}/${encodeURIComponent(I)}`):void 0,S={id:I??N.externalId??N.displayName,name:N.displayName,displayName:N.displayName,description:_.description??N.displayName,requestable:_.requestable,providerId:_.providerId??N.externalId,requestUrl:_.requestUrl,source:_.source,deprecated:_.deprecated,assignableSubjectTypes:_.assignableSubjectTypes,recommendedSubjectTypes:_.recommendedSubjectTypes},v=_.requestUrl??C.entitlementRequestUrl?.(S,z,{request:Y});return{...N,meta:{...N.meta,resourceType:"Group",location:b},[p]:{..._,requestUrl:v}}},m=(N)=>W9(L,N),d=async(N,Y)=>{if(!B){if(Y)throw Error(`Cannot persist access for code entitlement "${N.entity.id}": no AccessCatalogStore is wired.`);return N.entity}try{return await L9(N.kind,N.entity,G9(B,N.kind))}catch(D){if(Y)throw D;return $.warn("Code entitlement discovery materialization failed; serving the code template",{"ion.operation":"iam.catalog.materialize","ion.outcome":"degraded",entitlementId:N.entity.id,entitlementType:N.kind,error:_5(D)}),N.entity}},o=async(N)=>{if(!B)return;try{await i9(L,B,N)}catch(Y){$.warn("Retired code entitlement deprecation failed; serving the last durable row",{"ion.operation":"iam.catalog.deprecate","ion.outcome":"degraded",entitlementId:N,error:_5(Y)})}},W=(N,Y)=>g(403,`Entitlement "${N}" is declared in application code; its structural definition cannot be ${Y} through SCIM. IAM may change presentation and receipts, while code continues to own structure.`,"mutability"),j=(N)=>N.path==="members"||Boolean(N.path?.startsWith("members[")),K=(N)=>j(N)||N.path==="displayName"||N.path===`${p}.description`||N.path===`${p}.providerId`||N.path===`${p}.requestUrl`,V=(N)=>N?.[p]?.requestable===!0,F=(N)=>g(404,`Requestable Group ${N} not found`,"invalidValue"),O=async(N,Y)=>{if(!await T5(N))return g(401,"Authorization required");let _=new URL(N.url),z=Y?.basePath??"/Groups",I=_.pathname;if(I.startsWith(z))I=I.substring(z.length);let S=I.match(/^\/([^/]+)$/)?.[1],v=N.method;try{if(S)switch(v){case"GET":return await P(N,z,S);case"PUT":return await E(N,z,S);case"PATCH":return await x(N,z,S);case"DELETE":return await T(S);default:return g(405,"Method not allowed")}else if(I===""||I==="/")switch(v){case"GET":return await A(N,z);case"POST":return await R(N,z);default:return g(405,"Method not allowed")}return g(404,"Resource not found")}catch(q){if(q instanceof i5)return u9(q);if($9(q))return g(409,q.message,"uniqueness");return $.error("Groups inbound handler error",{"ion.operation":"scim.groups.handler","ion.outcome":"failure"},q),g(500,q instanceof Error?q.message:"Internal server error")}},A=async(N,Y)=>{let D=new URL(N.url),_=D.searchParams.get("startIndex"),z=D.searchParams.get("count"),I=_!=null?parseInt(_,10):void 0,b=z!=null?parseInt(z,10):void 0,S=I!=null&&!Number.isNaN(I)?Math.max(0,I-1):0,v=b!=null&&!Number.isNaN(b)?b:void 0,q=D.searchParams.get("filter"),k=d9(q);if(k!==void 0){await o();let n=await w4(y,Q,k,s),u=n?[U(n,N,Y)]:[];return R5(u,{totalResults:u.length,startIndex:1,itemsPerPage:u.length})}if(E4(q)?.requestable===!1)return R5([],{totalResults:0,startIndex:1,itemsPerPage:0});let J5={requestable:!0};if(L)await Promise.all([...L.groups.list().filter((n)=>n.requestable===!0).map((n)=>({entity:n,kind:"group"})),...L.roles.list().filter((n)=>n.requestable===!0).map((n)=>({entity:n,kind:"role"})),...L.permissions.list().filter((n)=>n.requestable===!0).map((n)=>({entity:n,kind:"permission"}))].map((n)=>d(n,!1)));await o();let a=await P4(y,Q,{start:S,limit:v,filter:J5},s);return R5(a.resources.map((n)=>U(n,N,Y)),{totalResults:a.total,startIndex:S+1,itemsPerPage:a.count})},P=async(N,Y,D)=>{let _=m(D);if(_&&_.entity.requestable!==!0)return F(D);if(_)await d(_,!1);await o(D);let z=await Z1(y,Q,D,s);if(!V(z))return F(D);return H5(U(z,N,Y))},R=async(N,Y)=>{let D=await N.json(),_=await n5(J.group,D);if(_.issues)return $.error("Group creation validation failed",{"ion.operation":"scim.group.create","ion.outcome":"failure",validationIssues:_.issues}),g(400,`Request validation failed: ${_.issues.map((a)=>a.message).join("; ")}`,"invalidValue");let z=_.value;if(!z.displayName)return g(400,"displayName is required","invalidValue");if(z[p]?.requestable===!1)return g(400,"SCIM may create only requestable entitlements; non-requestable definitions are App-owned.","invalidValue");if(z[p]={...z[p],requestable:!0},!B)return g(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 b=a5(z),S=n9();if(m(S))throw new M9(`id "${S}" is reserved by the code catalog`,"unique_violation","id");let v=r1(z),q=z1(new Map,N1(z.members,b,S,v)),k;await d5(f,async()=>{k=await J9(y,z,S)},q,{oaa:()=>e1(X,k,b)});let r=await y5(y,Q,b,S),J5=U(v5(k,b,r),N,Y);return H5(J5,201,J5.meta?.location)},E=async(N,Y,D)=>{let _=await N.json(),z=await n5(J.group,_);if(z.issues)return $.error("Group replacement validation failed",{"ion.operation":"scim.group.replace","ion.outcome":"failure",validationIssues:z.issues}),g(400,`Request validation failed: ${z.issues.map((u)=>u.message).join("; ")}`,"invalidValue");let I=z.value,b=a5(I),S=m(D);if(S&&S.entity.requestable!==!0)return F(D);if(S){if(await d(S,!0),H4(I,S))return W(D,"replaced")}let v=await Z1(y,Q,D);if(!V(v))return F(D);if(!S&&v[p]?.source==="code"&&D4(I,v))return W(D,"replaced");let q=S?.kind??b,k=S?B9(S.entity):r1(I),r=Q?(await Q.listByTarget(q,D)).items:[],J5=z1(M4(r),N1(I.members,q,D,k)),a;await d5(f,async()=>{a=await J9(y,I,D)},J5,{oaa:()=>e1(X,a,q)});let n=await y5(y,Q,q,D);return H5(U(v5(a,q,n),N,Y))},x=async(N,Y,D)=>{let _=m(D);if(_&&_.entity.requestable!==!0)return F(D);if(_)await d(_,!0);let z=await Z1(y,Q,D);if(!V(z))return F(D);let I=await N.json();if((_!==void 0||z[p]?.source==="code")&&(I.Operations??[]).some((u)=>!K(u)))return W(D,"patched");let S={...z};for(let u of I.Operations??[])if(u.op==="replace"&&u.path&&u.value!==void 0){if(u.path==="displayName")S.displayName=u.value;else if(u.path===`${p}.requestable`)S[p]={...S[p],requestable:Boolean(u.value)};else if(u.path===`${p}.description`)S[p]={...S[p],description:String(u.value)};else if(u.path===`${p}.providerId`)S[p]={...S[p],providerId:String(u.value)};else if(u.path===`${p}.requestUrl`)S[p]={...S[p],requestUrl:String(u.value)}}else if(u.op==="add"&&u.path==="members"&&u.value!==void 0){let w5=u.value;S.members=[...S.members??[],...w5]}else if(u.op==="remove"&&u.path?.startsWith("members[")){let w5=u.path.match(/members\[value eq "([^"]+)"\]/);if(w5)S.members=(S.members??[]).filter((Q5)=>Q5.value!==w5[1])}let v=await n5(J.group,S);if(v.issues)return $.error("Group patch validation failed",{"ion.operation":"scim.group.patch","ion.outcome":"failure",validationIssues:v.issues}),g(400,`Request validation failed: ${v.issues.map((u)=>u.message).join("; ")}`,"invalidValue");let q=_?.kind??a5(S),k=_?B9(_.entity):r1(S),r=z1(N1(z.members,q,D,k),N1(S.members,q,D,k)),J5,a=!_||(I.Operations??[]).some((u)=>!j(u));await d5(f,async()=>{if(a)J5=await J9(y,S,D)},r,a?{oaa:()=>e1(X,J5,q)}:void 0);let n=await Z1(y,Q,D);return H5(U(n,N,Y))},T=async(N)=>{let Y=m(N);if(Y&&Y.entity.requestable!==!0)return F(N);if(Y)await d(Y,!0);let D=await Z1(y,Q,N);if(!V(D))return F(N);let _=D[p];if((Y||_?.source==="code")&&_?.deprecated!==!0)return g(403,`Code-owned entitlement "${N}" can be deleted only after it is marked deprecated.`,"mutability");let z=a5(D);if(Q){let I=await Q.listByTarget(z,N),b=[];for(let S of I.items)await O1(f,S,b);await Y9(f,b)}return await I4(y,N),new Response(null,{status:204})};L5={handler:O}}let Y5;if(C.userStore){let{userStore:y,inboundUsers:U}=C,m=(Y)=>Y?.find((D)=>D.primary)?.value||Y?.[0]?.value,d=async(Y)=>{if(U?.mapBaseUserToScim)return await U.mapBaseUserToScim(Y);return t1(Y)},o=async(Y,D,_)=>{let z=await d(Y),I=z.id??Y.id;return{...z,id:I,meta:{...z.meta,resourceType:"User",location:I?z5(D,`${_}/${encodeURIComponent(I)}`):void 0}}},W=async(Y,D)=>{if(U?.mapValidatedScimToBaseUser)return await U.mapValidatedScimToBaseUser(Y,D);let _=new Date,z=m(Y.emails),I=Y.name?.formatted||[Y.name?.givenName,Y.name?.middleName,Y.name?.familyName].filter(Boolean).join(" ").trim()||Y.displayName,b=Y.id||D.existing?.id||n9(),S=Y.userName||z||D.existing?.userName||b,v=I||Y.displayName||D.existing?.name||S,q=Object.fromEntries(Object.entries(Y).filter(([n,u])=>n.startsWith("urn:")&&n!==K1&&n!==N5&&u!==void 0)),k=Y[N5],r=k?.ecid!==void 0&&k.ecid!==null?j1(k.ecid):D.existing?.ecid,J5=k?.accountClass??D.existing?.accountClass,a=D.existing?.sso;return{...D.existing??{},id:b,userName:S,name:v,email:z||D.existing?.email||S,avatar:Y.profileUrl,sso:{...a??{},profile:{...a?.profile??{},sub:b,iss:a?.profile.iss??"iam-provisioned",aud:a?.profile.aud??"iam-provisioned",exp:a?.profile.exp??Math.floor(Date.now()/1000)+3600,iat:a?.profile.iat??Math.floor(Date.now()/1000),email:z||D.existing?.email||S,email_verified:!0,name:v,preferred_username:S},tenant:a?.tenant??{id:"iam-provisioned",name:"IAM Provisioned"},scope:a?.scope??"openid profile email",tokenType:a?.tokenType??"Bearer",expires:a?.expires??new Date(Date.now()+3600000)},externalId:Y.externalId,ecid:r,accountClass:J5,displayName:Y.displayName,scimName:Y.name,emails:Y.emails,nickName:Y.nickName,title:Y.title,preferredLanguage:Y.preferredLanguage,locale:Y.locale,timezone:Y.timezone,active:Y.active,phoneNumbers:Y.phoneNumbers,ims:Y.ims,photos:Y.photos,addresses:Y.addresses,groups:Y.groups,entitlements:Y.entitlements,roles:Y.roles,x509Certificates:Y.x509Certificates,scimEnterprise:Y[K1],scimSchemaExtensions:Object.keys(q).length>0?q:void 0,createdAt:D.existing?.createdAt??(Y.meta?.created?new Date(Y.meta.created):_),updatedAt:Y.meta?.lastModified?new Date(Y.meta.lastModified):_,userType:Y.userType}},j=(Y,D,_)=>{Y[D]=_},K=(Y,D,_)=>{let z=Y[D];if(Array.isArray(z)){Y[D]=[...z,...Array.isArray(_)?_:[_]];return}if(z&&typeof z==="object"&&!Array.isArray(z)&&_&&typeof _==="object"&&!Array.isArray(_)){Y[D]={...z,..._};return}Y[D]=_},V=(Y,D,_)=>{let z=D.match(/^(urn:.*:(?:User|Group))(?::(.+))?$/),I=z?[z[1],...z[2]?.split(":")??[]]:D.split("."),b=Y;for(let v of I.slice(0,-1)){let q=b[v];if(q===void 0){if(!_)return null;b[v]={}}else if(q===null||typeof q!=="object"||Array.isArray(q)){if(!_)return null;b[v]={}}b=b[v]}let S=I.at(-1);if(!S)return null;return{parent:b,key:S}},F=(Y,D)=>{let _=D.op.toLowerCase();if(!D.path){if(_!=="remove"&&D.value&&typeof D.value==="object"&&!Array.isArray(D.value))Object.assign(Y,D.value);return}let z=D.path.match(/^([A-Za-z0-9]+)\[value eq "([^"]+)"\]$/);if(z&&_==="remove"){let[,b,S]=z,v=Y[b];if(Array.isArray(v))Y[b]=v.filter((q)=>!(q&&typeof q==="object"&&("value"in q)&&q.value===S));return}let I=V(Y,D.path,_!=="remove");if(!I)return;if(_==="remove"){delete I.parent[I.key];return}if(_==="add"){K(I.parent,I.key,D.value);return}j(I.parent,I.key,D.value)},O=async(Y,D)=>{if(!await T5(Y))return g(401,"Authorization required");let z=new URL(Y.url),I=D?.basePath??"/Users",b=z.pathname;if(b.startsWith(I))b=b.substring(I.length);let v=b.match(/^\/([^/]+)$/)?.[1],q=Y.method;try{if(v)switch(q){case"GET":return await P(Y,I,v);case"PUT":return await x(Y,I,v);case"PATCH":return await T(Y,I,v);case"DELETE":return await N(v);default:return g(405,"Method not allowed")}else if(b===""||b==="/")switch(q){case"GET":return await A(Y,I);case"POST":return await E(Y,I);default:return g(405,"Method not allowed")}return g(404,"Resource not found")}catch(k){if(k instanceof i5)return u9(k);if($9(k))return g(409,k.message,"uniqueness");return $.error("Users inbound handler error",{"ion.operation":"scim.users.handler","ion.outcome":"failure"},k),g(500,k instanceof Error?k.message:"Internal server error")}},A=async(Y,D)=>{let _=new URL(Y.url),z=_.searchParams.get("startIndex"),I=_.searchParams.get("count"),b=z!=null?parseInt(z,10):void 0,S=I!=null?parseInt(I,10):void 0,v=b!=null&&!Number.isNaN(b)?Math.max(0,b-1):0,q=S!=null&&!Number.isNaN(S)?S:void 0,k=d9(_.searchParams.get("filter"));if(k!==void 0){let a=await y.lookup({externalId:k}),n=a?[await o(a,Y,D)]:[];return R5(n,{totalResults:n.length,startIndex:1,itemsPerPage:n.length})}let r=await y.list({start:v,limit:q}),J5=await Promise.all(r.items.map((a)=>o(a,Y,D)));return R5(J5,{totalResults:r.total,startIndex:v+1,itemsPerPage:r.count})},P=async(Y,D,_)=>{let z=await y.get(_);if(!z)return g(404,`User ${_} not found`,"invalidValue");return H5(await o(z,Y,D))},R=async(Y,D)=>{let _=f.accessIndex;if(!_?.setSubjectDisabled||!D.id)return;let z=Y?Y.active??!0:!0,I=D.active??!0;if(Y&&z===I)return;if(!Y&&I)return;await _.setSubjectDisabled(D.id,"user",!I)},E=async(Y,D)=>{let _=await Y.json(),z=await n5(J.user,_);if(z.issues)return $.error("User creation validation failed",{"ion.operation":"scim.user.create","ion.outcome":"failure",validationIssues:z.issues}),g(400,`Request validation failed: ${z.issues.map((v)=>v.message).join("; ")}`,"invalidValue");let I=z.value;if(!I.userName&&!I.emails?.[0]?.value)return g(400,"userName or email is required","invalidValue");let b=await W(I,{mode:"create"});await d5(f,async()=>{await y.upsert(b),await R(void 0,b)},o1(void 0,b),{oaa:async()=>{await s1(X,b)},delta:async()=>{await f.iamDelta?.onUserUpsert(b)}});let S=await o(b,Y,D);return H5(S,201,S.meta?.location)},x=async(Y,D,_)=>{let z=await y.get(_);if(!z)return g(404,`User ${_} not found`,"invalidValue");let I=await Y.json(),b=await n5(J.user,I);if(b.issues)return $.error("User replacement validation failed",{"ion.operation":"scim.user.replace","ion.outcome":"failure",validationIssues:b.issues}),g(400,`Request validation failed: ${b.issues.map((q)=>q.message).join("; ")}`,"invalidValue");let S=b.value,v=await W({...S,id:_},{existing:z,mode:"replace"});return v.createdAt=z.createdAt,v.updatedAt=new Date,await d5(f,async()=>{await y.upsert(v),await R(z,v)},o1(z,v),{oaa:async()=>{await s1(X,v)},delta:async()=>{await c9(f.iamDelta,z,v)}}),H5(await o(v,Y,D))},T=async(Y,D,_)=>{let z=await y.get(_);if(!z)return g(404,`User ${_} not found`,"invalidValue");let b=(await Y.json()).Operations??[],v={...await d(z)};for(let r of b)F(v,r);let q=await n5(J.user,v);if(q.issues)return $.error("User patch validation failed",{"ion.operation":"scim.user.patch","ion.outcome":"failure",validationIssues:q.issues}),g(400,`Request validation failed: ${q.issues.map((r)=>r.message).join("; ")}`,"invalidValue");let k=await W(q.value,{existing:z,mode:"patch"});return k.updatedAt=new Date,await d5(f,async()=>{await y.upsert(k),await R(z,k)},o1(z,k),{oaa:async()=>{await s1(X,k)},delta:async()=>{await c9(f.iamDelta,z,k)}}),H5(await o(k,Y,D))},N=async(Y)=>{let D=await y.get(Y);if(!D)return g(404,`User ${Y} not found`,"invalidValue");if(Q){let _=await Q.listBySubject(Y,"user"),z=[];for(let I of _.items)await O1(f,I,z);await Y9(f,z)}if(await y.delete(Y),await f.accessIndex?.setSubjectDisabled?.(Y,"user",!1),D.externalId&&f.iamDelta?.isReady())await B1(f,"iam.delta.egress","IAM delta user delete failed after SCIM write; full aggregation will reconcile",()=>f.iamDelta?.onUserDelete(D.externalId)??Promise.resolve(),{id:Y,kind:"user"});else if(f.iamDelta?.isReady())f.log?.warn("IAM delta: deleted User has no externalId; destination delete skipped",{"ion.operation":"iam.delta.delete","ion.outcome":"skipped",id:Y,kind:"user"});if(f.authz.oaa.isReady())await B1(f,"authz.oaa.delete","OAA incremental user delete failed; full sync will reconcile",()=>f.authz.oaa.deleteUser(Y),{id:Y,kind:"user"});return new Response(null,{status:204})};Y5={handler:O}}async function p5(y,U){O5();let m=new URL(y.url).pathname,d=b5(U?.usersUrl??C.usersUrl??"/api/iam/Users")??"/api/iam/Users",o=b5(U?.groupsUrl??C.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",W=await M5(y,U);if(W)return W;let j=(K)=>m===K||m.startsWith(`${K}/`);if(j(d)){if(!t)return g(404,"SCIM Users endpoint is disabled by RemoteConfig");if(!Y5)return g(501,"SCIM Users endpoint is enabled by RemoteConfig but no user store capability is wired by the application.");return Y5.handler(y,{basePath:d})}if(j(o)){if(!W5)return g(404,"SCIM Groups endpoint is disabled by RemoteConfig");if(!L5)return g(501,"SCIM Groups endpoint is enabled by RemoteConfig but no AccessCatalogStore capability is wired by the application.");return L5.handler(y,{basePath:o})}return g(404,"Resource not found")}return{...C,createUser:m5,getBaseUrl:k5,groups_outbound:g5,groups_inbound:L5,users_inbound:Y5,handler:p5,delta:i}}function N9(J,$){let Z=new TextEncoder().encode(J),X=typeof $==="string"?new TextEncoder().encode($):$,Q=new Uint8Array(Z.length+1+X.length);return Q.set(Z,0),Q[Z.length]=46,Q.set(X,Z.length+1),Q}function v4(J){let $=J.replace(/-/g,"+").replace(/_/g,"/"),Z=$.length%4===0?"":"=".repeat(4-$.length%4),X=atob($+Z),Q=new Uint8Array(X.length);for(let G=0;G<X.length;G++)Q[G]=X.charCodeAt(G);return Q}function q4(J){let $="";for(let Z of J)$+=String.fromCharCode(Z);return btoa($).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function t9(J){let $=JSON.parse(J);if(!$||typeof $!=="object"||!Array.isArray($.keys))throw Error("Invalid JWKS: expected { keys: [...] }");return $}function U4(J){return JSON.stringify(J)}async function C4(J){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:J.x},{name:"Ed25519"},!0,["verify"])}async function k4(J){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:J.x,d:J.d},{name:"Ed25519"},!0,["sign"])}async function f4(J){let Z=(typeof J.jwks==="string"?t9(J.jwks):J.jwks).keys.find((X)=>X.kid===J.kid&&X.kty==="OKP"&&X.crv==="Ed25519");if(!Z?.x)return!1;try{let X=await C4(Z),Q=N9(J.requestId,J.rawBody),G=v4(J.signatureB64Url);return crypto.subtle.verify({name:"Ed25519"},X,G,Q)}catch{return!1}}async function h4(J){let $=await k4(J.privateKeyJwk),Z=N9(J.requestId,J.rawBody),X=await crypto.subtle.sign({name:"Ed25519"},$,Z);return q4(new Uint8Array(X))}async function g4(J){let $=await crypto.subtle.generateKey({name:"Ed25519"},!0,["sign","verify"]),Z=await crypto.subtle.exportKey("jwk",$.privateKey),Q=(await crypto.subtle.exportKey("jwk",$.publicKey)).x,G=Z.d;if(!Q||!G)throw Error("Failed to export Ed25519 key material (missing x/d)");return{privateJwk:{kty:"OKP",crv:"Ed25519",x:Q,d:G,kid:J,alg:"EdDSA",use:"sig"},publicJwks:{keys:[{kty:"OKP",crv:"Ed25519",x:Q,kid:J,alg:"EdDSA",use:"sig"}]}}}var G1={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 E1(J,$){if(typeof J!=="number"||!Number.isFinite(J))return $.default;let Z=Math.floor(J);if(Z<$.min)return $.min;if(Z>$.max)return $.max;return Z}function o9(J){return{ttlMs:E1(J?.ttlSeconds,G1.jwksTtlSeconds)*1000,maxEntries:E1(J?.maxEntries,G1.jwksMaxEntries)}}function r9(J){let $=J?.read;return{read:{enabled:$?.enabled===!0,ttlMs:E1($?.ttlSeconds,G1.sessionReadTtlSeconds)*1000,maxEntries:E1($?.maxEntries,G1.sessionReadMaxEntries)}}}function m4(J){return{jwks:o9(J?.jwks),session:r9(J?.session)}}function p4(J){let $={};if(!J)return $;let Z=J.split(";");for(let X of Z){let Q=X.trim();if(!Q)continue;let G=Q.indexOf("=");if(G===-1)continue;$[Q.slice(0,G).trim()]=Q.slice(G+1).trim()}return $}function s9(J){if(!J.expiresAt)return!1;let $=J.expiresAt instanceof Date?J.expiresAt:new Date(J.expiresAt);return!Number.isNaN($.getTime())&&Date.now()>$.getTime()}function u4(J){if(!J||typeof J!=="object"||Array.isArray(J))return;let{access_token:$,id_token:Z,refresh_token:X,tokens:Q,...G}=J;return G}function D5(J,$){let Z=J[$];return typeof Z==="string"?Z:""}function l4(J,$){let Z=J.exp;if(typeof Z==="number")return new Date(Z*1000);if(typeof Z==="string"&&Z.trim()){let X=Number(Z);if(!Number.isNaN(X))return new Date(X*1000)}if($ instanceof Date)return $;if($){let X=new Date($);if(!Number.isNaN(X.getTime()))return X}return new Date}function c4(J){let $=J.claims;if(!$?.sub||typeof $.sub!=="string")return;let Z=l4($,J.expiresAt);if(J.authType==="sso")return{id:$.sub,userName:D5($,"preferred_username"),name:D5($,"name"),email:D5($,"email"),avatar:D5($,"picture")||void 0,sso:{profile:$,tenant:{id:D5($,"idp")||D5($,"iss"),name:D5($,"iss")},tokenType:"Bearer",expires:Z}};return{id:$.sub,userName:D5($,"preferred_username"),name:D5($,"name"),email:D5($,"email"),avatar:D5($,"picture")||void 0,userType:"customer",ciam:{profile:$,scope:"openid profile email",tokenType:"Bearer",expires:Z}}}function d4(J){if(J.authType!=="sso"&&J.authType!=="ciam")return;if(s9(J))return;return{sid:J.sid,authType:J.authType,tenantId:typeof J.tenantId==="string"?J.tenantId:void 0,sub:J.sub,expiresAt:J.expiresAt,createdAt:J.createdAt,claims:u4(J.claims)}}function n4(J,$){if(!J.endsWith(".session"))return!1;if(!$||$.length===0)return!0;return $.some((Z)=>J===`${Z}.session`)}function a4(J){if(J===void 0)return;let $=(Array.isArray(J)?J:[J]).map((Z)=>Z.trim()).filter((Z)=>Z.length>0);return $.length>0?$:void 0}async function e9(J,$,Z){return(await J2(J,$,Z)).map(d4).filter((Q)=>Boolean(Q))}async function J2(J,$,Z){let X=p4(J.headers.get("cookie")),Q=a4(Z?.cookiesPrefix),G=[],B=new Set;for(let[L,M]of Object.entries(X)){if(!n4(L,Q)||!M)continue;if(B.has(M))continue;B.add(M);let H=await $.get(M);if(!H)continue;if(H.authType!=="sso"&&H.authType!=="ciam")continue;if(s9(H))continue;G.push(H)}return G}async function i4(J,$,Z){return(await e9(J,$,Z)).map(c4).filter((Q)=>Boolean(Q))}var t4="@ionite/core",o4=c5(M1(t4));async function r4(J,$){let Z=await P5({idToken:J,jwksUri:$.jwksUri,issuer:$.issuer,audience:$.audience}),X=await o4.validate(Z);if(X.issues)throw Error(`ID token claims validation failed: ${X.issues.map((B)=>B.message).join("; ")}`);let Q=X.value;if(Q===void 0)throw Error("ID token claims missing");return $2(Q)}function Z5(J){return Date.now()-J}function z9(J){if(J instanceof Error)return{"error.name":J.name,"error.message":J.message};return{"error.name":typeof J,"error.message":String(J)}}function w1(J,$){if(!J)return{};try{let Z=new URL(J);return{[`${$}.origin`]:Z.origin,[`${$}.path`]:Z.pathname}}catch{return{[`${$}.path`]:J.startsWith("/")?J:`/${J}`}}}function P1(J,$=5){if(!Array.isArray(J))return[String(J)];return J.slice(0,$).map((Z)=>{if(!Z||typeof Z!=="object")return String(Z);let X=Z,Q=Array.isArray(X.path)?X.path.join("."):String(X.path??""),G=typeof X.message==="string"?X.message:String(X.message??"validation failed");return Q?`${Q}: ${G}`:G})}function s4(J){if(!J||typeof J!=="object")return{};let $=J;return{oidc_error:typeof $.error==="string"?$.error:void 0,oidc_error_description:typeof $.error_description==="string"?$.error_description:void 0,oidc_error_uri:typeof $.error_uri==="string"?$.error_uri:void 0}}function e4(J,$={}){let Z=typeof J==="string"?J:J?.headers.get("cookie")??void 0;if(!Z)return[];let Q=`${$.cookiePrefix??"ion.sso"}.`,G=new Set;for(let B of Object.keys($J(Z))){if(!B.startsWith(Q))continue;let L=B.slice(Q.length),M=L.lastIndexOf(".");if(M<=0)continue;let H=L.slice(0,M).trim();if(H)G.add(H)}return Array.from(G)}function JJ(J,$,Z,X,Q){if(!Z&&!X)return;let G=new WeakMap,B=new Map,L={...Z,...X},M=!!(L.authority&&L.tokenUrl&&L.authorizationUrl&&L.clientId&&L.redirectUri&&L.scope),H={...L,authority:M?l(L.authority,"Missing 'authority' from SSO Config"):L.authority,tokenUrl:M?l(L.tokenUrl,"Missing 'tokenUrl' from SSO Config"):L.tokenUrl,authorizationUrl:M?l(L.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"):L.authorizationUrl,clientId:M?l(L.clientId,"Missing 'clientId' from SSO Config"):L.clientId,redirectUri:M?l(L.redirectUri,"Missing 'redirectUri' from SSO Config"):L.redirectUri,scope:M?l(L.scope,"Missing 'scope' from SSO Config"):L.scope,responseType:L.responseType??"code",cookiesSecure:L.cookiesSecure!==void 0?L.cookiesSecure:!0,cookiesSameSite:L.cookiesSameSite!==void 0?L.cookiesSameSite:"Strict",cookiesPrefix:L.cookiesPrefix??(L.clientId?`ion.sso.${L.clientId}`:"ion.sso"),cookiesPath:L.cookiesPath??"/"},h=Math.min(600,Math.max(0,Math.floor(Number(H.rotationGraceSeconds??60))||0))*1000;function i(){let W=[];if(!H.authority)W.push("authority");if(!H.tokenUrl)W.push("tokenUrl");if(!H.authorizationUrl)W.push("authorizationUrl");if(!H.clientId)W.push("clientId");if(!H.redirectUri)W.push("redirectUri");if(!H.scope)W.push("scope");if(W.length>0)throw Error(`Missing OIDC configuration fields: ${W.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 c(W){if(!H)throw Error("ionite SSO Manager not initialized");let j=G.get(W);if(j)return j;let K=s(W);return G.set(W,K),K}async function s(W){try{let{tokens:j,session:K,refreshedUser:V}=await Y5(W);if(!j)return{status:"unauthenticated"};if(V)return{status:"authenticated",value:V};if(K?.claims)return{status:"authenticated",value:O5(K.claims,j,M5(K.expiresAt))};return{status:"unauthenticated"}}catch(j){if(Z2(j))return{status:"unauthenticated"};return $.error("Error parsing user from cookies",{"ion.operation":"cookie.parse","ion.outcome":"degraded"},j),{status:"degraded",error:j instanceof Error?j:void 0}}}async function X5(W){let j=await c(W);return j.status==="authenticated"?j.value:void 0}async function f(W){if(!H)throw Error("ionite SSO Manager not initialized");i();let j=l(H.redirectUri,"Missing 'redirectUri' from SSO Config"),K=l(H.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"),V=l(H.clientId,"Missing 'clientId' from SSO Config"),F=l(H.scope,"Missing 'scope' from SSO Config"),O=H.cookiesSecure?W.url.replace(/^http:\/\//,"https://"):W.url,A=V5(),P=V5(64),R=V5(),E=j;try{new URL(E)}catch{if(O)try{let D=new URL(O),_=E.startsWith("//")?E.slice(1):E.startsWith("/")?E:`/${E}`;E=new URL(_,D.origin).toString()}catch{try{let D=new URL(K),_=E.startsWith("//")?E.slice(1):E.startsWith("/")?E:`/${E}`;E=new URL(_,D.origin).toString()}catch{throw Error(`Invalid redirectUri: "${j}". It must be a valid absolute URL.`)}}}let x=new URL(K);x.searchParams.append("client_id",V),x.searchParams.append("redirect_uri",E),x.searchParams.append("response_type","code"),x.searchParams.append("scope",F),x.searchParams.append("state",A),x.searchParams.append("nonce",R);let T=await J1(P);x.searchParams.append("code_challenge",T),x.searchParams.append("code_challenge_method","S256");let N=await H.beforeLogin?.({request:W}),Y=N===void 0?{state:A,codeVerifier:P,nonce:R}:{state:A,codeVerifier:P,nonce:R,context:N};return new Response("Redirecting to SSO Provider",{status:302,headers:{Location:x.toString(),"Set-Cookie":y(d(A),Y,H.loginStateTtl??600,"Lax")}})}async function K5(W){if(!H)throw Error("ionite SSO Manager not initialized");let j;try{j=await X5(W)}catch{j=void 0}let K=await H.beforeLogout?.({request:W,user:j}),V=m("session",W),F;try{F=await Y5(W);let T=F.tokens?.refresh_token??m("refresh",W);if(T)await k5(T)}catch(T){$.warn("Failed to revoke token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},T)}if(H.sessionStore)try{let T=F?.sid??V;if(T)await H.sessionStore.delete(T)}catch(T){$.warn("Failed to delete session",{"ion.operation":"session.delete","ion.outcome":"degraded"},T)}let O=[["Set-Cookie",U("session")]],A=await H.afterLogout?.({request:W,context:K}),P=I5(A,"/",W.url);if(P.response){let T=new Headers(P.response.headers);for(let[,N]of O)T.append("Set-Cookie",N);return new Response(P.response.body,{status:P.response.status,statusText:P.response.statusText,headers:T})}let R=P.location??"/",E=W.headers.get("accept");if(E?.includes("application/json")||E?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:R}),{status:200,headers:[["Content-Type","application/json"],...O]});return new Response("Logged out",{status:302,headers:[["Location",R],...O]})}async function C(W){if(!H)throw Error("ionite SSO Manager not initialized");if(!H.sessionStore)throw Error("Back-Channel Logout requires sessionStore configuration");try{if(!W.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 K=await W.text(),F=new URLSearchParams(K).get("logout_token");if(!F)return new Response("Missing logout_token parameter",{status:400});let O=l(H.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify logout tokens."),A=l(H.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify logout tokens."),P=H.jwksUri||`${O}/protocol/openid-connect/certs`,R=await u1({logoutToken:F,jwksUri:P,issuer:O,audience:A,log:$}),E=typeof R.sid==="string"?R.sid:void 0;if(!E)return $.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 H.sessionStore.delete(E),$.info("Back-Channel Logout: successfully deleted session",{"ion.module":"sso",sid:E}),new Response("OK",{status:200})}catch(j){return $.error("Error during back-channel logout",{"ion.operation":"backchannel_logout","ion.outcome":"failure"},j),new Response("Internal Server Error",{status:500})}}async function t(W){if(!H)throw Error("ionite SSO Manager not initialized");let j=Date.now(),K=new URL(W.url),V=new URLSearchParams(K.search);$.debug("SSO callback received",{"ion.event":"ion.sso.callback.received","ion.module":"sso","ion.operation":"sign_in.callback","http.method":W.method,"url.path":K.pathname,hasCode:V.has("code"),hasState:V.has("state"),hasError:V.has("error"),...w1(V.get("iss")??void 0,"oidc.issuer")});let F=Object.fromEntries(V.entries()),O=await J.callbackParams.validate(F);if(O.issues)return $.warn("SSO callback parameter validation failed",{"ion.event":"ion.sso.callback.validation_failed","ion.operation":"sign_in.callback","ion.outcome":"failure","validation.issues":P1(O.issues)}),X2(O.issues,"OIDC callback parameters validation failed");let{code:A,state:P}=O.value,R;try{let E=l(P,'OIDC "state" was not present in the callback parameters'),x=m(d(E),W,!0),{codeVerifier:T,state:N,nonce:Y,context:D}=x??{};R=D,$.debug("SSO callback state cookie read",{"ion.event":"ion.sso.callback.state_cookie_read","ion.module":"sso","ion.operation":"sign_in.callback",hasStateCookie:Boolean(x),hasCodeVerifier:Boolean(T),hasStateVerifier:Boolean(N),hasNonce:Boolean(Y),hasContext:D!==void 0});let _=l(T,'OIDC "codeVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');l(N,'OIDC "stateVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');let z=l(Y,'OIDC "nonce" was not present in cookies, ensure that the SSO login was initiated correctly'),I=l(A,'OIDC "code" was not present in the callback parameters');if(P!==N)throw $.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');$.debug("SSO callback state verified",{"ion.event":"ion.sso.callback.state_verified","ion.module":"sso","ion.operation":"sign_in.callback"});let b=H.cookiesSecure?W.url.replace(/^http:\/\//,"https://"):W.url,S=await U5(I,_,b),{tokenExpiresAt:v,sessionExpiresAt:q}=W5(S);S.expires=v.toISOString();let k=Date.now();$.debug("SSO ID token parsing started",{"ion.event":"ion.sso.id_token.parse_started","ion.module":"sso","ion.operation":"id_token.parse"});let r=await q5(S,z,q);$.debug("SSO ID token parsing completed",{"ion.event":"ion.sso.id_token.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":Z5(k),"user.id":r.id});let J5,a;{let Q5=E5("SSO requires sessionStore configuration for opaque session cookies."),u5=typeof r.sso.profile.sid==="string"?r.sso.profile.sid:void 0,t5=u5||V5(32),F5=r.id;if($.debug("SSO session creation evaluated",{"ion.event":"ion.sso.session.create_evaluated","ion.module":"sso","ion.operation":"session.create",hasSid:Boolean(t5),hasIdpSid:Boolean(u5),hasSub:Boolean(F5),"user.id":F5}),!F5)throw Error("Session creation failed: missing sub in ID token claims");let T1=Date.now(),L1={sid:t5,sub:F5,idpSid:u5,authType:"sso",tenantId:H.tenantId,tokens:S,claims:r.sso.profile,expiresAt:q,createdAt:new Date};await S5(Q5,L1),a=L1,J5=["Set-Cookie",y("session",t5,q)],$.info("SSO session created",{"ion.event":"ion.sso.session.created","ion.operation":"session.create","ion.outcome":"success","duration.ms":Z5(T1),"user.id":F5})}if(H.userStore)try{let Q5=r.id;if(Q5){let u5=new Date,t5=Date.now();$.debug("SSO user store lookup started",{"ion.event":"ion.sso.user.lookup_started","ion.module":"sso","ion.operation":"user.lookup","user.id":Q5});let F5=await H.userStore.get(Q5);if($.debug("SSO user store lookup completed",{"ion.event":"ion.sso.user.lookup_completed","ion.module":"sso","ion.operation":"user.lookup","duration.ms":Z5(t5),"user.id":Q5,found:Boolean(F5)}),F5||H.enableJitUserProvisioning){let T1=Date.now(),L1={...F5??{},...r,id:Q5,tenantId:F5?.tenantId,createdAt:F5?.createdAt??u5,updatedAt:u5};await H.userStore.upsert(L1),$.info("SSO user stored",{"ion.event":"ion.sso.user.stored","ion.operation":"user.store","ion.outcome":"success","duration.ms":Z5(T1),"user.id":Q5,existing:Boolean(F5),jitProvisioning:Boolean(H.enableJitUserProvisioning)})}else $.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":Q5})}else $.warn("User storage skipped: missing sub in ID token claims",{"ion.event":"ion.sso.user.skipped","ion.operation":"user.store","ion.outcome":"skipped"})}catch(Q5){$.warn("Failed to store user",{"ion.event":"ion.sso.user.store_failed","ion.operation":"user.store","ion.outcome":"degraded",...z9(Q5)})}$.info("SSO sign-in succeeded",{"ion.event":"ion.sso.sign_in.succeeded","ion.operation":"sign_in.callback","ion.outcome":"success","duration.ms":Z5(j),"user.id":r.id});let n=[["Set-Cookie",U(d(E))],...J5?[J5]:[]],u=await H.afterLogin?.({ok:!0,request:W,user:r,session:a,context:R}),w5=I5(u,"/",W.url);if(w5.response)return x5(w5.response,n.map(([,Q5])=>Q5));return new Response("Authentication successful, redirecting",{status:302,headers:[["Location",w5.location],...n]})}catch(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":Z5(j),...z9(E)});let x=P?[["Set-Cookie",U(d(P))]]:[],T=await H.afterLogin?.({ok:!1,request:W,error:E,context:R}),N=I5(T,"/",W.url);if(N.response)return x5(N.response,x.map(([,Y])=>Y));return new Response("Authentication failed, redirecting",{status:302,headers:[["Location",N.location],...x]})}}function W5(W){let j=Date.now(),K=Number(W.expires_in??3600)||3600,V=new Date(j+K*1000),F;if(W.refresh_expires_in!=null&&Number.isFinite(Number(W.refresh_expires_in)))F=Number(W.refresh_expires_in);else if(W.refresh_token)F=86400;else F=K;return{tokenExpiresAt:V,sessionExpiresAt:new Date(j+F*1000)}}async function q5(W,j,K){if(!H)throw Error("ionite SSO Manager not initialized");let V=Date.now(),F=await h5(W.id_token,j);return $.debug("SSO user parsed from ID token",{"ion.event":"ion.sso.user.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":Z5(V),"user.id":F.sub,hasEmail:Boolean(F.email),hasName:Boolean(F.name)}),O5(F,W,K)}function O5(W,j,K){let V=K??W5(j).sessionExpiresAt,F=W.ecid!==void 0&&W.ecid!==null?j1(W.ecid):void 0;return{id:W.sub,userName:W.preferred_username||"",name:W.name||"",email:W.email||"",emails:[{value:W.email||"",primary:!0}],...F?{ecid:F}:{},avatar:W.picture,sso:{profile:{...W},tenant:{id:W.idp||W.iss||"",name:W.iss||""},scope:j.scope,tokenType:j.token_type,sessionState:j.session_state,expires:V}}}async function T5(W){if(!H.userStore)return W;let j=await H.userStore.lookup(W);if(!j)return W;return{...W,...j,id:W.id,sso:W.sso}}async function U5(W,j,K){if(!H)throw Error("ionite SSO Manager not initialized");i();let V=l(H.tokenUrl,"Missing 'tokenUrl' from SSO Config"),F=l(H.redirectUri,"Missing 'redirectUri' from SSO Config"),O=l(H.clientId,"Missing 'clientId' from SSO Config"),A=F;try{new URL(A)}catch{if(K)try{let R=new URL(K),E=A.startsWith("//")?A.slice(1):A.startsWith("/")?A:`/${A}`;A=new URL(E,R.origin).toString()}catch{try{let R=new URL(V),E=A.startsWith("//")?A.slice(1):A.startsWith("/")?A:`/${A}`;A=new URL(E,R.origin).toString()}catch{throw Error(`Invalid redirectUri: "${F}". It must be a valid absolute URL.`)}}}let P=new URLSearchParams;if(P.append("grant_type","authorization_code"),P.append("code",W),P.append("redirect_uri",A),P.append("client_id",O),H.clientSecret)P.append("client_secret",H.clientSecret);P.append("code_verifier",j);try{let R=Date.now();$.debug("SSO token exchange started",{"ion.event":"ion.sso.token.exchange_started","ion.module":"sso","ion.operation":"token.exchange",...w1(V,"oidc.token_url"),...w1(A,"oidc.redirect_uri"),hasClientSecret:Boolean(H.clientSecret)});let E=await fetch(V,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:P.toString()});$.debug("SSO token exchange response received",{"ion.event":"ion.sso.token.response_received","ion.module":"sso","ion.operation":"token.exchange","http.status_code":E.status,"duration.ms":Z5(R)}),$.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 x=await E.json();if($.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":Z5(R)}),!E.ok){$.error("Token exchange error",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":E.status,"duration.ms":Z5(R),...s4(x)});let N=x;throw Error(`Token exchange failed: ${N.error||E.statusText} - ${N.error_description||""}`.trim())}let T=await J.tokenResponse.validate(x);if(T.issues)throw $.error("Token response validation failed",{"ion.event":"ion.sso.token.response_validation_failed","ion.operation":"token.exchange","ion.outcome":"failure","duration.ms":Z5(R),"validation.issues":P1(T.issues)}),Error(`Token response validation failed: ${T.issues}`);return $.debug("SSO token exchange completed",{"ion.event":"ion.sso.token.exchange_completed","ion.module":"sso","ion.operation":"token.exchange","ion.outcome":"success","duration.ms":Z5(R),tokenType:T.value.token_type,hasAccessToken:Boolean(T.value.access_token),hasIdToken:Boolean(T.value.id_token),hasRefreshToken:Boolean(T.value.refresh_token),expiresIn:T.value.expires_in}),T.value}catch(R){throw $.error("Error during token exchange",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure",...z9(R)}),R}}async function C5(W){return k1(async()=>{if(!H)throw Error("ionite SSO Manager not initialized");i();let j=l(H.tokenUrl,"Missing 'tokenUrl' from SSO Config"),K=l(H.clientId,"Missing 'clientId' from SSO Config"),V=new URLSearchParams;V.append("grant_type","refresh_token"),V.append("refresh_token",W),V.append("client_id",K);let F=await fetch(j,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:V.toString()}),O=await F.json();if(!F.ok){$.error("Token refresh error",{"ion.operation":"token.refresh","ion.outcome":"failure",response:O});let P=O;throw Error(`Token refresh failed: ${P.error||F.statusText} - ${P.error_description||""}`.trim())}let A=await J.tokenResponse.validate(O);if(A.issues)throw $.error("Token refresh response validation failed",{"ion.event":"ion.sso.token.refresh_validation_failed","ion.operation":"token.refresh","ion.outcome":"failure","validation.issues":P1(A.issues)}),Error(`Token refresh response validation failed: ${A.issues}`);return A.value},void 0,void 0,void 0,$)}async function k5(W){try{if(!H)throw Error("ionite SSO Manager not initialized");if(!H.revocationEndpoint)return;let j=l(H.clientId,"Missing 'clientId' from SSO Config"),K=new URLSearchParams;K.append("token",W),K.append("token_type_hint","refresh_token"),K.append("client_id",j);let V=await fetch(H.revocationEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:K.toString()});if(!V.ok)$.warn("Token revocation failed",{"ion.operation":"token.revoke","ion.outcome":"degraded",status:V.status,statusText:V.statusText});else $.info("Token revoked successfully",{"ion.module":"sso"})}catch(j){$.warn("Error revoking token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},j)}}async function f5(){if(!H)throw Error("ionite SSO Manager not initialized");let W=H.authority;if(!H.jwksUri&&!W)throw Error("Missing 'jwksUri' or 'authority' from SSO Config. OIDC configuration is required for this operation.");let j=H.jwksUri||`${W}/protocol/openid-connect/certs`;return r5(j,$)}async function h5(W,j){let K=Date.now(),V=l(H.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify ID tokens."),F=l(H.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify ID tokens."),O=H.jwksUri||`${V}/protocol/openid-connect/certs`;$.debug("SSO ID token verification started",{"ion.event":"ion.sso.id_token.verify_started","ion.module":"sso","ion.operation":"id_token.verify",...w1(O,"oidc.jwks_uri")});let A;try{A=await P5({idToken:W,jwksUri:O,issuer:V,audience:F,expectedNonce:j,log:$})}catch(R){throw $.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":Z5(K)},R),R}$.debug("SSO ID token signature verified",{"ion.event":"ion.sso.id_token.signature_verified","ion.module":"sso","ion.operation":"id_token.verify","duration.ms":Z5(K)});let P=await J.idTokenClaims.validate(A);if(P.issues)throw $.error("ID token claims validation failed",{"ion.event":"ion.sso.id_token.validation_failed","ion.operation":"id_token.validate","ion.outcome":"failure","duration.ms":Z5(K),"validation.issues":P1(P.issues)}),Error(`ID token claims validation failed: ${P.issues}`);return $.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":Z5(K),"user.id":P.value.sub,hasIssuer:Boolean(P.value.iss),hasAudience:Boolean(P.value.aud)}),P.value}function E5(W="SSO sessionStore is required for opaque session cookies."){if(!H.sessionStore)throw Error(W);return H.sessionStore}async function S5(W,j){try{await W.create(j)}catch(K){if(!await W.get(j.sid))throw K;await W.update(j.sid,j)}}function M5(W){if(!W)return;if(W instanceof Date)return W;let j=new Date(W);return Number.isNaN(j.getTime())?void 0:j}function g5(W){let j=W.tokens;if(!j?.access_token||!j.id_token||!j.token_type)return;return j}async function m5(W,j=!1){let K=E5(),V=m("session",W);if(!V)return{tokens:void 0,refreshHeaders:[]};let F=await K.get(V);if(F&&H.tenantId&&F.tenantId&&F.tenantId!==H.tenantId)return{tokens:void 0,refreshHeaders:[["Set-Cookie",U("session")]],sid:V};if(F?.authType!=="sso")return{tokens:void 0,refreshHeaders:[["Set-Cookie",U("session")]],sid:V};let O=g5(F);if(!O)return{tokens:void 0,refreshHeaders:[["Set-Cookie",U("session")]],sid:V};let A=M5(F.expiresAt);if(A?Date.now()>A.getTime():!1)return await K.delete(V),{tokens:void 0,sid:V,refreshHeaders:[["Set-Cookie",U("session")]]};let R=M5(O.expires),E=R?Date.now()>R.getTime():!0;if((j||E)&&O.refresh_token)return L5(V,F,O);return{tokens:O,sid:V,session:F,refreshHeaders:[]}}function L5(W,j,K){let V=B.get(W);if(V)return V;let F=E5(),O=(async()=>{let A=await C5(K.refresh_token),{tokenExpiresAt:P,sessionExpiresAt:R}=W5(A);A.expires=P.toISOString();let E=await q5(A,void 0,R),x=E.sso.profile,T=V5(32),N={...j,sid:T,tokens:A,claims:x,expiresAt:R,createdAt:new Date};await S5(F,N);try{if(h<=0)await F.delete(W);else{let{refresh_token:Y,...D}=K;await F.update(W,{tokens:D,expiresAt:new Date(Date.now()+h)})}}catch(Y){$.warn("Failed to retire rotated SSO session record",{"ion.operation":"session.rotate","ion.outcome":"degraded"},Y)}return{tokens:A,sid:T,session:N,refreshedUser:E,refreshHeaders:[["Set-Cookie",y("session",T,R)]]}})();return B.set(W,O),O.finally(()=>{B.delete(W)})}async function Y5(W,j=!1){return m5(W,j)}async function p5(W){let{tokens:j}=await Y5(W);if(!j)return;return j.access_token}function y(W,j,K,V=H.cookiesSameSite??"Strict"){if(!H)throw Error("ionite SSO Manager not initialized");if(W=`${H.cookiesPrefix}.${W}`,typeof j!=="string")j=btoa(JSON.stringify(j));let F;if(K instanceof Date)F=`Expires=${K.toUTCString()}`;else if(typeof K==="number")F=`Max-Age=${K}`;else throw Error("Invalid expires type",K);if(j.length>4000)throw Error(`Error setting cookie: ${W}. Cookie length is: ${j.length}`);return`${W}=${j}; ${F}; Path=${H.cookiesPath}; HttpOnly;${H.cookiesSecure?" Secure;":""} SameSite=${V};`}function U(W){if(!H)throw Error("ionite SSO Manager not initialized");return`${H.cookiesPrefix}.${W}=; Max-Age=0; Path=${H.cookiesPath}; HttpOnly;${H.cookiesSecure?" Secure;":""} SameSite=${H.cookiesSameSite};`}function m(W,j,K=!1){if(!H)throw Error("ionite SSO Manager not initialized");let V=j.headers.get("cookie");if(!V)return null;let F=`${H.cookiesPrefix}.${W}`,O=V.split(";").find((E)=>E.trim().startsWith(`${F}=`));if(!O)return null;let A=O.indexOf("="),P=O.slice(A+1).trim();if(!K)return P;let R=atob(P);return JSON.parse(R)}function d(W){return`state_${W}`}async function o(W,j){if(!H)throw Error("ionite SSO Manager not initialized");let{loginUrl:K,userUrl:V,tokenUrl:F,refreshUrl:O,logoutUrl:A,logoutBackChannelUrl:P,jwksUrl:R,redirectUri:E}={...H,...j},x=new URL(W.url).pathname;if(E){let T;try{T=new URL(E).pathname}catch{try{let N=new URL(W.url),Y=E.startsWith("//")?E.slice(1):E;T=new URL(Y,N.origin).pathname}catch{T=E.startsWith("/")?E:`/${E}`}}if(T===x)return t(W)}if(K===x)return f(W);if(V===x)try{let{tokens:T,session:N,refreshedUser:Y,refreshHeaders:D}=await Y5(W);if(!T)return new Response("User not logged in",{status:401,headers:D});let _=Y??(N?.claims?O5(N.claims,T,M5(N.expiresAt)):void 0);if(!_)return new Response("User not logged in",{status:401,headers:D});let z=await T5(_);return new Response(JSON.stringify(z),{headers:[["Content-Type","application/json"],...D]})}catch(T){if(Z2(T))return new Response("User not logged in",{status:401});return $.error("Error resolving SSO user",{"ion.operation":"sso.user","ion.outcome":"degraded"},T),new Response(JSON.stringify({error:"auth_unavailable"}),{status:503,headers:{"Content-Type":"application/json"}})}if(F===x){let{tokens:T,refreshHeaders:N}=await Y5(W);if(!T)return new Response("User not logged in",{status:401,headers:N});return new Response(JSON.stringify({token:T.access_token,expires:T.expires}),{headers:[["Content-Type","application/json"],...N]})}if(O===x){let{tokens:T,refreshHeaders:N}=await Y5(W,!0);if(!T)return new Response("User not logged in",{status:401});return new Response("Refresh Complete",{status:200,headers:N})}if(A===x)return K5(W);if(P===x)return C(W);if(R===x){let T=await f5();return new Response(JSON.stringify(T),{headers:[["Content-Type","application/json"]]})}return new Response("Not Found",{status:404})}return{...H,getUser:X5,resolveUser:c,getJwt:p5,initiateLogin:f,logout:K5,logoutBackChannel:C,callbackHandler:t,handler:o}}function $J(J){let $={},Z=J.split(";");for(let X of Z){let Q=X.trim();if(!Q)continue;let G=Q.indexOf("=");if(G===-1)continue;let B=Q.slice(0,G).trim(),L=Q.slice(G+1).trim();$[B]=L}return $}function Z2(J){if(!(J 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(($)=>J.message.includes($))}function Q2(J){return J=J??"SSO Unavailable",new Response(JSON.stringify({error:J}),{status:503,statusText:J,headers:{"Content-Type":"application/json"}})}var I1="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.";async function ZJ(J,$){return l($,I1),$.sso?.getUser(J)}async function XJ(J,$){return l($,I1),await $.sso?.resolveUser(J)??{status:"unauthenticated"}}async function QJ(J,$){l($,I1);let Z=$.sso;if(!Z)return Q2();return Z.initiateLogin(J)}async function KJ(J,$){l($,I1);let Z=$.sso;if(!Z)return Q2();return Z.callbackHandler(J)}export{x5 as withSetCookies,r4 as verifyUser,u1 as verifyLogoutToken,f4 as verifyLfvSignature,P5 as verifyIdToken,U4 as stringifyLfvJwks,JJ as sso,h4 as signLfvPayload,w2 as setJwksRetry,E2 as setJwksClock,C2 as setDiscoveryClock,WJ as sendTenantWebhook,n1 as sameOriginRedirectRules,XJ as resolveUser,r9 as resolveSessionCacheConfig,a1 as resolveRedirect,b1 as resolveProviderBranding,o9 as resolveJwksCacheConfig,S2 as resolveJwkForKid,o2 as resolveCustomer,V1 as resolveCiamProvider,d2 as resolveCapturedRedirect,m4 as resolveCacheConfig,I5 as resolveAfterRedirect,D9 as reconcileSubjectAccess,J1 as pkceChallengeFromVerifier,t9 as parseLfvJwks,y1 as orderedEnabledProviders,e5 as normalizeOidcIssuer,e4 as listSsoClientIdsFromCookies,f9 as isRedirectAllowed,QJ as initiateLogin,y4 as iam,_2 as hasScope,D2 as hasRole,H2 as hasPermission,M2 as hasGroup,O2 as hasAnyScope,N2 as hasAny,j2 as hasAllScope,z2 as hasAll,V2 as has,h1 as getVerificationKeyForKid,ZJ as getUser,x2 as getPublicKeyFromJwks,R2 as getPublicKeyForKid,R1 as getProviderPreset,r5 as getJwks,i4 as getDiscoveredSessionUsers,t2 as getCustomer,f1 as getCachedVerificationKey,g4 as generateLfvEd25519KeyPair,d1 as generateAppleClientSecret,c1 as fetchUserInfo,H9 as expandRoot,p1 as exchangeAuthorizationCode,i1 as entitlementToScimGroup,e9 as discoverSessions,J2 as discoverSessionRecords,l1 as discoverOidcEndpoints,l2 as defaultRedirectPolicies,A2 as configureJwksCache,YJ as collectReferencedDefinitions,T2 as clearJwksCache,k2 as clearDiscoveryCache,i2 as ciam,c2 as captureRedirect,KJ as callback,N9 as buildLfvSigningInput,m1 as buildAuthorizationUrl,U9 as blockDangerousUrls,t1 as baseUserToScimUser,y9 as assertTrustedIdTokenClaims,k9 as allowSameOrigin,C9 as allowRelativePaths,p2 as allowOrigins,u2 as allowHosts,BJ as InMemoryTenantStore,V9 as CatalogAdjacencyCache,E9 as CIAM_PROVIDER_PRESETS,G1 as CACHE_BOUNDS};
1
+ import{A as p9,B as M1,C as c5,D as c,E as K2,I as _1,M as X2,O as z9,P as X9,S as WJ,T as LJ,U as p,V as Q9,X as D5,a as A9,d as t9,h as L9,i as F9,k as V9,l as o9,m as H9,n as B5,o as G1,p as D9,q as M9,r as N9,s as GJ,y as j1,z as m9}from"./shared/core-15896f6h.js";var B2="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.",j9=["user","customer","workload"],G2={user:async(J,$)=>$.sso?.getUser(J),customer:async(J,$)=>$.ciam?.getCustomer(J),workload:async(J,$)=>{let Z=await $.workload?.getWorkloadIdentity?.(J);if(!Z)return;let X=Z.clientId??Z.workloadId??Z.claims.sub;return X?{...Z,id:X}:void 0}};function W2(J){if(J==="any")return j9;let $=Array.isArray(J)?J:[J];return j9.filter((Z)=>$.includes(Z))}function L2(J){let $=J.headers.get("cookie");if(!$)return[];return $.split(";").map((Z)=>Z.slice(0,Z.indexOf("=")===-1?Z.length:Z.indexOf("=")).trim()).filter(Boolean)}function F2(J,$){let Z=J.headers.get("authorization")?.toLowerCase().startsWith("bearer ")??!1,X=L2(J),K=new Set;for(let G of X){if(G.startsWith("ion.sso"))K.add("user");if(G.startsWith("ion.ciam"))K.add("customer")}let W=X.length>0&&!K.has("user")&&!K.has("customer");return $.filter((G)=>{if(G==="workload")return Z;if(X.length===0)return!1;return K.has(G)||W})}function s(J){return typeof J==="string"?J:J.id}function E9(J){let{subject:$,subjectType:Z}=J,X;if(Z==="user")X=$.sso?.scope;else if(Z==="customer")X=$.ciam?.scope;else if(Z==="workload")X=$.scope;return new Set((X??"").split(/\s+/).filter(Boolean))}function b1(J,$,Z){let X=E9(J),K=$.filter((G)=>X.has(G));return{allow:Z==="any"?K.length>0:$.length>0&&K.length===$.length,metadata:{reason:"scope",wantedScopes:$,matchedScopes:K}}}function l5(J,$){return(Z)=>{if(J.length===0)return;let X=E9(Z),K=J.filter((G)=>X.has(G));return($==="any"?K.length>0:K.length===J.length)?K:void 0}}function F1(J,$,Z){return(X)=>{if($.length===0||X.subjectType!=="workload")return;let K=A9(J.config?.authz,X.subject);if(!K)return;let W=$.filter((L)=>K.has(L));return(Z==="any"?W.length>0:W.length===$.length)?W:void 0}}function V2(J,$){if(J.subjectType==="workload"){let Z=J.subject.scopesAsEntitlements;if(typeof Z==="boolean")return Z}return $.config?.authz?.scopesAsEntitlements===!0}function R1(J,$,Z,X,K){return{allow:Z==="ok",subject:$?.subject,subjectType:$?.subjectType,reason:Z,decision:X,response(){if(Z==="ok")return new Response(null,{status:204});if(Z==="unauthenticated")return J.log.warn("authz.denied",{reason:Z,...K()}),Response.json({error:"Unauthorized"},{status:401});if(Z==="not_configured")return J.log.warn("authz.denied",{reason:Z,subject:$?.subject?.id,subjectType:$?.subjectType,...K()}),Response.json({error:"not_configured"},{status:503});return J.log.warn("authz.denied",{reason:Z,subject:$?.subject?.id,subjectType:$?.subjectType,...K()}),Response.json({error:"Forbidden"},{status:403})}}}function H2(J,$,Z){return new Promise((X)=>{let K=[],W=J.length,G=!1,L=()=>{if(W-=1,W===0&&!G)G=!0,X({outcomes:K})};for(let D of J)$(D).then((H)=>{if(K.push({principal:D,decision:H}),!G&&H.allow){G=!0,X({matched:{principal:D,decision:H},outcomes:K});return}L()},(H)=>{Z?.(D,H),K.push({principal:D,decision:{allow:!1,metadata:{reason:"error"}}}),L()})})}async function A5(J,$,Z,X,K,W,G){c($,B2);let L=F2(J,W2(Z)),H=(await Promise.all(L.map(async(v)=>{let i=await G2[v](J,$);return i?.id?{subject:i,subjectType:v,subjectId:i.id}:void 0}))).filter((v)=>v!==void 0);if(H.length===0)return R1($,void 0,"unauthenticated",void 0,K);let k=async(v)=>{let i=$.authz.accessIndex;if(!i?.isSubjectDisabled)return!1;return i.isSubjectDisabled(v.subjectId,v.subjectType)},a=async(v)=>{if(G){let i=G(v);if(i&&i.length>0){if(await k(v))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"trusted-client",matchedPermissions:i}}}}if(W&&V2(v,$)){let i=W(v);if(i&&i.length>0){if(await k(v))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"scope",matchedScopes:i}}}}return X(v)},{matched:n,outcomes:o}=await H2(H,a,(v,i)=>{$.log.warn("authz.check_error",{"ion.operation":"authz.check","ion.outcome":"error",subject:v.subjectId,subjectType:v.subjectType,error:i instanceof Error?i.message:String(i),...K()})});if(n){if(n.decision.metadata?.reason==="scope")$.log.info("authz.scope_honor",{"ion.operation":"authz.scope_honor","ion.outcome":"allow",subject:n.principal.subjectId,subjectType:n.principal.subjectType,matchedScopes:n.decision.metadata.matchedScopes,...K()});return R1($,n.principal,"ok",n.decision,K)}let Z5=o.length>0&&o.every((v)=>{let i=v.decision.metadata?.reason;return i==="access_index_not_configured"||i==="error"}),C=o[0],Q5=Z5?"not_configured":"forbidden";return R1($,C?.principal,Q5,C?.decision,K)}async function D2(J,$,Z,X,K,W="any"){return A5(J,$,W,(G)=>$.authz.has(G.subjectId,Z,X,K,G.subjectType),()=>({targetType:Z,target:s(X),resource:K?s(K):void 0}),K?void 0:l5([s(X)],"any"),Z==="permission"&&!K?F1($,[s(X)],"any"):void 0)}async function M2(J,$,Z,X,K="any"){return A5(J,$,K,(W)=>$.authz.hasPermission(W.subjectId,Z,X,W.subjectType),()=>({targetType:"permission",target:s(Z),resource:X?s(X):void 0}),X?void 0:l5([s(Z)],"any"),X?void 0:F1($,[s(Z)],"any"))}async function N2(J,$,Z,X,K="any"){return A5(J,$,K,(W)=>$.authz.hasRole(W.subjectId,Z,X,W.subjectType),()=>({targetType:"role",target:s(Z),resource:X?s(X):void 0}),X?void 0:l5([s(Z)],"any"))}async function z2(J,$,Z,X,K="any"){return A5(J,$,K,(W)=>$.authz.hasGroup(W.subjectId,Z,X,W.subjectType),()=>({targetType:"group",target:s(Z),resource:X?s(X):void 0}),X?void 0:l5([s(Z)],"any"))}async function _2(J,$,Z,X="any"){let K=Z.filter((G)=>!G.resource).map((G)=>s(G.target)),W=Z.filter((G)=>!G.resource&&G.targetType==="permission").map((G)=>s(G.target));return A5(J,$,X,(G)=>$.authz.hasAny(G.subjectId,Z,G.subjectType),()=>({targets:Z.map((G)=>`${G.targetType}:${s(G.target)}`)}),K.length>0?l5(K,"any"):void 0,W.length>0?F1($,W,"any"):void 0)}async function O2(J,$,Z,X="any"){let K=Z.length>0&&Z.every((L)=>!L.resource),W=Z.length>0&&Z.every((L)=>!L.resource&&L.targetType==="permission"),G=Z.map((L)=>s(L.target));return A5(J,$,X,(L)=>$.authz.hasAll(L.subjectId,Z,L.subjectType),()=>({targets:Z.map((L)=>`${L.targetType}:${s(L.target)}`)}),K?l5(G,"all"):void 0,W?F1($,G,"all"):void 0)}async function j2(J,$,Z,X="any"){return A5(J,$,X,(K)=>Promise.resolve(b1(K,[Z],"any")),()=>({scope:Z}))}async function A2(J,$,Z,X="any"){return A5(J,$,X,(K)=>Promise.resolve(b1(K,Z,"any")),()=>({scopes:Z}))}async function E2(J,$,Z,X="any"){return A5(J,$,X,(K)=>Promise.resolve(b1(K,Z,"all")),()=>({scopes:Z}))}function J5(J){return typeof J==="string"&&J.length>0?J:void 0}function w9(J){let $=J5(J.email);return{sub:String(J.sub??""),email:$,name:J5(J.name),userName:J5(J.preferred_username)??$,avatar:J5(J.picture)}}var P9={oidc:{flow:"id_token",scope:"openid profile email",branding:{displayName:"Single sign-on"},mapClaims:w9},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:w9},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:(J)=>{let $=J5(J.email)??J5(J.preferred_username);return{sub:String(J.sub??J.oid??""),email:$,name:J5(J.name),userName:J5(J.preferred_username)??$,avatar:J5(J.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:(J)=>{let $=J5(J.email);return{sub:String(J.sub??""),email:$,name:J5(J.name),userName:$}}},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:(J)=>({sub:String(J.id??J.node_id??""),email:J5(J.email),name:J5(J.name)??J5(J.login),userName:J5(J.login),avatar:J5(J.avatar_url)})}};function y1(J){if(J==="magic-link")return;return P9[J]}function V1(J,$){if($.type==="magic-link")return;let Z=y1($.type);if(!Z)return;return{name:J,type:$.type,flow:Z.flow,authorizationUrl:$.authorizationUrl??Z.authorizationUrl,tokenUrl:$.tokenUrl??Z.tokenUrl,jwksUri:$.jwksUri??Z.jwksUri,userInfoUrl:$.userInfoUrl??Z.userInfoUrl,scope:$.scope??Z.scope,clientId:$.clientId,clientSecret:$.clientSecret,extraAuthParams:Z.extraAuthParams,branding:{...Z.branding,...$.branding},mapClaims:Z.mapClaims,config:$}}function v1(J){return{...y1(J.type)?.branding??{displayName:J.type},...J.branding}}function q1(J){if(!J)return[];return Object.entries(J).filter(([,$])=>$.enabled!==!1).map(([$,Z],X)=>({name:$,config:Z,index:X})).sort(($,Z)=>{let X=$.config.order??Number.MAX_SAFE_INTEGER,K=Z.config.order??Number.MAX_SAFE_INTEGER;if(X!==K)return X-K;return $.index-Z.index}).map(({name:$,config:Z})=>({name:$,config:Z}))}var T9=600000,C1=256,K5=new Map;function w2(J){if(typeof J?.ttlMs==="number"&&Number.isFinite(J.ttlMs))T9=Math.min(Math.max(J.ttlMs,60000),86400000);if(typeof J?.maxEntries==="number"&&Number.isFinite(J.maxEntries)){C1=Math.max(1,Math.floor(J.maxEntries));while(K5.size>C1){let $=K5.keys().next().value;if($===void 0)break;K5.delete($)}}}function I9(J,$){K5.delete(J),K5.set(J,$);while(K5.size>C1){let Z=K5.keys().next().value;if(Z===void 0)break;K5.delete(Z)}}var o5=new Map,k1=()=>Date.now();function P2(J){k1=J??(()=>Date.now())}var f1={};function I2(J){f1=J??{}}function T2(J){if(!J)return;if(/\bno-store\b/i.test(J))return 60000;let $=/max-age\s*=\s*(\d+)/i.exec(J);if(!$)return;let Z=Number($[1]);return Number.isFinite(Z)?Z*1000:void 0}function S2(J){let Z=T2(J)??T9;return Math.min(Math.max(Z,60000),86400000)}async function h1(J,$=3,Z=1000,X=30000,K){let W=Error("Placeholder Error");for(let G=0;G<=$;G++)try{return await J()}catch(L){if(W=L instanceof Error?L:Error(String(L)),L instanceof Error&&L.message.includes("400"))throw L;if(G===$)throw W;let D=Math.min(Z*2**G,X),H=Math.random()*0.1*D;await new Promise((k)=>setTimeout(k,D+H)),K?.warn(`Retry attempt ${G+1} after ${D+H}ms delay`)}throw W}async function r5(J,$,Z){let X=K5.get(J);if(!Z?.forceRefresh&&X&&X.expiresAt>k1())return I9(J,X),X.jwks;let K=o5.get(J);if(K)return K;let W=(async()=>{try{return await h1(async()=>{let G=await fetch(J);if(!G.ok)throw Error("Failed to fetch JWKS");let L=await G.json(),D=S2(G.headers.get("cache-control"));return I9(J,{jwks:L,expiresAt:k1()+D,importedKeys:new Map}),L},f1.maxRetries,f1.baseDelayMs,void 0,$)}catch(G){let L=K5.get(J);if(L)return $?.warn("JWKS refresh failed; serving last-known-good keys",{"ion.operation":"jwks.refresh","ion.outcome":"degraded"}),L.jwks;throw G}finally{o5.delete(J)}})();return o5.set(J,W),W}function x2(J){if(J){K5.delete(J),o5.delete(J);return}K5.clear(),o5.clear()}async function R2(J,$,Z){return(await S9(J,$,Z)).jwk}async function S9(J,$,Z){if(!$?.trim())throw Error("JWT header missing kid");await r5(J,Z);let X=K5.get(J),K=X?.jwks.keys.find((W)=>W.kid===$);if(!K)await r5(J,Z,{forceRefresh:!0}),X=K5.get(J),K=X?.jwks.keys.find((W)=>W.kid===$);if(!X||!K)throw Error("Public key not found");return{jwk:K,entry:X}}async function g1(J,$,Z,X,K){let{jwk:W,entry:G}=await S9(J,$,K),L=`${$}\x00${Z}`,D=G.importedKeys.get(L);if(D)return D;let H=X(W);return H.catch(()=>{if(G.importedKeys.get(L)===H)G.importedKeys.delete(L)}),G.importedKeys.set(L,H),H}async function b2(J,$){let Z=J.keys.find((X)=>X.kid===$);if(!Z)throw Error("Public key not found");return x9(Z)}function x9(J){return crypto.subtle.importKey("jwk",{kty:J.kty,n:J.n,e:J.e},{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},!1,["verify"])}async function y2(J,$,Z){return g1(J,$,"rs256",x9,Z)}var U1={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 m1(J,$,Z,X){if(typeof Z!=="string"||!(Z in U1))throw Error(`Unsupported JWT alg "${String(Z)}" (allowed: ${Object.keys(U1).join(", ")})`);let K=U1[Z];return{key:await g1(J,$,`oidc:${Z}`,(G)=>{if(G.kty!==K.kty)throw Error(`JWK type "${G.kty}" does not match token alg "${Z}"`);if(K.kty==="EC"){let L=G;if(L.crv!==K.crv)throw Error(`JWK curve "${String(L.crv)}" does not match token alg "${Z}"`);return crypto.subtle.importKey("jwk",{kty:"EC",crv:L.crv,x:L.x,y:L.y},K.importParams,!1,["verify"])}return crypto.subtle.importKey("jwk",{kty:G.kty,n:G.n,e:G.e},K.importParams,!1,["verify"])},X),algorithm:K.verifyParams}}function F5(J=32){let $=new Uint8Array(J);return crypto.getRandomValues($),Array.from($,(Z)=>Z.toString(16).padStart(2,"0")).join("").substring(0,J)}function H1(J){let $="";return J.forEach((Z)=>{$+=String.fromCharCode(Z)}),btoa($).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function y9(J){let $=J.replace(/-/g,"+").replace(/_/g,"/"),Z=$.padEnd($.length+(4-$.length%4)%4,"="),X=atob(Z),K=new Uint8Array(X.length);for(let W=0;W<X.length;W++)K[W]=X.charCodeAt(W);return K}function R9(J){let $=new TextDecoder().decode(y9(J));return JSON.parse($)}async function J1(J){let $=new TextEncoder().encode(J),Z=await crypto.subtle.digest("SHA-256",$);return H1(new Uint8Array(Z))}function u1(J){let $=new URL(J.authorizationUrl);if($.searchParams.set("client_id",J.clientId),$.searchParams.set("redirect_uri",J.redirectUri),$.searchParams.set("response_type","code"),$.searchParams.set("scope",J.scope),$.searchParams.set("state",J.state),J.codeChallenge)$.searchParams.set("code_challenge",J.codeChallenge),$.searchParams.set("code_challenge_method","S256");if(J.nonce)$.searchParams.set("nonce",J.nonce);for(let[Z,X]of Object.entries(J.extraParams??{}))$.searchParams.set(Z,X);return $.toString()}async function l1(J){let $=new URLSearchParams;if($.append("grant_type","authorization_code"),$.append("code",J.code),$.append("redirect_uri",J.redirectUri),$.append("client_id",J.clientId),J.clientSecret)$.append("client_secret",J.clientSecret);if(J.codeVerifier)$.append("code_verifier",J.codeVerifier);let Z=await fetch(J.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:$.toString()}),X=await Z.json();if(!Z.ok){let K=X;throw J.log?.error("OIDC authorization-code exchange failed",{"ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":Z.status,oidc_error:K.error}),Error(`Token exchange failed: ${K.error||Z.statusText} - ${K.error_description||""}`.trim())}if(typeof X.access_token!=="string")throw Error("Token exchange response missing access_token");return X}var v9=60;function e5(J){return J.trim().replace(/\/$/,"")}function q9(J){let{claims:$,audience:Z}=J,X=e5(J.issuer),K=J.nowSec??Math.floor(Date.now()/1000),W=J.clockSkewSec??v9,G=$.iss;if(typeof G!=="string"||e5(G)!==X)throw Error("ID token issuer mismatch");let L=$.aud,D=Array.isArray(L)?L.includes(Z):typeof L==="string"&&L===Z,H=typeof $.azp==="string"&&$.azp===Z;if(!D&&!H)throw Error("ID token audience mismatch");if(typeof $.exp!=="number")throw Error("ID token missing exp");if($.exp<K-W)throw Error("ID token expired");if(J.expectedNonce!==void 0){if($.nonce!==J.expectedNonce)throw Error("ID token nonce mismatch")}}async function U9(J,$,Z){let X=J.split(".");if(X.length!==3)throw Error("Invalid JWT");let K=R9(X[0]),W=R9(X[1]),G=y9(X[2]),{key:L,algorithm:D}=await m1($,K.kid,K.alg,Z),H=new TextEncoder().encode(`${X[0]}.${X[1]}`);if(!await crypto.subtle.verify(D,L,G,H))throw Error("Invalid JWT signature");return{header:K,payload:W}}async function I5(J){let{payload:$}=await U9(J.idToken,J.jwksUri,J.log);return q9({claims:$,issuer:J.issuer,audience:J.audience,clockSkewSec:J.clockSkewSec,expectedNonce:J.expectedNonce}),$}var v2="http://schemas.openid.net/event/backchannel-logout";async function c1(J){let{payload:$}=await U9(J.logoutToken,J.jwksUri,J.log),Z=e5(J.issuer),X=$.iss;if(typeof X!=="string"||e5(X)!==Z)throw Error("Logout token issuer mismatch");let K=$.aud,W=Array.isArray(K)?K.includes(J.audience):typeof K==="string"&&K===J.audience,G=typeof $.azp==="string"&&$.azp===J.audience;if(!W&&!G)throw Error("Logout token audience mismatch");if($.nonce!=null)throw Error("Logout token must not contain a nonce");let L=$.events;if(!(typeof L==="object"&&L!==null&&!Array.isArray(L)&&Object.hasOwn(L,v2)))throw Error("Logout token missing back-channel logout event");let H=typeof $.sid==="string"&&$.sid.length>0,k=typeof $.sub==="string"&&$.sub.length>0;if(!H&&!k)throw Error("Logout token missing sid and sub");if(typeof $.exp==="number"){let a=Math.floor(Date.now()/1000),n=J.clockSkewSec??v9;if($.exp<a-n)throw Error("Logout token expired")}return $}var q2=3600000,U2=60000,C2=86400000,k2=256,E5=new Map,s5=new Map;function b9(J,$){E5.delete(J),E5.set(J,$);while(E5.size>k2){let Z=E5.keys().next().value;if(Z===void 0)break;E5.delete(Z)}}var p1=()=>Date.now();function f2(J){p1=J??(()=>Date.now())}function h2(J){if(J){E5.delete(J),s5.delete(J);return}E5.clear(),s5.clear()}function g2(J){let $=J?/max-age\s*=\s*(\d+)/i.exec(J):null,Z=$?Number($[1]):Number.NaN,X=Number.isFinite(Z)?Z*1000:q2;return Math.min(Math.max(X,U2),C2)}async function d1(J){let $=E5.get(J);if($&&$.expiresAt>p1())return b9(J,$),$.endpoints;let Z=s5.get(J);if(Z)return Z;let X=(async()=>{try{let K=J.replace(/\/$/,""),W=await fetch(`${K}/.well-known/openid-configuration`,{headers:{Accept:"application/json"}});if(!W.ok)throw Error(`OIDC discovery failed for ${J} with status ${W.status}`);let G=await W.json(),L={authorizationUrl:typeof G.authorization_endpoint==="string"?G.authorization_endpoint:void 0,tokenUrl:typeof G.token_endpoint==="string"?G.token_endpoint:void 0,jwksUri:typeof G.jwks_uri==="string"?G.jwks_uri:void 0,userInfoUrl:typeof G.userinfo_endpoint==="string"?G.userinfo_endpoint:void 0};return b9(J,{endpoints:L,expiresAt:p1()+g2(W.headers.get("cache-control"))}),L}catch(K){let W=E5.get(J);if(W)return W.endpoints;throw K}finally{s5.delete(J)}})();return s5.set(J,X),X}async function n1(J,$){let Z=await fetch(J,{headers:{Authorization:`Bearer ${$}`,Accept:"application/json","User-Agent":"ionite-ciam"}});if(!Z.ok)throw Error(`UserInfo request failed with status ${Z.status}`);return await Z.json()}function m2(J){let $=J.replace(/-----BEGIN [^-]+-----/g,"").replace(/-----END [^-]+-----/g,"").replace(/\s+/g,""),Z=atob($),X=new Uint8Array(Z.length);for(let K=0;K<Z.length;K++)X[K]=Z.charCodeAt(K);return X}async function a1(J){let $=Math.floor(Date.now()/1000),Z={alg:"ES256",kid:J.keyId,typ:"JWT"},X={iss:J.teamId,iat:$,exp:$+(J.expiresInSeconds??3600),aud:"https://appleid.apple.com",sub:J.clientId},K=H1(new TextEncoder().encode(JSON.stringify(Z))),W=H1(new TextEncoder().encode(JSON.stringify(X))),G=`${K}.${W}`,L=await crypto.subtle.importKey("pkcs8",m2(J.privateKey),{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),D=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},L,new TextEncoder().encode(G));return`${G}.${H1(new Uint8Array(D))}`}function p2(J){for(let $=0;$<J.length;$++){let Z=J.charCodeAt($);if(Z<=31||Z===127)return!0}return!1}function u2(J,$){let Z=null;try{Z=new URL(J,$)}catch{Z=null}let X="";try{X=new URL($).origin}catch{X=""}return{candidate:J,url:Z,requestOrigin:X}}function C9(J,$,Z){let X=u2(J,Z),K=!1;for(let W of $){let G=W(X);if(G==="deny")return!1;if(G==="allow")K=!0}return K}function k9(){return({candidate:J,url:$})=>{if(p2(J))return"deny";if(J.includes("\\"))return"deny";if(J.startsWith("//"))return"deny";if(!$)return"deny";if($.protocol!=="http:"&&$.protocol!=="https:")return"deny";if($.username||$.password)return"deny";return"abstain"}}function f9(){return({candidate:J})=>J.startsWith("/")&&!J.startsWith("//")&&!J.startsWith("/\\")?"allow":"abstain"}function h9(){return({url:J,requestOrigin:$})=>J&&$&&J.origin===$?"allow":"abstain"}function l2(...J){let $=new Set(J.map((Z)=>{try{return new URL(Z).origin}catch{return Z}}));return({url:Z})=>Z&&$.has(Z.origin)?"allow":"abstain"}function c2(...J){let $=J.map((Z)=>Z.toLowerCase());return({url:Z})=>{if(!Z)return"abstain";let X=Z.hostname.toLowerCase();for(let K of $)if(K.startsWith(".")){if(X===K.slice(1)||X.endsWith(K))return"allow"}else if(X===K)return"allow";return"abstain"}}function i1(){return[k9(),f9(),h9()]}function g9(J,$,Z){if(!J)return!1;return C9(J,$,Z)}function t1(J,$){if(!J)return $.fallback;return C9(J,$.rules,$.requestUrl)?J:$.fallback}var d2={rules:i1(),fallback:"/"};function n2(J,$,Z="redirect"){let X=new URL(J.url).searchParams.get(Z)??void 0;return g9(X,$.rules,J.url)?{redirect:X}:void 0}function a2(J,$){let Z=J.context;return t1(Z?.redirect,{rules:$.rules,fallback:$.fallback,requestUrl:J.request.url})}function T5(J,$,Z){if(J instanceof Response)return{response:J};if(typeof J==="string")return{location:t1(J,{rules:i1(),fallback:$,requestUrl:Z})};return{location:$}}function R5(J,$){if($.length===0)return J;let Z=new Headers(J.headers);for(let X of $)Z.append("Set-Cookie",X);return new Response(J.body,{status:J.status,statusText:J.statusText,headers:Z})}var D1="ciam",i2="id_token",t2="access_token";function o2(J,$,Z,X,K,W){if(!Z&&!X)return;let G=new WeakMap,L={...Z,...X},D={...L,magicLinkTtl:L.magicLinkTtl??3600,sessionTtl:L.sessionTtl??86400,cookiesSecure:L.cookiesSecure!==void 0?L.cookiesSecure:!0,cookiesSameSite:L.cookiesSameSite!==void 0?L.cookiesSameSite:"Strict",cookiesPrefix:L.cookiesPrefix??(L.ciamId?`ion.ciam.${L.ciamId}`:"ion.ciam"),cookiesPath:L.cookiesPath??"/"};function H(){if(!D.sessionStore)throw Error("Missing CIAM configuration field: sessionStore. CIAM sessionStore is required for server-side session tracking and first-party logout.");return D.sessionStore}function k(){H()}let a=J.callbackParams??c5(m9("ionite.ciam")),n=J.idTokenClaims??c5(M1("ionite.ciam")),o=J.tokenResponse??c5(p9("ionite.ciam"));function Z5(Q=32){let B=new Uint8Array(Q);return crypto.getRandomValues(B),Array.from(B,(F)=>F.toString(16).padStart(2,"0")).join("").substring(0,Q)}function C(Q,B,F,z=D.cookiesSameSite??"Strict"){if(!D)throw Error("ionite CIAM Manager not initialized");if(Q=`${D.cookiesPrefix}.${Q}`,typeof B!=="string")B=btoa(JSON.stringify(B));let O;if(F instanceof Date)O=`Expires=${F.toUTCString()}`;else if(typeof F==="number")O=`Max-Age=${F}`;else throw Error("Invalid expires type",F);if(B.length>4000)throw Error(`Error setting cookie: ${Q}. Cookie length is: ${B.length}`);return`${Q}=${B}; ${O}; Path=${D.cookiesPath}; HttpOnly;${D.cookiesSecure?" Secure;":""} SameSite=${z};`}function Q5(Q){if(!D)throw Error("ionite CIAM Manager not initialized");return`${D.cookiesPrefix}.${Q}=; Max-Age=0; Path=${D.cookiesPath}; HttpOnly;${D.cookiesSecure?" Secure;":""} SameSite=${D.cookiesSameSite};`}function v(Q,B,F=!1){if(!D)throw Error("ionite CIAM Manager not initialized");let z=B.headers.get("cookie");if(!z)return null;let O=`${D.cookiesPrefix}.${Q}`,w=z.split(";").find((P)=>P.trim().startsWith(`${O}=`));if(!w)return null;let T=w.indexOf("="),E=w.substring(T+1).trim();if(!F)return E;try{let P=atob(E);return JSON.parse(P)}catch(P){return $.error("[CIAM] Failed to parse cookie",{"ion.operation":"cookie.parse","ion.outcome":"failure",cookieName:O},P),null}}function i(Q){return`cstate_${Q}`}async function G5(Q,B,F,z){let O=await D.afterLogin?.({...B,request:Q,context:F}),w=T5(O,"/",Q.url);if(w.response)return R5(w.response,z.map(([,T])=>T));return new Response(B.ok?"Authentication successful, redirecting":"Authentication failed, redirecting",{status:302,headers:[["Location",w.location],...z]})}function U5(Q,B){return["Set-Cookie",C("session",Q,B)]}function z5(Q){if(!Q)return;if(Q instanceof Date)return Q;let B=new Date(Q);return Number.isNaN(B.getTime())?void 0:B}async function w5(Q){let B=v("session",Q);if(!B)return;let F=await H().get(B);if(F&&D.tenantId&&F.tenantId&&F.tenantId!==D.tenantId)return;if(F?.authType!=="ciam")return;let z=z5(F.expiresAt);if(z&&Date.now()>z.getTime()){await H().delete(B);return}return F}async function P5(Q){if(!D)throw Error("ionite CIAM Manager not initialized");k();let B=G.get(Q);if(B)return B;let F=C5(Q);return G.set(Q,F),F}async function C5(Q){try{let B=await w5(Q);if(!B?.claims?.sub)return{status:"unauthenticated"};return{status:"authenticated",value:_5(B.claims)}}catch(B){return $.error("CIAM session resolution failed",{"ion.operation":"ciam.session","ion.outcome":"degraded"},B),{status:"degraded",error:B instanceof Error?B:void 0}}}async function k5(Q){let B=await P5(Q);return B.status==="authenticated"?B.value:void 0}async function f5(Q){if(!D)throw Error("ionite CIAM Manager not initialized");k();let B;try{B=await k5(Q)}catch{B=void 0}let F=await D.beforeLogout?.({request:Q,user:B});try{let I=v("session",Q);if(I)await H().delete(I)}catch(I){$.warn("Failed to delete CIAM session",{"ion.operation":"session.delete","ion.outcome":"degraded"},I)}let z=[["Set-Cookie",Q5("session")]],O=await D.afterLogout?.({request:Q,context:F}),w=T5(O,"/",Q.url);if(w.response)return R5(w.response,z.map(([,I])=>I));let T=w.location??"/",E=Q.headers.get("accept");if(E?.includes("application/json")||E?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:T}),{status:200,headers:[["Content-Type","application/json"],...z]});return new Response("Logged out",{status:302,headers:[["Location",T],...z]})}function h5(Q){return Q.id||Q.email||`ciam-${Q.userName}`}function g5(Q,B,F){return{sub:h5(Q),iss:D1,aud:D1,typ:i2,exp:Math.floor(F.getTime()/1000),iat:Math.floor(Date.now()/1000),email:Q.email,name:Q.name,preferred_username:Q.userName,picture:Q.avatar,sid:B}}function m5(Q,B,F){return{sub:Q,iss:D1,aud:D1,typ:t2,exp:Math.floor(F.getTime()/1000),iat:Math.floor(Date.now()/1000),sid:B,scope:"openid profile email"}}function _5(Q){let B=Q.exp?new Date(Q.exp*1000):new Date;return{id:Q.sub,userName:Q.preferred_username??"",name:Q.name??"",email:Q.email??"",avatar:Q.picture,userType:"customer",ciam:{profile:Q,scope:"openid profile email",tokenType:"Bearer",expires:B}}}async function S5(Q){if(!D)throw Error("ionite CIAM Manager not initialized");if(!K)return new Response(JSON.stringify({error:"Workload authentication required"}),{status:401,headers:{"Content-Type":"application/json"}});if(!await K.getWorkloadIdentity(Q))return new Response(JSON.stringify({error:"Unauthorized: Valid workload token required"}),{status:401,headers:{"Content-Type":"application/json"}});let F,z;try{if(!Q.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 _=await Q.text(),N=JSON.parse(_);z=typeof N?.redirect==="string"&&N.redirect.length>0?N.redirect:void 0;let j={userName:N.userName,name:N.name,email:N.email,avatar:N.avatar},x=await J.customer.validate(j);if(x.issues)return new Response(JSON.stringify({error:"Missing required fields: userName, name, email"}),{status:400,headers:{"Content-Type":"application/json"}});F=x.value}catch(V){return new Response(JSON.stringify({error:"Invalid JSON in request body"}),{status:400,headers:{"Content-Type":"application/json"}})}let w=new URL(Q.url).searchParams.get("ttl"),T=w?parseInt(w,10):D.magicLinkTtl??3600;if(Number.isNaN(T)||T<=0)return new Response(JSON.stringify({error:"Invalid TTL parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let E=Z5(32),P=new Date(Date.now()+T*1000);if(!D.magicLinkStore)return new Response(JSON.stringify({error:"Magic link store not configured"}),{status:500,headers:{"Content-Type":"application/json"}});try{await D.magicLinkStore.create(E,F,P)}catch(V){return $.error("Error creating magic link",{"ion.operation":"magic_link.create","ion.outcome":"failure"},V),new Response(JSON.stringify({error:"Failed to create magic link"}),{status:500,headers:{"Content-Type":"application/json"}})}let I=new URL(Q.url),M=D.magicLinkLoginUrl||"/magic-link/login",Y=new URL(M,I.origin);if(Y.searchParams.set("token",E),z)Y.searchParams.set("redirect",z);return new Response(JSON.stringify({magicLink:Y.toString(),expiresAt:P.toISOString()}),{status:200,headers:{"Content-Type":"application/json"}})}async function O5(Q){if(!D)throw Error("ionite CIAM Manager not initialized");k();let F=new URL(Q.url).searchParams.get("token");if(!F)return G5(Q,{ok:!1,error:Error("Missing magic-link token")},void 0,[]);if(!D.magicLinkStore)return G5(Q,{ok:!1,error:Error("Magic link store not configured")},void 0,[]);let z=await D.magicLinkStore.getAndDelete(F);if(!z)return G5(Q,{ok:!1,error:Error("Magic link invalid, expired, or already used")},void 0,[]);let O=new Date(Date.now()+(D.sessionTtl??86400)*1000),w=Z5(32),T=h5(z.customer),E=g5(z.customer,w,O),P=m5(T,w,O),I=_5(E),M;try{let V={sid:w,sub:T,authType:"ciam",tenantId:D.tenantId,expiresAt:O,claims:E,accessClaims:P,createdAt:new Date};await H().create(V),M=V}catch(V){throw $.warn("Failed to create session",{"ion.operation":"session.create","ion.outcome":"degraded"},V),V}if(D.customerStore)try{let V=I.id;if(V){let _=new Date,N=await D.customerStore.get(V);if(N||D.enableJitUserProvisioning){let j={...N??{},...I,id:V,tenantId:N?.tenantId,createdAt:N?.createdAt??_,updatedAt:_,userType:N?.userType??"customer"};await D.customerStore.upsert(j)}}}catch(V){$.warn("Failed to store customer",{"ion.operation":"customer.store","ion.outcome":"degraded"},V)}let Y=[U5(w,O)];return G5(Q,{ok:!0,user:I,session:M},void 0,Y)}function W5(Q,B=200,F=[]){return new Response(JSON.stringify(Q),{status:B,headers:[["Content-Type","application/json"],...F]})}function j5(Q,B){try{return new URL(Q).toString()}catch{let F=new URL(B).origin,z=D.cookiesSecure?F.replace(/^http:\/\//,"https://"):F;return new URL(Q,z).toString()}}function p5(){let Q=D.customerLoginUrl||"/auth/customer/login",B=Q.includes("?")?"&":"?";return q1(D.providers).map(({name:F,config:z})=>{let O=v1(z);return{name:F,type:z.type,displayName:O.displayName,loginUrl:`${Q}${B}provider=${encodeURIComponent(F)}`,iconUrl:O.iconUrl,colors:O.colors,url:O.url}})}async function R(Q){if(!Q)return{};let{authorizationUrl:B,tokenUrl:F,jwksUri:z,userInfoUrl:O}=Q,w=Q.config.authority;if(w&&(!B||!F||Q.flow==="id_token"&&!z))try{let E=await d1(w);B=B??E.authorizationUrl,F=F??E.tokenUrl,z=z??E.jwksUri,O=O??E.userInfoUrl}catch(E){$.error("CIAM provider OIDC discovery failed",{"ion.operation":"ciam.oidc.discovery","ion.outcome":"failure"},E)}return{authorizationUrl:B,tokenUrl:F,jwksUri:z,userInfoUrl:O}}async function q(Q){if(Q.type==="apple"){let{teamId:B,keyId:F,privateKey:z,clientId:O}=Q.config;if(B&&F&&z&&O)return a1({teamId:B,keyId:F,privateKey:z,clientId:O})}return Q.clientSecret}async function g(Q){H();let F=new URL(Q.url).searchParams.get("provider");if(!F)return W5({error:"Missing required query parameter: provider"},400);let z=D.providers?.[F];if(!z||z.enabled===!1||z.type==="magic-link")return W5({error:`Unknown or disabled CIAM provider: ${F}`},404);let O=V1(F,z);if(!O?.clientId)return W5({error:`CIAM provider ${F} is not fully configured`},500);let w=await R(O);if(!w.authorizationUrl)return W5({error:`CIAM provider ${F} is missing an authorization endpoint`},500);let T=D.customerCallbackUrl||"/auth/customer/callback",E=j5(T,Q.url),P=F5(),I=F5(64),M=F5(),Y=O.flow==="id_token",V=Y?await J1(I):void 0,_=await D.beforeLogin?.({request:Q}),N=u1({authorizationUrl:w.authorizationUrl,clientId:O.clientId,redirectUri:E,scope:O.scope,state:P,codeChallenge:V,nonce:M,extraParams:O.extraAuthParams}),j={provider:F,state:P,codeVerifier:Y?I:void 0,nonce:M,redirectUri:E,..._===void 0?{}:{context:_}};return new Response("Redirecting to CIAM provider",{status:302,headers:[["Location",N],["Set-Cookie",C(i(P),j,D.loginStateTtl??600,"Lax")]]})}async function u(Q){if(Q.method==="POST"){if((Q.headers.get("content-type")??"").includes("application/x-www-form-urlencoded")){let F=await Q.text();return Object.fromEntries(new URLSearchParams(F).entries())}}return Object.fromEntries(new URL(Q.url).searchParams.entries())}async function t(Q,B){let F=Q.mapClaims(B);if(!F.sub)return{ok:!1};let z=`${Q.name}:${F.sub}`,O={id:z,userName:F.userName||F.email||z,name:F.name||"",email:F.email||"",avatar:F.avatar,userType:"customer"},w=z;if(D.customerStore){let Y=await D.customerStore.lookup(O)??await D.customerStore.get(z);if(w=Y?.id??z,!Y&&!D.enableJitUserProvisioning)return $.warn("CIAM JIT customer provisioning disabled: unknown customer rejected",{"ion.operation":"customer.store","ion.outcome":"skipped"}),{ok:!1};let V=new Date,_={...Y??{},...O,id:w,tenantId:Y?.tenantId,createdAt:Y?.createdAt??V,updatedAt:V,userType:Y?.userType??"customer"};await D.customerStore.upsert(_)}let T=new Date(Date.now()+(D.sessionTtl??86400)*1000),E=F5(32),P={sub:w,iss:Q.name,aud:Q.clientId,exp:Math.floor(T.getTime()/1000),iat:Math.floor(Date.now()/1000),email:F.email,name:F.name,preferred_username:F.userName??F.email,picture:F.avatar,sid:E},I={sid:E,sub:w,authType:"ciam",tenantId:D.tenantId,expiresAt:T,claims:P,accessClaims:{sub:w,sid:E,scope:Q.scope},createdAt:new Date},M=H();try{await M.create(I)}catch(Y){if(!await M.get(E))throw Y;await M.update(E,I)}return{ok:!0,claims:P,sid:E,expires:T}}async function l(Q){H();let B,F,z=(O)=>{let w=B?[["Set-Cookie",Q5(B)]]:[];return G5(Q,{ok:!1,error:O},F,w)};try{let O=await u(Q),w=await a.validate(O);if(w.issues||!w.value)return z(Error("Invalid CIAM callback parameters"));let{code:T,state:E}=w.value;if(!E)return z(Error("Missing CIAM callback state"));B=i(E);let P=v(B,Q,!0);if(F=P?.context,!P?.provider||!P.state||P.state!==E)return $.warn("CIAM callback state verification failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),z(Error("CIAM callback state verification failed"));let I=D.providers?.[P.provider];if(!I)return z(Error("Unknown CIAM provider"));let M=V1(P.provider,I);if(!M?.clientId)return z(Error("CIAM provider not configured"));let Y=await R(M);if(!Y.tokenUrl)return z(Error("CIAM provider missing token endpoint"));let V=await q(M),_=await l1({tokenUrl:Y.tokenUrl,clientId:M.clientId,clientSecret:V,redirectUri:P.redirectUri||j5(D.customerCallbackUrl||"/auth/customer/callback",Q.url),code:T,codeVerifier:M.flow==="id_token"?P.codeVerifier:void 0,log:$}),N;if(M.flow==="id_token"){let b=M.config.authority;if(!_.id_token||!Y.jwksUri||!b)return z(Error("CIAM id_token flow misconfigured"));if(!P.nonce)return z(Error("CIAM callback state cookie missing nonce"));if((await o.validate(_)).issues)return $.warn("CIAM token response validation failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),z(Error("CIAM token response validation failed"));N=await I5({idToken:_.id_token,jwksUri:Y.jwksUri,issuer:b,audience:M.clientId,expectedNonce:P.nonce,log:$});let U=await n.validate(N);if(!U.issues)N=U.value}else{if(!Y.userInfoUrl)return z(Error("CIAM provider missing userinfo endpoint"));N=await n1(Y.userInfoUrl,_.access_token);let b=M.config.authority;if(_.id_token&&Y.jwksUri&&b){let y=await I5({idToken:_.id_token,jwksUri:Y.jwksUri,issuer:b,audience:M.clientId,expectedNonce:P.nonce||void 0,log:$}),U=typeof y.sub==="string"?y.sub:"";if(U){if(typeof N.sub==="string"&&N.sub.length>0&&N.sub!==U)return $.warn("CIAM UserInfo sub does not match verified id_token sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),z(Error("CIAM UserInfo sub mismatch"));N.sub=U}}if(typeof N.sub!=="string"||N.sub.length===0)return $.warn("CIAM UserInfo response missing sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),z(Error("CIAM UserInfo response missing sub"))}let j=await t(M,N);if(!j.ok)return z(Error("Failed to persist CIAM customer"));let x=_5(j.claims);$.info("CIAM third-party sign-in succeeded",{"ion.operation":"ciam.oidc.callback","ion.outcome":"success",provider:M.name});let S=[["Set-Cookie",Q5(B)],U5(j.sid,j.expires)];return G5(Q,{ok:!0,user:x,session:void 0},F,S)}catch(O){return $.error("Error during CIAM third-party sign-in callback",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"},O),z(O)}}async function e(Q){if(!D)throw Error("ionite CIAM Manager not initialized");k();let B=D.magicLinkUrl||"/magic-link",F=D.magicLinkLoginUrl||"/magic-link/login",z=D.logoutUrl||"/auth/customer/logout",O=D.customerLoginUrl||"/auth/customer/login",w=D.customerCallbackUrl||"/auth/customer/callback",T=D.customerProvidersUrl||"/auth/customer/providers",E=new URL(Q.url).pathname,P=(j)=>{if(!j)return;try{return new URL(j).pathname}catch{return j.startsWith("/")?j:`/${j}`}};if(P(B)===E&&Q.method==="POST")return S5(Q);if(P(F)===E&&Q.method==="GET")return O5(Q);if(P(z)===E&&Q.method==="GET")return f5(Q);if(P(T)===E&&Q.method==="GET")return W5({providers:p5()});if(P(O)===E&&Q.method==="GET")return g(Q);if(P(w)===E&&(Q.method==="GET"||Q.method==="POST"))return l(Q);return new Response("Not Found",{status:404})}return{...D,getCustomer:k5,resolveCustomer:P5,logout:f5,handler:e,listCustomerProviders:p5}}async function r2(J,$){return c($,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),$.ciam?.getCustomer(J)}async function s2(J,$){return c($,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),await $.ciam?.resolveCustomer(J)??{status:"unauthenticated"}}var e2="urn:ietf:params:scim:schemas:core:2.0:User",u9="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",J4="urn:ietf:params:scim:schemas:core:2.0:Group";function o1(J,$,Z){let K=($==="group"?J.resources:void 0)?.map((W)=>typeof W==="string"?W:W.id).filter(Boolean);return{schemas:[J4,p],id:J.id,externalId:J.providerId,displayName:J.displayName??J.name,members:Z,[p]:{type:$,requestable:J.requestable,providerId:J.providerId,requestUrl:J.requestUrl,source:J.source,deprecated:J.deprecated,description:J.description,resources:K&&K.length>0?K:void 0,assignableSubjectTypes:J.assignableSubjectTypes,recommendedSubjectTypes:J.recommendedSubjectTypes}}}function $4(J){if(J.scimName)return J.scimName;if(!J.name)return;let[$,...Z]=J.name.split(" ");return{givenName:$,familyName:Z.join(" ")||void 0}}function Z4(J){let $={};if(J.ecid!==void 0)$.ecid=J.ecid;if(J.accountClass!==void 0)$.accountClass=J.accountClass;return $.ecid!==void 0||$.accountClass!==void 0?$:void 0}function X4(J){return Object.keys(J.scimSchemaExtensions??{}).filter(($)=>$.startsWith("urn:")&&J.scimSchemaExtensions?.[$]!==void 0)}function r1(J){let $=J.userName||J.email||J.id||"",Z=J.emails??(J.email?[{value:J.email,primary:!0}]:[]),X=new Set([e2]);if(J.scimEnterprise!==void 0)X.add(u9);let K=Z4(J);if(K!==void 0)X.add(D5);for(let G of X4(J))X.add(G);let W={};if(J.scimEnterprise!==void 0)W[u9]=J.scimEnterprise;if(K!==void 0)W[D5]=K;for(let[G,L]of Object.entries(J.scimSchemaExtensions??{}))if(G.startsWith("urn:")&&G!==D5&&L!==void 0)W[G]=L;return{schemas:Array.from(X),id:J.id,externalId:J.externalId,userName:$,displayName:J.displayName??J.name??$,name:$4(J),nickName:J.nickName,profileUrl:J.avatar,title:J.title,userType:J.userType,preferredLanguage:J.preferredLanguage,locale:J.locale,timezone:J.timezone,active:J.active??!0,emails:Z,phoneNumbers:J.phoneNumbers,ims:J.ims,photos:J.photos,addresses:J.addresses,groups:J.groups,entitlements:J.entitlements,roles:J.roles,x509Certificates:J.x509Certificates,meta:{resourceType:"User",created:(J.createdAt??J.updatedAt??new Date).toISOString(),lastModified:(J.updatedAt??J.createdAt??new Date).toISOString()},...W}}var Q1="application/scim+json",Q4="urn:ietf:params:scim:api:messages:2.0:ListResponse",K9="urn:ietf:params:scim:api:messages:2.0:Error",Y9="urn:ietf:params:scim:schemas:core:2.0:User",K1="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",B9="urn:ietf:params:scim:schemas:core:2.0:Group",K4="urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig",l9="urn:ietf:params:scim:schemas:core:2.0:ResourceType",$1="urn:ietf:params:scim:schemas:core:2.0:Schema",Y4="00000000000000000000000000000000";function B4(J){let $={timestamp:new Date().toISOString()};if(J)$.actor=J;try{let K=globalThis[Symbol.for("opentelemetry.js.api.1")]?.trace?.getActiveSpan?.()?.spanContext?.(),W=K?.traceId;if(W&&W!==Y4){if($.traceId=W,K?.spanId)$.spanId=K.spanId}}catch{}return $}class Y1 extends Error{constructor(J){super(J);this.name="SubjectTypeNotAssignableError",Object.setPrototypeOf(this,Y1.prototype)}}async function G4(J,$,Z,X){let K=Z.subjectType??"user";if(!Q9.includes(K))throw new Y1(`Cannot grant ${Z.targetType} "${B5(Z.target)}" to a "${K}" principal: only [${Q9.join(", ")}] principals are assignable on this platform.`);let W=H9($,J);if(!W&&!X)return;let G=B5(Z.target),L;if(X)L=await X.getNode(Z.targetType,G);else if(W)L=await(Z.targetType==="group"?W.groups:Z.targetType==="role"?W.roles:W.permissions).get(G);let D=L?.assignableSubjectTypes;if(D&&D.length>0&&!D.includes(K))throw new Y1(`Cannot grant ${Z.targetType} "${G}" to a "${K}" principal: this entitlement restricts assignment to [${D.join(", ")}].`)}async function W4(J,$){let Z=L9(J.codeCatalog,B5($.target));if(!Z)return;if(Z.kind!==$.targetType)throw Error(`Cannot grant ${$.targetType} "${Z.entity.id}": code declares that id as ${Z.kind}.`);if(!J.catalogStore)throw Error(`Cannot grant code entitlement "${Z.entity.id}": no AccessCatalogStore is wired for materialization.`);await V9(Z.kind,Z.entity,F9(J.catalogStore,Z.kind))}async function L4(J,$,Z,X){await W4(J,$),await G4(J.catalogStore,J.codeCatalog,$,X);let K={...$,status:$.status??"active",provenance:$.provenance??B4()};if(K.id=G1(K),await J.accessStore?.grant(K),J.accessIndex&&(J.catalogStore||J.codeCatalog)){let W=await M9(K,{catalog:J.catalogStore,code:J.codeCatalog,resources:J.resources,cache:X});await J.accessIndex.materialize(K.id,W)}return Z?.push({op:"add",change:K}),K}async function O1(J,$,Z){let X=$.id??G1($);await J.accessStore?.revoke($),await J.accessIndex?.removeByRoot(X),Z?.push({op:"delete",change:{...$,id:X}})}async function G9(J,$){let Z=await F4(J,$),X=await H4(J,$);return{oaa:Z,delta:X}}async function F4(J,$){if($.length===0||!J.authz.oaa.isReady())return{status:"skipped"};return B1(J,"authz.oaa.push","OAA incremental access push failed after SCIM mutation; full sync will reconcile",()=>J.authz.oaa.pushAccessChanges($),{count:$.length})}async function B1(J,$,Z,X,K){try{return await X(),{status:"ok"}}catch(W){return J.log?.warn(Z,{"ion.operation":$,"ion.outcome":"degraded",...K,error:N5(W)}),{status:"degraded",reason:N5(W)}}}var V4=6;async function H4(J,$){let Z=J.iamDelta;if(!Z?.isReady()||$.length===0)return{status:"skipped"};let X=new Map;for(let D of $){let H=`${D.change.subjectType??"user"}:${B5(D.change.subject)}\x00${D.change.targetType}:${B5(D.change.target)}`;X.set(H,D)}let K=[...X.values()],W=K.map(({op:D,change:H})=>()=>D==="add"?Z.onGrant(H):Z.onRevoke(H)),L=(await D4(W,V4)).filter((D)=>D.status==="rejected");if(L.length>0)return J.log?.warn("IAM delta egress degraded after SCIM mutation; IAM server reconcile/aggregation will recover",{"ion.operation":"iam.delta.egress","ion.outcome":"degraded",failed:L.length,total:K.length,error:N5(L[0]?.reason)}),{status:"degraded",reason:N5(L[0]?.reason)};return{status:"ok"}}async function D4(J,$){let Z=Array(J.length),X=0,K=async()=>{while(!0){let G=X++;if(G>=J.length)return;let L=J[G];if(!L)continue;try{Z[G]={status:"fulfilled",value:await L()}}catch(D){Z[G]={status:"rejected",reason:D}}}},W=Array.from({length:Math.min($,J.length)},K);return await Promise.all(W),Z}class A1 extends Error{constructor(J){super(J);this.name="DerivedRevokeError",Object.setPrototypeOf(this,A1.prototype)}}class i5 extends Error{summary;clientError;constructor(J,$,Z=!1){super(J);this.name="ScimMutationError",this.summary=$,this.clientError=Z,Object.setPrototypeOf(this,i5.prototype)}}function f(J,$,Z){return new Response(JSON.stringify({schemas:[K9],status:String(J),scimType:Z,detail:$}),{status:J,headers:{"Content-Type":Q1}})}function b5(J,$){let Z=$?.totalResults??J.length,X=$?.startIndex??1,K=$?.itemsPerPage??J.length;return new Response(JSON.stringify({schemas:[Q4],totalResults:Z,startIndex:X,itemsPerPage:K,Resources:J}),{status:200,headers:{"Content-Type":Q1}})}function V5(J,$=200,Z){let X=new Headers({"Content-Type":Q1});if(Z)X.set("Location",Z);return new Response(JSON.stringify(J),{status:$,headers:X})}function c9(J){return f(J.clientError?409:500,`${J.message}; authz mutation summary: ${JSON.stringify(J.summary)}`,J.clientError?"mutability":"invalidValue")}function X1(J){return G1(J)}function s1(J,$){return z1(d9(J),d9($))}function d9(J){let $=new Map;if(!J?.id)return $;for(let Z of J.groups??[]){let X={subject:J.id,targetType:"group",target:Z.value,metadata:Z.display||Z.type?{display:Z.display,type:Z.type}:void 0};$.set(X1(X),X)}for(let Z of J.roles??[]){let X={subject:J.id,targetType:"role",target:Z.value,metadata:Z.display||Z.type?{display:Z.display,type:Z.type,primary:Z.primary}:void 0};$.set(X1(X),X)}for(let Z of J.entitlements??[]){let X={subject:J.id,targetType:"permission",target:Z.value,metadata:Z.display||Z.type?{display:Z.display,type:Z.type,primary:Z.primary}:void 0};$.set(X1(X),X)}return $}function N1(J,$,Z,X){let K=new Map,W=X&&X.length>0?X:void 0;for(let G of J??[]){let L={subject:G.value,targetType:$,target:Z,resources:W,metadata:G.display||G.type?{display:G.display,type:G.type}:void 0};K.set(X1(L),L)}return K}function e1(J){let $=J[p]?.resources;return $&&$.length>0?$:void 0}function M4(J,$){let Z=(K,W)=>[...K??[]].sort().join(",")===[...W??[]].sort().join(","),X=J[p];if(X?.type!==void 0&&X.type!==$.kind)return!0;if(X?.requestable!==void 0&&X.requestable!==$.entity.requestable)return!0;if(X?.resources!==void 0&&!Z(X.resources,W9($.entity)))return!0;if(X?.assignableSubjectTypes!==void 0&&!Z(X.assignableSubjectTypes,$.entity.assignableSubjectTypes))return!0;if(X?.recommendedSubjectTypes!==void 0&&!Z(X.recommendedSubjectTypes,$.entity.recommendedSubjectTypes))return!0;return!1}function N4(J,$){let Z=(W,G)=>[...W??[]].sort().join(",")===[...G??[]].sort().join(","),X=J[p],K=$[p];if(X?.type!==void 0&&X.type!==K?.type)return!0;if(X?.requestable!==void 0&&X.requestable!==K?.requestable)return!0;if(X?.resources!==void 0&&!Z(X.resources,K?.resources))return!0;if(X?.assignableSubjectTypes!==void 0&&!Z(X.assignableSubjectTypes,K?.assignableSubjectTypes))return!0;if(X?.recommendedSubjectTypes!==void 0&&!Z(X.recommendedSubjectTypes,K?.recommendedSubjectTypes))return!0;return!1}function z4(J){let $=new Map;for(let Z of J)$.set(X1(Z),Z);return $}async function v5(J,$,Z,X,K,W){let G=[],L=new Set,D=(k,a)=>`${a}\x00${k}`,H=W?W.get(`${Z}:${X}`)??[]:$?(await $.listByTarget(Z,X)).items:[];for(let k of H){let a=B5(k.subject),n=k.metadata,o=k.subjectType==="workload"?"Workload":n?.type??"User",Z5=D(a,o);if(L.has(Z5))continue;L.add(Z5),G.push({value:a,...n?.display?{display:n.display}:{},type:o})}for(let k of K??[]){if(k.targetType!==Z||B5(k.target)!==X)continue;let a=B5(k.subject),n=D(a,"Workload");if(L.has(n))continue;L.add(n),G.push({value:a,type:"Workload"})}if(Z==="group"){let k=await J.groups.get(X);for(let a of k?.groups??[]){let n=B5(a),o=D(n,"Group");if(!n||L.has(o))continue;L.add(o),G.push({value:n,type:"Group"})}}return G.length>0?G:void 0}function z1(J,$){let Z=[];for(let[X,K]of $)if(!J.has(X))Z.push({action:"grant",change:K});for(let[X,K]of J)if(!$.has(X))Z.push({action:"revoke",change:K});return Z}async function J9(J,$){if(J.oaa.isReady())await J.oaa.pushUser($)}async function n9(J,$,Z){if($?.externalId&&$.externalId!==Z.externalId)await J?.onUserDelete($.externalId);await J?.onUserUpsert(Z)}async function d5(J,$,Z,X){let K={metadataApplied:!1,access:[]},W={status:"skipped"},G=[],L=new D9(J.catalogStore,J.resources,J.codeCatalog);try{try{await $(),K.metadataApplied=!0}catch(D){for(let H of Z)K.access.push({change:H.change,status:"rolled_back"});throw K.metadataApplied=!1,new i5(`SCIM metadata write failed: ${N5(D)}`,K,!1)}if(X?.oaa)await B1(J,"authz.oaa.metadata","OAA metadata projection failed after SCIM write; full sync will reconcile",X.oaa);if(X?.delta&&J.iamDelta?.isReady())W=await B1(J,"iam.delta.egress","IAM delta metadata projection failed after SCIM write; full aggregation will reconcile",X.delta);for(let D=0;D<Z.length;D++){let H=Z[D];try{if(H.action==="grant")await L4(J,H.change,G,L);else await E4(J,H.change,G);K.access.push({change:H.change,status:"applied"})}catch(k){K.access.push({change:H.change,status:"failed",error:k});for(let n=D+1;n<Z.length;n++)K.access.push({change:Z[n].change,status:"rolled_back"});let a=k instanceof A1||k instanceof Y1;if(!a)await j4(J,H.change,L);throw new i5(a?N5(k):`SCIM access mutation failed: ${N5(k)}`,K,a)}}return K}finally{await O4(J),K.egress=await G9(J,G),K.egress.delta=_4(W,K.egress.delta),A4(J,K)}}function _4(J,$){if(J.status==="degraded")return J;if($.status==="degraded")return $;return J.status==="ok"||$.status==="ok"?{status:"ok"}:{status:"skipped"}}function N5(J){return J instanceof Error?J.message:String(J)}async function O4(J){try{await J.settleAuthz?.()}catch{}}async function j4(J,$,Z){if(!J.accessIndex||!J.catalogStore&&!J.codeCatalog||!J.accessStore)return;let X=B5($.subject);if(!X)return;let K=$.subjectType??"user";try{await N9(X,K,{accessStore:J.accessStore,accessIndex:J.accessIndex,catalogStore:J.catalogStore,code:J.codeCatalog,resources:J.resources},Z)}catch(W){J.log?.warn("Per-subject reconcile after failed SCIM access mutation failed",{"ion.operation":"authz.reconcile.subject.repair","ion.outcome":"degraded",subject:X,subjectType:K,error:N5(W)})}}function A4(J,$){if(!J.onAccessMutation)return;try{J.onAccessMutation($)}catch{}}async function E4(J,$,Z){if(J.accessStore){let X=$.id??G1($);if(!await J.accessStore.get(X)){if((J.accessIndex?await J.accessIndex.has($.subject,$.targetType,$.target,$.resources?.[0],$.subjectType):{allow:!1}).allow)throw new A1(`Cannot revoke ${$.targetType} "${B5($.target)}" for "${B5($.subject)}": it is not a directly granted root (it is derived from group/role membership). Remove the granting group/role instead.`);await O1(J,$,Z);return}}await O1(J,$,Z)}function a5(J){let $=J[p]?.type??"group";if($==="group"||$==="role"||$==="permission")return $;throw Error(`Unsupported ionite SCIM Group authz type "${String($)}"`)}async function $9(J,$,Z){if(!J.oaa.isReady())return;if(Z==="role"){await J.oaa.pushRole($);return}if(Z==="permission"){await J.oaa.pushPermission($);return}await J.oaa.pushGroup($)}function W9(J){let $=J.resources;if(!$||$.length===0)return;let Z=$.map((X)=>typeof X==="string"?X:X.id).filter(Boolean);return Z.length>0?Z:void 0}function q5(J,$,Z){return o1(J,$,Z)}function w4(J,$){let Z=J[p],X={id:$,name:J.displayName,displayName:J.displayName,description:Z?.description??J.displayName,requestable:Z?.requestable,providerId:Z?.providerId??J.externalId,requestUrl:Z?.requestUrl};if(Z?.resources!==void 0)X.resources=Z.resources;return X}function P4(J){if(!J)return;let $=J.trim().match(/^requestable\s+eq\s+(true|false)$/i);if(!$)return;return{requestable:$[1]?.toLowerCase()==="true"}}function a9(J){if(!J)return;let $=J.trim().match(/^externalId\s+eq\s+"([^"]*)"$/i);return $?$[1]:void 0}async function I4(J,$,Z,X){let K=[],W=[["group",J.groups],["role",J.roles],["permission",J.permissions]];for(let[L,D]of W)for await(let H of t9((k,a)=>D.list({start:k,limit:a,filter:{requestable:!0}})))if(H.providerId===Z)K.push({entity:H,type:L});if(K.length>1)throw new z9(`Ambiguous providerId "${Z}": ${K.length} entitlements share it (${K.map((L)=>`${L.type}:${L.entity.id}`).join(", ")})`,"unique_violation","providerId");let G=K[0];if(G?.entity.requestable!==!0)return;return q5(G.entity,G.type,await v5(J,$,G.type,G.entity.id,X))}async function T4(J,$,Z,X){let K=Math.max(0,Z.start),W=Z.limit!=null?K+Z.limit:void 0,G={start:0,limit:W,filter:Z.filter},[L,D,H]=await Promise.all([J.groups.list(G),J.roles.list(G),J.permissions.list(G)]),k=[...L.items.map((C)=>({entity:C,type:"group"})),...D.items.map((C)=>({entity:C,type:"role"})),...H.items.map((C)=>({entity:C,type:"permission"}))],a=L.total+D.total+H.total,n=k.slice(K,W),o=$?.listByTargets?await $.listByTargets(n.map(({entity:C,type:Q5})=>({targetType:Q5,target:C.id}))):void 0,Z5=await Promise.all(n.map(async({entity:C,type:Q5})=>q5(C,Q5,await v5(J,$,Q5,C.id,X,o))));return{resources:Z5,total:a,count:Z5.length}}async function Z1(J,$,Z,X){let[K,W,G]=await Promise.all([J.groups.get(Z),J.roles.get(Z),J.permissions.get(Z)]);if(K)return q5(K,"group",await v5(J,$,"group",Z,X));if(W)return q5(W,"role",await v5(J,$,"role",Z,X));if(G)return q5(G,"permission",await v5(J,$,"permission",Z,X));return}async function Z9(J,$,Z){let X=a5($),K=X==="role"?await J.roles.get(Z):X==="permission"?await J.permissions.get(Z):await J.groups.get(Z),W={...K??{},...w4($,Z),source:K?.source??"scim"},G=X==="role"?J.roles.set(W):X==="permission"?J.permissions.set(W):J.groups.set(W);return await G.ready(),G}async function S4(J,$){await Promise.all([J.groups.delete($),J.roles.delete($),J.permissions.delete($)])}function i9(){return crypto.randomUUID()}function n5(J,$){let Z=J;if(typeof Z.validate==="function")return Z.validate($);return Promise.resolve(J["~standard"].validate($))}function x4(J){if(!J)return;try{return new URL(J).pathname}catch{return J.startsWith("/")?J:`/${J}`}}function y5(J){let $=x4(J);return $?_1($):void 0}function R4(J,$){let Z=y5(J);if(Z?.endsWith("/Users"))return Z.slice(0,-6);let X=y5($);if(X?.endsWith("/Groups"))return X.slice(0,-7);return}function M5(J,$){return new URL($,J.url).toString()}function A(J,$,Z,X){let{multiValued:K=!1,...W}=X??{};return{name:J,type:$,description:Z,multiValued:K,...W}}function b4(J,$){return{schemas:[K4],documentationUri:$?.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:M5(J.request,`${J.basePath}/ServiceProviderConfig`)}}}function y4(J){let $=[];if(J.supportsUsers)$.push({schemas:[l9],id:"User",name:"User",description:"User Account",endpoint:J.usersUrl,schema:Y9,schemaExtensions:[{schema:K1,required:!1},{schema:D5,required:!1}],meta:{resourceType:"ResourceType",location:M5(J.request,`${J.basePath}/ResourceTypes/User`)}});if(J.supportsGroups)$.push({schemas:[l9],id:"Group",name:"Group",description:"Group",endpoint:J.groupsUrl,schema:B9,schemaExtensions:[{schema:p,required:!1}],meta:{resourceType:"ResourceType",location:M5(J.request,`${J.basePath}/ResourceTypes/Group`)}});return $}function v4(J){let $=[];if(J.supportsUsers)$.push({schemas:[$1],id:Y9,name:"User",description:"User Account",meta:{resourceType:"Schema",location:M5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(Y9)}`)},attributes:[A("id","string","Unique identifier for the User.",{multiValued:!1,required:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),A("externalId","string","External identifier from the provisioning client.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",uniqueness:"none"}),A("userName","string","Unique identifier typically used for login.",{multiValued:!1,required:!0,caseExact:!1,mutability:"readWrite",returned:"default",uniqueness:"server"}),A("name","complex","The components of the user name.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",subAttributes:[A("formatted","string","The full name, including titles and suffixes.",{multiValued:!1}),A("familyName","string","The family name of the User.",{multiValued:!1}),A("givenName","string","The given name of the User.",{multiValued:!1}),A("middleName","string","The middle name(s) of the User.",{multiValued:!1}),A("honorificPrefix","string","The honorific prefix(es) of the User.",{multiValued:!1}),A("honorificSuffix","string","The honorific suffix(es) of the User.",{multiValued:!1})]}),A("displayName","string","The name of the User, suitable for display.",{multiValued:!1}),A("nickName","string","The casual way to address the user.",{multiValued:!1}),A("profileUrl","reference","A URL pointing to the User profile.",{multiValued:!1,referenceTypes:["external"]}),A("title","string","The user title, such as Vice President.",{multiValued:!1}),A("userType","string","The relationship between the organization and the User.",{multiValued:!1}),A("preferredLanguage","string","Preferred written or spoken language.",{multiValued:!1}),A("locale","string","Default location for localizing values.",{multiValued:!1}),A("timezone","string","The User time zone.",{multiValued:!1}),A("active","boolean","The User administrative status.",{multiValued:!1}),A("emails","complex","Email addresses for the User.",{multiValued:!0,subAttributes:[A("value","string","Email address value.",{multiValued:!1,required:!0}),A("display","string","Display label for the email.",{multiValued:!1}),A("type","string","Email type such as work or home.",{multiValued:!1}),A("primary","boolean","Primary email indicator.",{multiValued:!1})]}),A("phoneNumbers","complex","Phone numbers for the User.",{multiValued:!0,subAttributes:[A("value","string","Phone number value.",{multiValued:!1,required:!0}),A("display","string","Display label for the phone number.",{multiValued:!1}),A("type","string","Phone number type.",{multiValued:!1}),A("primary","boolean","Primary phone number indicator.",{multiValued:!1})]}),A("photos","complex","Photo URLs for the User.",{multiValued:!0,subAttributes:[A("value","reference","Photo URL.",{multiValued:!1,required:!0,referenceTypes:["external"]}),A("display","string","Display label for the photo.",{multiValued:!1}),A("type","string","Photo type.",{multiValued:!1}),A("primary","boolean","Primary photo indicator.",{multiValued:!1})]}),A("addresses","complex","Physical mailing addresses for the User.",{multiValued:!0,subAttributes:[A("formatted","string","Formatted mailing address.",{multiValued:!1}),A("streetAddress","string","Full street address component.",{multiValued:!1}),A("locality","string","City or locality.",{multiValued:!1}),A("region","string","State or region.",{multiValued:!1}),A("postalCode","string","Postal code.",{multiValued:!1}),A("country","string","Country.",{multiValued:!1}),A("type","string","Address type.",{multiValued:!1}),A("primary","boolean","Primary address indicator.",{multiValued:!1})]}),A("groups","complex","Groups to which the User belongs.",{multiValued:!0,mutability:"readOnly",subAttributes:[A("value","string","Group identifier.",{multiValued:!1,required:!0}),A("$ref","reference","Reference to the Group resource.",{multiValued:!1,referenceTypes:["Group"]}),A("display","string","Display name of the group.",{multiValued:!1}),A("type","string","Relationship type.",{multiValued:!1})]}),A("entitlements","complex","Entitlements for the User.",{multiValued:!0,subAttributes:[A("value","string","Entitlement value.",{multiValued:!1,required:!0}),A("display","string","Display value.",{multiValued:!1}),A("type","string","Entitlement type.",{multiValued:!1}),A("primary","boolean","Primary entitlement indicator.",{multiValued:!1})]}),A("roles","complex","Roles for the User.",{multiValued:!0,subAttributes:[A("value","string","Role value.",{multiValued:!1,required:!0}),A("display","string","Display value.",{multiValued:!1}),A("type","string","Role type.",{multiValued:!1}),A("primary","boolean","Primary role indicator.",{multiValued:!1})]}),A("x509Certificates","complex","Certificates issued to the User.",{multiValued:!0,subAttributes:[A("value","string","Certificate value.",{multiValued:!1,required:!0}),A("display","string","Display value.",{multiValued:!1}),A("type","string","Certificate type.",{multiValued:!1}),A("primary","boolean","Primary certificate indicator.",{multiValued:!1})]})]}),$.push({schemas:[$1],id:K1,name:"EnterpriseUser",description:"Enterprise User extension",meta:{resourceType:"Schema",location:M5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(K1)}`)},attributes:[A("employeeNumber","string","Numeric or alphanumeric identifier assigned to a person.",{multiValued:!1}),A("costCenter","string","Name of a cost center.",{multiValued:!1}),A("organization","string","Name of an organization.",{multiValued:!1}),A("division","string","Name of a division.",{multiValued:!1}),A("department","string","Name of a department.",{multiValued:!1}),A("manager","complex","The User manager.",{multiValued:!1,subAttributes:[A("value","string","Identifier of the manager User resource.",{multiValued:!1}),A("$ref","reference","Reference to the manager User resource.",{multiValued:!1,referenceTypes:["User"]}),A("displayName","string","Display name of the manager.",{multiValued:!1})]})]}),$.push({schemas:[$1],id:D5,name:"IoniteUser",description:"ionite User extension carrying the Enterprise Controlled ID (ECID) identity correlator and the account purpose (accountClass). See https://ionite.com/docs/llms-ecid.txt.",meta:{resourceType:"Schema",location:M5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(D5)}`)},attributes:[A("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}),A("accountClass","string","Account purpose (distinct from userType persona). Open value set: 'daily', 'privileged', 'break_glass', 'service'.",{multiValued:!1})]});if(J.supportsGroups)$.push({schemas:[$1],id:p,name:"IoniteAuthzGroup",description:"ionite authorization metadata for SCIM Group resources.",meta:{resourceType:"Schema",location:M5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(p)}`)},attributes:[A("type","string","Authorization entity kind: group, role, or permission.",{multiValued:!1,required:!1}),A("requestable","boolean","Whether this catalog entry is exposed as assignable access to IAM tooling. Only true entries are served.",{multiValued:!1,required:!1}),A("providerId","string","IAM service-provider id captured when this entitlement is materialized at the destination.",{multiValued:!1,required:!1,mutability:"readWrite"}),A("requestUrl","reference","IAM-owned deep link where a principal can request this entitlement.",{multiValued:!1,required:!1,mutability:"readWrite",referenceTypes:["external"]}),A("source","string","Provenance of the catalog row.",{multiValued:!1,required:!1,mutability:"readOnly",canonicalValues:["code","app","scim"]}),A("deprecated","boolean","Whether this retired entitlement may be deleted.",{multiValued:!1,required:!1,mutability:"readOnly"}),A("description","string","Human-readable authorization entity description.",{multiValued:!1,required:!1}),A("resources","string","Resource ids this entitlement is scoped to.",{multiValued:!0,required:!1}),A("assignableSubjectTypes","string","AppDev-owned hard ceiling of principal kinds (user, workload) that may hold this entitlement. Read-only to IAM tooling.",{multiValued:!0,required:!1,mutability:"readOnly",canonicalValues:["user","customer","workload"]}),A("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"]})]});if(J.supportsGroups)$.push({schemas:[$1],id:B9,name:"Group",description:"Group",meta:{resourceType:"Schema",location:M5(J.request,`${J.basePath}/Schemas/${encodeURIComponent(B9)}`)},attributes:[A("id","string","Unique identifier for the Group.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),A("externalId","string","External identifier from the provisioning client.",{multiValued:!1,uniqueness:"none"}),A("displayName","string","Human-readable name for the Group.",{multiValued:!1,required:!0,uniqueness:"none"}),A("members","complex","Members of the Group.",{multiValued:!0,subAttributes:[A("value","string","Identifier of the member resource.",{multiValued:!1,required:!0}),A("$ref","reference","Reference to the member resource.",{multiValued:!1,referenceTypes:["User","Group"]}),A("display","string","Display name of the member.",{multiValued:!1}),A("type","string","Member type.",{multiValued:!1})]})]});return $}function q4(J,$,Z,X,K,W,G,L,D,H,k,a,n,o,Z5){let C={authz:X,settleAuthz:Z5,accessStore:K,accessIndex:W,catalogStore:G,codeCatalog:L,resources:D,log:$,iamDelta:a,onAccessMutation:n};if(!H&&!k)return;let v={...H,...k},i=v.users?.enabled!==!1,G5=v.groups?.enabled!==!1;if(Boolean(v.url||v.userStore||G||L)&&!Z)$.error("IAM requires workload identity for SCIM push/pull operations",{"ion.operation":"workload.require","ion.outcome":"failure"});function z5(){if(!Z)throw $.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 Z}async function w5(R){let q=z5(),g=R.headers.get("Authorization");if(!g?.startsWith("Bearer "))return!1;try{let u=g.substring(7);return(await q.validateToken(u)).valid}catch{return!1}}async function P5(){let R=z5(),q=typeof R.getServerToken==="function"?await R.getServerToken():await R.getToken();return new Headers({"Content-Type":Q1,Accept:Q1,Authorization:`Bearer ${q}`})}async function C5(R,q,g,u){if(!v.url)throw Error("IAM URL not configured for outgoing requests");let t=`${v.url}${q}`;try{let l=await P5(),e=await fetch(t,{method:R,headers:l,body:g?JSON.stringify(g):void 0}),Q=await e.json();if(!e.ok)return{success:!1,error:Q,status:e.status};let B=await u["~standard"].validate(Q);if(B.issues)return $.error("SCIM response validation failed",{"ion.operation":"scim.response.validate","ion.outcome":"failure",validationIssues:B.issues}),{success:!1,error:{schemas:[K9],status:"400",scimType:"invalidValue",detail:`Response validation failed: ${B.issues.map((F)=>F.message).join("; ")}`},status:400};return{success:!0,data:B.value,status:e.status}}catch(l){return{success:!1,error:{schemas:[K9],status:"500",detail:l instanceof Error?l.message:"Unknown error occurred"},status:500}}}function k5(){return v.url}function f5(R,q){let g=y5(q?.usersUrl??v.usersUrl??"/api/iam/Users")??"/api/iam/Users",u=y5(q?.groupsUrl??v.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",t=y5(q?.discovery?.basePath??v.discovery?.basePath)??R4(g,u);if(!t)return;return{request:R,basePath:t,usersUrl:g,groupsUrl:u,supportsUsers:i&&Boolean(v.userStore),supportsGroups:G5&&Boolean(G||L)}}async function h5(R){let q=b4(R,v.discovery);return await v.discovery?.buildServiceProviderConfig?.(R,q)??q}async function g5(R){let q=y4(R);return await v.discovery?.buildResourceTypes?.(R,q)??q}async function m5(R){let q=v4(R);return await v.discovery?.buildSchemas?.(R,q)??q}async function _5(R,q){let g=f5(R,q);if(!g)return;let u=_1(new URL(R.url).pathname),{basePath:t}=g;if(u!==t&&!u.startsWith(`${t}/`))return;let l=_1(u.slice(t.length)||"/");if(!(l==="/ServiceProviderConfig"||l==="/ResourceTypes"||l.startsWith("/ResourceTypes/")||l==="/Schemas"||l.startsWith("/Schemas/")))return;if(R.method!=="GET")return f(405,"Method not allowed");if(!await w5(R))return f(401,"Authorization required");if(l==="/ServiceProviderConfig")return V5(await h5(g));if(l==="/ResourceTypes")return b5(await g5(g));if(l.startsWith("/ResourceTypes/")){let B=decodeURIComponent(l.slice(15)),F=(await g5(g)).find((z)=>z.id===B||z.name===B);return F?V5(F):f(404,"Resource not found")}if(l==="/Schemas")return b5(await m5(g));if(l.startsWith("/Schemas/")){let B=decodeURIComponent(l.slice(9)),F=(await m5(g)).find((z)=>z.id===B);return F?V5(F):f(404,"Resource not found")}return}let S5,O5;if(v.url)O5=async(q,g)=>{let u={...q,schemas:q.schemas??["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"]};return C5("POST","/Users",u,J.user)},S5={createGroup:async(q,g)=>{let u={schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],displayName:q,externalId:g?.id,members:g?.members};return C5("POST","/Groups",u,J.group)}};let W5;if(G||L){let R=H9(L,G),q=(M,Y,V)=>{let _=M[p]??{},N=a5(M),j=M.id,x=j?M5(Y,`${V}/${encodeURIComponent(j)}`):void 0,S={id:j??M.externalId??M.displayName,name:M.displayName,displayName:M.displayName,description:_.description??M.displayName,requestable:_.requestable,providerId:_.providerId??M.externalId,requestUrl:_.requestUrl,source:_.source,deprecated:_.deprecated,assignableSubjectTypes:_.assignableSubjectTypes,recommendedSubjectTypes:_.recommendedSubjectTypes},b=_.requestUrl??v.entitlementRequestUrl?.(S,N,{request:Y});return{...M,meta:{...M.meta,resourceType:"Group",location:x},[p]:{..._,requestUrl:b}}},g=(M)=>L9(L,M),u=async(M,Y)=>{if(!G){if(Y)throw Error(`Cannot persist access for code entitlement "${M.entity.id}": no AccessCatalogStore is wired.`);return M.entity}try{return await V9(M.kind,M.entity,F9(G,M.kind))}catch(V){if(Y)throw V;return $.warn("Code entitlement discovery materialization failed; serving the code template",{"ion.operation":"iam.catalog.materialize","ion.outcome":"degraded",entitlementId:M.entity.id,entitlementType:M.kind,error:N5(V)}),M.entity}},t=async(M)=>{if(!G)return;try{await o9(L,G,M)}catch(Y){$.warn("Retired code entitlement deprecation failed; serving the last durable row",{"ion.operation":"iam.catalog.deprecate","ion.outcome":"degraded",entitlementId:M,error:N5(Y)})}},l=(M,Y)=>f(403,`Entitlement "${M}" is declared in application code; its structural definition cannot be ${Y} through SCIM. IAM may change presentation and receipts, while code continues to own structure.`,"mutability"),e=(M)=>M.path==="members"||Boolean(M.path?.startsWith("members[")),Q=(M)=>e(M)||M.path==="displayName"||M.path===`${p}.description`||M.path===`${p}.providerId`||M.path===`${p}.requestUrl`,B=(M)=>M?.[p]?.requestable===!0,F=(M)=>f(404,`Requestable Group ${M} not found`,"invalidValue"),z=async(M,Y)=>{if(!await w5(M))return f(401,"Authorization required");let _=new URL(M.url),N=Y?.basePath??"/Groups",j=_.pathname;if(j.startsWith(N))j=j.substring(N.length);let S=j.match(/^\/([^/]+)$/)?.[1],b=M.method;try{if(S)switch(b){case"GET":return await w(M,N,S);case"PUT":return await E(M,N,S);case"PATCH":return await P(M,N,S);case"DELETE":return await I(S);default:return f(405,"Method not allowed")}else if(j===""||j==="/")switch(b){case"GET":return await O(M,N);case"POST":return await T(M,N);default:return f(405,"Method not allowed")}return f(404,"Resource not found")}catch(y){if(y instanceof i5)return c9(y);if(X9(y))return f(409,y.message,"uniqueness");return $.error("Groups inbound handler error",{"ion.operation":"scim.groups.handler","ion.outcome":"failure"},y),f(500,y instanceof Error?y.message:"Internal server error")}},O=async(M,Y)=>{let V=new URL(M.url),_=V.searchParams.get("startIndex"),N=V.searchParams.get("count"),j=_!=null?parseInt(_,10):void 0,x=N!=null?parseInt(N,10):void 0,S=j!=null&&!Number.isNaN(j)?Math.max(0,j-1):0,b=x!=null&&!Number.isNaN(x)?x:void 0,y=V.searchParams.get("filter"),U=a9(y);if(U!==void 0){await t();let d=await I4(R,K,U,o),m=d?[q(d,M,Y)]:[];return b5(m,{totalResults:m.length,startIndex:1,itemsPerPage:m.length})}if(P4(y)?.requestable===!1)return b5([],{totalResults:0,startIndex:1,itemsPerPage:0});let X5={requestable:!0};if(L)await Promise.all([...L.groups.list().filter((d)=>d.requestable===!0).map((d)=>({entity:d,kind:"group"})),...L.roles.list().filter((d)=>d.requestable===!0).map((d)=>({entity:d,kind:"role"})),...L.permissions.list().filter((d)=>d.requestable===!0).map((d)=>({entity:d,kind:"permission"}))].map((d)=>u(d,!1)));await t();let h=await T4(R,K,{start:S,limit:b,filter:X5},o);return b5(h.resources.map((d)=>q(d,M,Y)),{totalResults:h.total,startIndex:S+1,itemsPerPage:h.count})},w=async(M,Y,V)=>{let _=g(V);if(_&&_.entity.requestable!==!0)return F(V);if(_)await u(_,!1);await t(V);let N=await Z1(R,K,V,o);if(!B(N))return F(V);return V5(q(N,M,Y))},T=async(M,Y)=>{let V=await M.json(),_=await n5(J.group,V);if(_.issues)return $.error("Group creation validation failed",{"ion.operation":"scim.group.create","ion.outcome":"failure",validationIssues:_.issues}),f(400,`Request validation failed: ${_.issues.map((h)=>h.message).join("; ")}`,"invalidValue");let N=_.value;if(!N.displayName)return f(400,"displayName is required","invalidValue");if(N[p]?.requestable===!1)return f(400,"SCIM may create only requestable entitlements; non-requestable definitions are App-owned.","invalidValue");if(N[p]={...N[p],requestable:!0},!G)return f(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 x=a5(N),S=i9();if(g(S))throw new z9(`id "${S}" is reserved by the code catalog`,"unique_violation","id");let b=e1(N),y=z1(new Map,N1(N.members,x,S,b)),U;await d5(C,async()=>{U=await Z9(R,N,S)},y,{oaa:()=>$9(X,U,x)});let r=await v5(R,K,x,S),X5=q(q5(U,x,r),M,Y);return V5(X5,201,X5.meta?.location)},E=async(M,Y,V)=>{let _=await M.json(),N=await n5(J.group,_);if(N.issues)return $.error("Group replacement validation failed",{"ion.operation":"scim.group.replace","ion.outcome":"failure",validationIssues:N.issues}),f(400,`Request validation failed: ${N.issues.map((m)=>m.message).join("; ")}`,"invalidValue");let j=N.value,x=a5(j),S=g(V);if(S&&S.entity.requestable!==!0)return F(V);if(S){if(await u(S,!0),M4(j,S))return l(V,"replaced")}let b=await Z1(R,K,V);if(!B(b))return F(V);if(!S&&b[p]?.source==="code"&&N4(j,b))return l(V,"replaced");let y=S?.kind??x,U=S?W9(S.entity):e1(j),r=K?(await K.listByTarget(y,V)).items:[],X5=z1(z4(r),N1(j.members,y,V,U)),h;await d5(C,async()=>{h=await Z9(R,j,V)},X5,{oaa:()=>$9(X,h,y)});let d=await v5(R,K,y,V);return V5(q(q5(h,y,d),M,Y))},P=async(M,Y,V)=>{let _=g(V);if(_&&_.entity.requestable!==!0)return F(V);if(_)await u(_,!0);let N=await Z1(R,K,V);if(!B(N))return F(V);let j=await M.json();if((_!==void 0||N[p]?.source==="code")&&(j.Operations??[]).some((m)=>!Q(m)))return l(V,"patched");let S={...N};for(let m of j.Operations??[])if(m.op==="replace"&&m.path&&m.value!==void 0){if(m.path==="displayName")S.displayName=m.value;else if(m.path===`${p}.requestable`)S[p]={...S[p],requestable:Boolean(m.value)};else if(m.path===`${p}.description`)S[p]={...S[p],description:String(m.value)};else if(m.path===`${p}.providerId`)S[p]={...S[p],providerId:String(m.value)};else if(m.path===`${p}.requestUrl`)S[p]={...S[p],requestUrl:String(m.value)}}else if(m.op==="add"&&m.path==="members"&&m.value!==void 0){let x5=m.value;S.members=[...S.members??[],...x5]}else if(m.op==="remove"&&m.path?.startsWith("members[")){let x5=m.path.match(/members\[value eq "([^"]+)"\]/);if(x5)S.members=(S.members??[]).filter((T1)=>T1.value!==x5[1])}let b=await n5(J.group,S);if(b.issues)return $.error("Group patch validation failed",{"ion.operation":"scim.group.patch","ion.outcome":"failure",validationIssues:b.issues}),f(400,`Request validation failed: ${b.issues.map((m)=>m.message).join("; ")}`,"invalidValue");let y=_?.kind??a5(S),U=_?W9(_.entity):e1(S),r=z1(N1(N.members,y,V,U),N1(S.members,y,V,U)),X5,h=!_||(j.Operations??[]).some((m)=>!e(m));await d5(C,async()=>{if(h)X5=await Z9(R,S,V)},r,h?{oaa:()=>$9(X,X5,y)}:void 0);let d=await Z1(R,K,V);return V5(q(d,M,Y))},I=async(M)=>{let Y=g(M);if(Y&&Y.entity.requestable!==!0)return F(M);if(Y)await u(Y,!0);let V=await Z1(R,K,M);if(!B(V))return F(M);let _=V[p];if((Y||_?.source==="code")&&_?.deprecated!==!0)return f(403,`Code-owned entitlement "${M}" can be deleted only after it is marked deprecated.`,"mutability");let N=a5(V);if(K){let j=await K.listByTarget(N,M),x=[];for(let S of j.items)await O1(C,S,x);await G9(C,x)}return await S4(R,M),new Response(null,{status:204})};W5={handler:z}}let j5;if(v.userStore){let{userStore:R,inboundUsers:q}=v,g=(Y)=>Y?.find((V)=>V.primary)?.value||Y?.[0]?.value,u=async(Y)=>{if(q?.mapBaseUserToScim)return await q.mapBaseUserToScim(Y);return r1(Y)},t=async(Y,V,_)=>{let N=await u(Y),j=N.id??Y.id;return{...N,id:j,meta:{...N.meta,resourceType:"User",location:j?M5(V,`${_}/${encodeURIComponent(j)}`):void 0}}},l=async(Y,V)=>{if(q?.mapValidatedScimToBaseUser)return await q.mapValidatedScimToBaseUser(Y,V);let _=new Date,N=g(Y.emails),j=Y.name?.formatted||[Y.name?.givenName,Y.name?.middleName,Y.name?.familyName].filter(Boolean).join(" ").trim()||Y.displayName,x=Y.id||V.existing?.id||i9(),S=Y.userName||N||V.existing?.userName||x,b=j||Y.displayName||V.existing?.name||S,y=Object.fromEntries(Object.entries(Y).filter(([d,m])=>d.startsWith("urn:")&&d!==K1&&d!==D5&&m!==void 0)),U=Y[D5],r=U?.ecid!==void 0&&U.ecid!==null?j1(U.ecid):V.existing?.ecid,X5=U?.accountClass??V.existing?.accountClass,h=V.existing?.sso;return{...V.existing??{},id:x,userName:S,name:b,email:N||V.existing?.email||S,avatar:Y.profileUrl,sso:{...h??{},profile:{...h?.profile??{},sub:x,iss:h?.profile.iss??"iam-provisioned",aud:h?.profile.aud??"iam-provisioned",exp:h?.profile.exp??Math.floor(Date.now()/1000)+3600,iat:h?.profile.iat??Math.floor(Date.now()/1000),email:N||V.existing?.email||S,email_verified:!0,name:b,preferred_username:S},tenant:h?.tenant??{id:"iam-provisioned",name:"IAM Provisioned"},scope:h?.scope??"openid profile email",tokenType:h?.tokenType??"Bearer",expires:h?.expires??new Date(Date.now()+3600000)},externalId:Y.externalId,ecid:r,accountClass:X5,displayName:Y.displayName,scimName:Y.name,emails:Y.emails,nickName:Y.nickName,title:Y.title,preferredLanguage:Y.preferredLanguage,locale:Y.locale,timezone:Y.timezone,active:Y.active,phoneNumbers:Y.phoneNumbers,ims:Y.ims,photos:Y.photos,addresses:Y.addresses,groups:Y.groups,entitlements:Y.entitlements,roles:Y.roles,x509Certificates:Y.x509Certificates,scimEnterprise:Y[K1],scimSchemaExtensions:Object.keys(y).length>0?y:void 0,createdAt:V.existing?.createdAt??(Y.meta?.created?new Date(Y.meta.created):_),updatedAt:Y.meta?.lastModified?new Date(Y.meta.lastModified):_,userType:Y.userType}},e=(Y,V,_)=>{Y[V]=_},Q=(Y,V,_)=>{let N=Y[V];if(Array.isArray(N)){Y[V]=[...N,...Array.isArray(_)?_:[_]];return}if(N&&typeof N==="object"&&!Array.isArray(N)&&_&&typeof _==="object"&&!Array.isArray(_)){Y[V]={...N,..._};return}Y[V]=_},B=(Y,V,_)=>{let N=V.match(/^(urn:.*:(?:User|Group))(?::(.+))?$/),j=N?[N[1],...N[2]?.split(":")??[]]:V.split("."),x=Y;for(let b of j.slice(0,-1)){let y=x[b];if(y===void 0){if(!_)return null;x[b]={}}else if(y===null||typeof y!=="object"||Array.isArray(y)){if(!_)return null;x[b]={}}x=x[b]}let S=j.at(-1);if(!S)return null;return{parent:x,key:S}},F=(Y,V)=>{let _=V.op.toLowerCase();if(!V.path){if(_!=="remove"&&V.value&&typeof V.value==="object"&&!Array.isArray(V.value))Object.assign(Y,V.value);return}let N=V.path.match(/^([A-Za-z0-9]+)\[value eq "([^"]+)"\]$/);if(N&&_==="remove"){let[,x,S]=N,b=Y[x];if(Array.isArray(b))Y[x]=b.filter((y)=>!(y&&typeof y==="object"&&("value"in y)&&y.value===S));return}let j=B(Y,V.path,_!=="remove");if(!j)return;if(_==="remove"){delete j.parent[j.key];return}if(_==="add"){Q(j.parent,j.key,V.value);return}e(j.parent,j.key,V.value)},z=async(Y,V)=>{if(!await w5(Y))return f(401,"Authorization required");let N=new URL(Y.url),j=V?.basePath??"/Users",x=N.pathname;if(x.startsWith(j))x=x.substring(j.length);let b=x.match(/^\/([^/]+)$/)?.[1],y=Y.method;try{if(b)switch(y){case"GET":return await w(Y,j,b);case"PUT":return await P(Y,j,b);case"PATCH":return await I(Y,j,b);case"DELETE":return await M(b);default:return f(405,"Method not allowed")}else if(x===""||x==="/")switch(y){case"GET":return await O(Y,j);case"POST":return await E(Y,j);default:return f(405,"Method not allowed")}return f(404,"Resource not found")}catch(U){if(U instanceof i5)return c9(U);if(X9(U))return f(409,U.message,"uniqueness");return $.error("Users inbound handler error",{"ion.operation":"scim.users.handler","ion.outcome":"failure"},U),f(500,U instanceof Error?U.message:"Internal server error")}},O=async(Y,V)=>{let _=new URL(Y.url),N=_.searchParams.get("startIndex"),j=_.searchParams.get("count"),x=N!=null?parseInt(N,10):void 0,S=j!=null?parseInt(j,10):void 0,b=x!=null&&!Number.isNaN(x)?Math.max(0,x-1):0,y=S!=null&&!Number.isNaN(S)?S:void 0,U=a9(_.searchParams.get("filter"));if(U!==void 0){let h=await R.lookup({externalId:U}),d=h?[await t(h,Y,V)]:[];return b5(d,{totalResults:d.length,startIndex:1,itemsPerPage:d.length})}let r=await R.list({start:b,limit:y}),X5=await Promise.all(r.items.map((h)=>t(h,Y,V)));return b5(X5,{totalResults:r.total,startIndex:b+1,itemsPerPage:r.count})},w=async(Y,V,_)=>{let N=await R.get(_);if(!N)return f(404,`User ${_} not found`,"invalidValue");return V5(await t(N,Y,V))},T=async(Y,V)=>{let _=C.accessIndex;if(!_?.setSubjectDisabled||!V.id)return;let N=Y?Y.active??!0:!0,j=V.active??!0;if(Y&&N===j)return;if(!Y&&j)return;await _.setSubjectDisabled(V.id,"user",!j)},E=async(Y,V)=>{let _=await Y.json(),N=await n5(J.user,_);if(N.issues)return $.error("User creation validation failed",{"ion.operation":"scim.user.create","ion.outcome":"failure",validationIssues:N.issues}),f(400,`Request validation failed: ${N.issues.map((b)=>b.message).join("; ")}`,"invalidValue");let j=N.value;if(!j.userName&&!j.emails?.[0]?.value)return f(400,"userName or email is required","invalidValue");let x=await l(j,{mode:"create"});await d5(C,async()=>{await R.upsert(x),await T(void 0,x)},s1(void 0,x),{oaa:async()=>{await J9(X,x)},delta:async()=>{await C.iamDelta?.onUserUpsert(x)}});let S=await t(x,Y,V);return V5(S,201,S.meta?.location)},P=async(Y,V,_)=>{let N=await R.get(_);if(!N)return f(404,`User ${_} not found`,"invalidValue");let j=await Y.json(),x=await n5(J.user,j);if(x.issues)return $.error("User replacement validation failed",{"ion.operation":"scim.user.replace","ion.outcome":"failure",validationIssues:x.issues}),f(400,`Request validation failed: ${x.issues.map((y)=>y.message).join("; ")}`,"invalidValue");let S=x.value,b=await l({...S,id:_},{existing:N,mode:"replace"});return b.createdAt=N.createdAt,b.updatedAt=new Date,await d5(C,async()=>{await R.upsert(b),await T(N,b)},s1(N,b),{oaa:async()=>{await J9(X,b)},delta:async()=>{await n9(C.iamDelta,N,b)}}),V5(await t(b,Y,V))},I=async(Y,V,_)=>{let N=await R.get(_);if(!N)return f(404,`User ${_} not found`,"invalidValue");let x=(await Y.json()).Operations??[],b={...await u(N)};for(let r of x)F(b,r);let y=await n5(J.user,b);if(y.issues)return $.error("User patch validation failed",{"ion.operation":"scim.user.patch","ion.outcome":"failure",validationIssues:y.issues}),f(400,`Request validation failed: ${y.issues.map((r)=>r.message).join("; ")}`,"invalidValue");let U=await l(y.value,{existing:N,mode:"patch"});return U.updatedAt=new Date,await d5(C,async()=>{await R.upsert(U),await T(N,U)},s1(N,U),{oaa:async()=>{await J9(X,U)},delta:async()=>{await n9(C.iamDelta,N,U)}}),V5(await t(U,Y,V))},M=async(Y)=>{let V=await R.get(Y);if(!V)return f(404,`User ${Y} not found`,"invalidValue");if(K){let _=await K.listBySubject(Y,"user"),N=[];for(let j of _.items)await O1(C,j,N);await G9(C,N)}if(await R.delete(Y),await C.accessIndex?.setSubjectDisabled?.(Y,"user",!1),V.externalId&&C.iamDelta?.isReady())await B1(C,"iam.delta.egress","IAM delta user delete failed after SCIM write; full aggregation will reconcile",()=>C.iamDelta?.onUserDelete(V.externalId)??Promise.resolve(),{id:Y,kind:"user"});else if(C.iamDelta?.isReady())C.log?.warn("IAM delta: deleted User has no externalId; destination delete skipped",{"ion.operation":"iam.delta.delete","ion.outcome":"skipped",id:Y,kind:"user"});if(C.authz.oaa.isReady())await B1(C,"authz.oaa.delete","OAA incremental user delete failed; full sync will reconcile",()=>C.authz.oaa.deleteUser(Y),{id:Y,kind:"user"});return new Response(null,{status:204})};j5={handler:z}}async function p5(R,q){z5();let g=new URL(R.url).pathname,u=y5(q?.usersUrl??v.usersUrl??"/api/iam/Users")??"/api/iam/Users",t=y5(q?.groupsUrl??v.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",l=await _5(R,q);if(l)return l;let e=(Q)=>g===Q||g.startsWith(`${Q}/`);if(e(u)){if(!i)return f(404,"SCIM Users endpoint is disabled by RemoteConfig");if(!j5)return f(501,"SCIM Users endpoint is enabled by RemoteConfig but no user store capability is wired by the application.");return j5.handler(R,{basePath:u})}if(e(t)){if(!G5)return f(404,"SCIM Groups endpoint is disabled by RemoteConfig");if(!W5)return f(501,"SCIM Groups endpoint is enabled by RemoteConfig but no AccessCatalogStore capability is wired by the application.");return W5.handler(R,{basePath:t})}return f(404,"Resource not found")}return{...v,createUser:O5,getBaseUrl:k5,groups_outbound:S5,groups_inbound:W5,users_inbound:j5,handler:p5,delta:a}}function _9(J,$){let Z=new TextEncoder().encode(J),X=typeof $==="string"?new TextEncoder().encode($):$,K=new Uint8Array(Z.length+1+X.length);return K.set(Z,0),K[Z.length]=46,K.set(X,Z.length+1),K}function U4(J){let $=J.replace(/-/g,"+").replace(/_/g,"/"),Z=$.length%4===0?"":"=".repeat(4-$.length%4),X=atob($+Z),K=new Uint8Array(X.length);for(let W=0;W<X.length;W++)K[W]=X.charCodeAt(W);return K}function C4(J){let $="";for(let Z of J)$+=String.fromCharCode(Z);return btoa($).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function r9(J){let $=JSON.parse(J);if(!$||typeof $!=="object"||!Array.isArray($.keys))throw Error("Invalid JWKS: expected { keys: [...] }");return $}function k4(J){return JSON.stringify(J)}async function f4(J){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:J.x},{name:"Ed25519"},!0,["verify"])}async function h4(J){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:J.x,d:J.d},{name:"Ed25519"},!0,["sign"])}async function g4(J){let Z=(typeof J.jwks==="string"?r9(J.jwks):J.jwks).keys.find((X)=>X.kid===J.kid&&X.kty==="OKP"&&X.crv==="Ed25519");if(!Z?.x)return!1;try{let X=await f4(Z),K=_9(J.requestId,J.rawBody),W=U4(J.signatureB64Url);return crypto.subtle.verify({name:"Ed25519"},X,W,K)}catch{return!1}}async function m4(J){let $=await h4(J.privateKeyJwk),Z=_9(J.requestId,J.rawBody),X=await crypto.subtle.sign({name:"Ed25519"},$,Z);return C4(new Uint8Array(X))}async function p4(J){let $=await crypto.subtle.generateKey({name:"Ed25519"},!0,["sign","verify"]),Z=await crypto.subtle.exportKey("jwk",$.privateKey),K=(await crypto.subtle.exportKey("jwk",$.publicKey)).x,W=Z.d;if(!K||!W)throw Error("Failed to export Ed25519 key material (missing x/d)");return{privateJwk:{kty:"OKP",crv:"Ed25519",x:K,d:W,kid:J,alg:"EdDSA",use:"sig"},publicJwks:{keys:[{kty:"OKP",crv:"Ed25519",x:K,kid:J,alg:"EdDSA",use:"sig"}]}}}var W1={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 E1(J,$){if(typeof J!=="number"||!Number.isFinite(J))return $.default;let Z=Math.floor(J);if(Z<$.min)return $.min;if(Z>$.max)return $.max;return Z}function s9(J){return{ttlMs:E1(J?.ttlSeconds,W1.jwksTtlSeconds)*1000,maxEntries:E1(J?.maxEntries,W1.jwksMaxEntries)}}function e9(J){let $=J?.read;return{read:{enabled:$?.enabled===!0,ttlMs:E1($?.ttlSeconds,W1.sessionReadTtlSeconds)*1000,maxEntries:E1($?.maxEntries,W1.sessionReadMaxEntries)}}}function u4(J){return{jwks:s9(J?.jwks),session:e9(J?.session)}}function l4(J){let $={};if(!J)return $;let Z=J.split(";");for(let X of Z){let K=X.trim();if(!K)continue;let W=K.indexOf("=");if(W===-1)continue;$[K.slice(0,W).trim()]=K.slice(W+1).trim()}return $}function J2(J){if(!J.expiresAt)return!1;let $=J.expiresAt instanceof Date?J.expiresAt:new Date(J.expiresAt);return!Number.isNaN($.getTime())&&Date.now()>$.getTime()}function c4(J){if(!J||typeof J!=="object"||Array.isArray(J))return;let{access_token:$,id_token:Z,refresh_token:X,tokens:K,...W}=J;return W}function H5(J,$){let Z=J[$];return typeof Z==="string"?Z:""}function d4(J,$){let Z=J.exp;if(typeof Z==="number")return new Date(Z*1000);if(typeof Z==="string"&&Z.trim()){let X=Number(Z);if(!Number.isNaN(X))return new Date(X*1000)}if($ instanceof Date)return $;if($){let X=new Date($);if(!Number.isNaN(X.getTime()))return X}return new Date}function n4(J){let $=J.claims;if(!$?.sub||typeof $.sub!=="string")return;let Z=d4($,J.expiresAt);if(J.authType==="sso")return{id:$.sub,userName:H5($,"preferred_username"),name:H5($,"name"),email:H5($,"email"),avatar:H5($,"picture")||void 0,sso:{profile:$,tenant:{id:H5($,"idp")||H5($,"iss"),name:H5($,"iss")},tokenType:"Bearer",expires:Z}};return{id:$.sub,userName:H5($,"preferred_username"),name:H5($,"name"),email:H5($,"email"),avatar:H5($,"picture")||void 0,userType:"customer",ciam:{profile:$,scope:"openid profile email",tokenType:"Bearer",expires:Z}}}function a4(J){if(J.authType!=="sso"&&J.authType!=="ciam")return;if(J2(J))return;return{sid:J.sid,authType:J.authType,tenantId:typeof J.tenantId==="string"?J.tenantId:void 0,sub:J.sub,expiresAt:J.expiresAt,createdAt:J.createdAt,claims:c4(J.claims)}}function i4(J,$){if(!J.endsWith(".session"))return!1;if(!$||$.length===0)return!0;return $.some((Z)=>J===`${Z}.session`)}function t4(J){if(J===void 0)return;let $=(Array.isArray(J)?J:[J]).map((Z)=>Z.trim()).filter((Z)=>Z.length>0);return $.length>0?$:void 0}async function $2(J,$,Z){return(await Z2(J,$,Z)).map(a4).filter((K)=>Boolean(K))}async function Z2(J,$,Z){let X=l4(J.headers.get("cookie")),K=t4(Z?.cookiesPrefix),W=[],G=new Set;for(let[L,D]of Object.entries(X)){if(!i4(L,K)||!D)continue;if(G.has(D))continue;G.add(D);let H=await $.get(D);if(!H)continue;if(H.authType!=="sso"&&H.authType!=="ciam")continue;if(J2(H))continue;W.push(H)}return W}async function o4(J,$,Z){return(await $2(J,$,Z)).map(n4).filter((K)=>Boolean(K))}var r4="@ionite/core",s4=c5(M1(r4));async function e4(J,$){let Z=await I5({idToken:J,jwksUri:$.jwksUri,issuer:$.issuer,audience:$.audience}),X=await s4.validate(Z);if(X.issues)throw Error(`ID token claims validation failed: ${X.issues.map((G)=>G.message).join("; ")}`);let K=X.value;if(K===void 0)throw Error("ID token claims missing");return X2(K)}function $5(J){return Date.now()-J}function O9(J){if(J instanceof Error)return{"error.name":J.name,"error.message":J.message};return{"error.name":typeof J,"error.message":String(J)}}function w1(J,$){if(!J)return{};try{let Z=new URL(J);return{[`${$}.origin`]:Z.origin,[`${$}.path`]:Z.pathname}}catch{return{[`${$}.path`]:J.startsWith("/")?J:`/${J}`}}}function P1(J,$=5){if(!Array.isArray(J))return[String(J)];return J.slice(0,$).map((Z)=>{if(!Z||typeof Z!=="object")return String(Z);let X=Z,K=Array.isArray(X.path)?X.path.join("."):String(X.path??""),W=typeof X.message==="string"?X.message:String(X.message??"validation failed");return K?`${K}: ${W}`:W})}function JJ(J){if(!J||typeof J!=="object")return{};let $=J;return{oidc_error:typeof $.error==="string"?$.error:void 0,oidc_error_description:typeof $.error_description==="string"?$.error_description:void 0,oidc_error_uri:typeof $.error_uri==="string"?$.error_uri:void 0}}function $J(J,$={}){let Z=typeof J==="string"?J:J?.headers.get("cookie")??void 0;if(!Z)return[];let K=`${$.cookiePrefix??"ion.sso"}.`,W=new Set;for(let G of Object.keys(XJ(Z))){if(!G.startsWith(K))continue;let L=G.slice(K.length),D=L.lastIndexOf(".");if(D<=0)continue;let H=L.slice(0,D).trim();if(H)W.add(H)}return Array.from(W)}function ZJ(J,$,Z,X,K){if(!Z&&!X)return;let W=new WeakMap,G=new Map,L={...Z,...X},D=!!(L.authority&&L.tokenUrl&&L.authorizationUrl&&L.clientId&&L.redirectUri&&L.scope),H={...L,authority:D?c(L.authority,"Missing 'authority' from SSO Config"):L.authority,tokenUrl:D?c(L.tokenUrl,"Missing 'tokenUrl' from SSO Config"):L.tokenUrl,authorizationUrl:D?c(L.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"):L.authorizationUrl,clientId:D?c(L.clientId,"Missing 'clientId' from SSO Config"):L.clientId,redirectUri:D?c(L.redirectUri,"Missing 'redirectUri' from SSO Config"):L.redirectUri,scope:D?c(L.scope,"Missing 'scope' from SSO Config"):L.scope,responseType:L.responseType??"code",cookiesSecure:L.cookiesSecure!==void 0?L.cookiesSecure:!0,cookiesSameSite:L.cookiesSameSite!==void 0?L.cookiesSameSite:"Strict",cookiesPrefix:L.cookiesPrefix??(L.clientId?`ion.sso.${L.clientId}`:"ion.sso"),cookiesPath:L.cookiesPath??"/"},k=Math.min(600,Math.max(0,Math.floor(Number(H.rotationGraceSeconds??60))||0))*1000,a=Math.floor(Number(H.sessionWindowSeconds??86400)),n=Number.isFinite(a)&&a>=1?a:86400;function o(){let Q=[];if(!H.authority)Q.push("authority");if(!H.tokenUrl)Q.push("tokenUrl");if(!H.authorizationUrl)Q.push("authorizationUrl");if(!H.clientId)Q.push("clientId");if(!H.redirectUri)Q.push("redirectUri");if(!H.scope)Q.push("scope");if(Q.length>0)throw Error(`Missing OIDC configuration fields: ${Q.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 Z5(Q){if(!H)throw Error("ionite SSO Manager not initialized");let B=W.get(Q);if(B)return B;let F=C(Q);return W.set(Q,F),F}async function C(Q){try{let{tokens:B,session:F,refreshedUser:z}=await R(Q);if(!B)return{status:"unauthenticated"};if(z)return{status:"authenticated",value:z};if(F?.claims)return{status:"authenticated",value:P5(F.claims,B,O5(F.expiresAt))};return{status:"unauthenticated"}}catch(B){if(Q2(B))return{status:"unauthenticated"};return $.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 Q5(Q){let B=await Z5(Q);return B.status==="authenticated"?B.value:void 0}async function v(Q){if(!H)throw Error("ionite SSO Manager not initialized");o();let B=c(H.redirectUri,"Missing 'redirectUri' from SSO Config"),F=c(H.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"),z=c(H.clientId,"Missing 'clientId' from SSO Config"),O=c(H.scope,"Missing 'scope' from SSO Config"),w=H.cookiesSecure?Q.url.replace(/^http:\/\//,"https://"):Q.url,T=F5(),E=F5(64),P=F5(),I=B;try{new URL(I)}catch{if(w)try{let N=new URL(w),j=I.startsWith("//")?I.slice(1):I.startsWith("/")?I:`/${I}`;I=new URL(j,N.origin).toString()}catch{try{let N=new URL(F),j=I.startsWith("//")?I.slice(1):I.startsWith("/")?I:`/${I}`;I=new URL(j,N.origin).toString()}catch{throw Error(`Invalid redirectUri: "${B}". It must be a valid absolute URL.`)}}}let M=new URL(F);M.searchParams.append("client_id",z),M.searchParams.append("redirect_uri",I),M.searchParams.append("response_type","code"),M.searchParams.append("scope",O),M.searchParams.append("state",T),M.searchParams.append("nonce",P);let Y=await J1(E);M.searchParams.append("code_challenge",Y),M.searchParams.append("code_challenge_method","S256");let V=await H.beforeLogin?.({request:Q}),_=V===void 0?{state:T,codeVerifier:E,nonce:P}:{state:T,codeVerifier:E,nonce:P,context:V};return new Response("Redirecting to SSO Provider",{status:302,headers:{Location:M.toString(),"Set-Cookie":g(l(T),_,H.loginStateTtl??600,"Lax")}})}async function i(Q){if(!H)throw Error("ionite SSO Manager not initialized");let B;try{B=await Q5(Q)}catch{B=void 0}let F=await H.beforeLogout?.({request:Q,user:B}),z=t("session",Q),O;try{O=await R(Q);let Y=O.tokens?.refresh_token??t("refresh",Q);if(Y)await h5(Y)}catch(Y){$.warn("Failed to revoke token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},Y)}if(H.sessionStore)try{let Y=O?.sid??z;if(Y)await H.sessionStore.delete(Y)}catch(Y){$.warn("Failed to delete session",{"ion.operation":"session.delete","ion.outcome":"degraded"},Y)}let w=[["Set-Cookie",u("session")]],T=await H.afterLogout?.({request:Q,context:F}),E=T5(T,"/",Q.url);if(E.response){let Y=new Headers(E.response.headers);for(let[,V]of w)Y.append("Set-Cookie",V);return new Response(E.response.body,{status:E.response.status,statusText:E.response.statusText,headers:Y})}let P=E.location??"/",I=Q.headers.get("accept");if(I?.includes("application/json")||I?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:P}),{status:200,headers:[["Content-Type","application/json"],...w]});return new Response("Logged out",{status:302,headers:[["Location",P],...w]})}async function G5(Q){if(!H)throw Error("ionite SSO Manager not initialized");if(!H.sessionStore)throw Error("Back-Channel Logout requires sessionStore configuration");try{if(!Q.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 F=await Q.text(),O=new URLSearchParams(F).get("logout_token");if(!O)return new Response("Missing logout_token parameter",{status:400});let w=c(H.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify logout tokens."),T=c(H.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify logout tokens."),E=H.jwksUri||`${w}/protocol/openid-connect/certs`,P=await c1({logoutToken:O,jwksUri:E,issuer:w,audience:T,log:$}),I=typeof P.sid==="string"?P.sid:void 0;if(!I)return $.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 H.sessionStore.delete(I),$.info("Back-Channel Logout: successfully deleted session",{"ion.module":"sso",sid:I}),new Response("OK",{status:200})}catch(B){return $.error("Error during back-channel logout",{"ion.operation":"backchannel_logout","ion.outcome":"failure"},B),new Response("Internal Server Error",{status:500})}}async function U5(Q){if(!H)throw Error("ionite SSO Manager not initialized");let B=Date.now(),F=new URL(Q.url),z=new URLSearchParams(F.search);$.debug("SSO callback received",{"ion.event":"ion.sso.callback.received","ion.module":"sso","ion.operation":"sign_in.callback","http.method":Q.method,"url.path":F.pathname,hasCode:z.has("code"),hasState:z.has("state"),hasError:z.has("error"),...w1(z.get("iss")??void 0,"oidc.issuer")});let O=Object.fromEntries(z.entries()),w=await J.callbackParams.validate(O);if(w.issues)return $.warn("SSO callback parameter validation failed",{"ion.event":"ion.sso.callback.validation_failed","ion.operation":"sign_in.callback","ion.outcome":"failure","validation.issues":P1(w.issues)}),K2(w.issues,"OIDC callback parameters validation failed");let{code:T,state:E}=w.value,P;try{let I=c(E,'OIDC "state" was not present in the callback parameters'),M=t(l(I),Q,!0),{codeVerifier:Y,state:V,nonce:_,context:N}=M??{};P=N,$.debug("SSO callback state cookie read",{"ion.event":"ion.sso.callback.state_cookie_read","ion.module":"sso","ion.operation":"sign_in.callback",hasStateCookie:Boolean(M),hasCodeVerifier:Boolean(Y),hasStateVerifier:Boolean(V),hasNonce:Boolean(_),hasContext:N!==void 0});let j=c(Y,'OIDC "codeVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');c(V,'OIDC "stateVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');let x=c(_,'OIDC "nonce" was not present in cookies, ensure that the SSO login was initiated correctly'),S=c(T,'OIDC "code" was not present in the callback parameters');if(E!==V)throw $.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');$.debug("SSO callback state verified",{"ion.event":"ion.sso.callback.state_verified","ion.module":"sso","ion.operation":"sign_in.callback"});let b=H.cookiesSecure?Q.url.replace(/^http:\/\//,"https://"):Q.url,y=await k5(S,j,b),{tokenExpiresAt:U,sessionExpiresAt:r}=z5(y);y.expires=U.toISOString();let X5=Date.now();$.debug("SSO ID token parsing started",{"ion.event":"ion.sso.id_token.parse_started","ion.module":"sso","ion.operation":"id_token.parse"});let h=await w5(y,x,r);$.debug("SSO ID token parsing completed",{"ion.event":"ion.sso.id_token.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":$5(X5),"user.id":h.id});let d,m;{let Y5=_5("SSO requires sessionStore configuration for opaque session cookies."),u5=typeof h.sso.profile.sid==="string"?h.sso.profile.sid:void 0,t5=u5||F5(32),L5=h.id;if($.debug("SSO session creation evaluated",{"ion.event":"ion.sso.session.create_evaluated","ion.module":"sso","ion.operation":"session.create",hasSid:Boolean(t5),hasIdpSid:Boolean(u5),hasSub:Boolean(L5),"user.id":L5}),!L5)throw Error("Session creation failed: missing sub in ID token claims");let x1=Date.now(),L1={sid:t5,sub:L5,idpSid:u5,authType:"sso",tenantId:H.tenantId,tokens:y,claims:h.sso.profile,expiresAt:r,createdAt:new Date};await S5(Y5,L1),m=L1,d=["Set-Cookie",g("session",t5,r)],$.info("SSO session created",{"ion.event":"ion.sso.session.created","ion.operation":"session.create","ion.outcome":"success","duration.ms":$5(x1),"user.id":L5})}if(H.userStore)try{let Y5=h.id;if(Y5){let u5=new Date,t5=Date.now();$.debug("SSO user store lookup started",{"ion.event":"ion.sso.user.lookup_started","ion.module":"sso","ion.operation":"user.lookup","user.id":Y5});let L5=await H.userStore.get(Y5);if($.debug("SSO user store lookup completed",{"ion.event":"ion.sso.user.lookup_completed","ion.module":"sso","ion.operation":"user.lookup","duration.ms":$5(t5),"user.id":Y5,found:Boolean(L5)}),L5||H.enableJitUserProvisioning){let x1=Date.now(),L1={...L5??{},...h,id:Y5,tenantId:L5?.tenantId,createdAt:L5?.createdAt??u5,updatedAt:u5};await H.userStore.upsert(L1),$.info("SSO user stored",{"ion.event":"ion.sso.user.stored","ion.operation":"user.store","ion.outcome":"success","duration.ms":$5(x1),"user.id":Y5,existing:Boolean(L5),jitProvisioning:Boolean(H.enableJitUserProvisioning)})}else $.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":Y5})}else $.warn("User storage skipped: missing sub in ID token claims",{"ion.event":"ion.sso.user.skipped","ion.operation":"user.store","ion.outcome":"skipped"})}catch(Y5){$.warn("Failed to store user",{"ion.event":"ion.sso.user.store_failed","ion.operation":"user.store","ion.outcome":"degraded",...O9(Y5)})}$.info("SSO sign-in succeeded",{"ion.event":"ion.sso.sign_in.succeeded","ion.operation":"sign_in.callback","ion.outcome":"success","duration.ms":$5(B),"user.id":h.id});let x5=[["Set-Cookie",u(l(I))],...d?[d]:[]],T1=await H.afterLogin?.({ok:!0,request:Q,user:h,session:m,context:P}),S1=T5(T1,"/",Q.url);if(S1.response)return R5(S1.response,x5.map(([,Y5])=>Y5));return new Response("Authentication successful, redirecting",{status:302,headers:[["Location",S1.location],...x5]})}catch(I){$.error("Error during sign-in callback",{"ion.event":"ion.sso.sign_in.callback_failed","ion.operation":"sign_in.callback","ion.outcome":"failure","duration.ms":$5(B),...O9(I)});let M=E?[["Set-Cookie",u(l(E))]]:[],Y=await H.afterLogin?.({ok:!1,request:Q,error:I,context:P}),V=T5(Y,"/",Q.url);if(V.response)return R5(V.response,M.map(([,_])=>_));return new Response("Authentication failed, redirecting",{status:302,headers:[["Location",V.location],...M]})}}function z5(Q){let B=Date.now(),F=Number(Q.expires_in??3600)||3600,z=new Date(B+F*1000),O;if(Q.refresh_expires_in!=null&&Number.isFinite(Number(Q.refresh_expires_in)))O=Number(Q.refresh_expires_in);else if(Q.refresh_token)O=n;else O=F;return{tokenExpiresAt:z,sessionExpiresAt:new Date(B+O*1000)}}async function w5(Q,B,F){if(!H)throw Error("ionite SSO Manager not initialized");let z=Date.now(),O=await m5(Q.id_token,B);return $.debug("SSO user parsed from ID token",{"ion.event":"ion.sso.user.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":$5(z),"user.id":O.sub,hasEmail:Boolean(O.email),hasName:Boolean(O.name)}),P5(O,Q,F)}function P5(Q,B,F){let z=F??z5(B).sessionExpiresAt,O=Q.ecid!==void 0&&Q.ecid!==null?j1(Q.ecid):void 0;return{id:Q.sub,userName:Q.preferred_username||"",name:Q.name||"",email:Q.email||"",emails:[{value:Q.email||"",primary:!0}],...O?{ecid:O}:{},avatar:Q.picture,sso:{profile:{...Q},tenant:{id:Q.idp||Q.iss||"",name:Q.iss||""},scope:B.scope,tokenType:B.token_type,sessionState:B.session_state,expires:z}}}async function C5(Q){if(!H.userStore)return Q;let B=await H.userStore.lookup(Q);if(!B)return Q;return{...Q,...B,id:Q.id,sso:Q.sso}}async function k5(Q,B,F){if(!H)throw Error("ionite SSO Manager not initialized");o();let z=c(H.tokenUrl,"Missing 'tokenUrl' from SSO Config"),O=c(H.redirectUri,"Missing 'redirectUri' from SSO Config"),w=c(H.clientId,"Missing 'clientId' from SSO Config"),T=O;try{new URL(T)}catch{if(F)try{let P=new URL(F),I=T.startsWith("//")?T.slice(1):T.startsWith("/")?T:`/${T}`;T=new URL(I,P.origin).toString()}catch{try{let P=new URL(z),I=T.startsWith("//")?T.slice(1):T.startsWith("/")?T:`/${T}`;T=new URL(I,P.origin).toString()}catch{throw Error(`Invalid redirectUri: "${O}". It must be a valid absolute URL.`)}}}let E=new URLSearchParams;if(E.append("grant_type","authorization_code"),E.append("code",Q),E.append("redirect_uri",T),E.append("client_id",w),H.clientSecret)E.append("client_secret",H.clientSecret);E.append("code_verifier",B);try{let P=Date.now();$.debug("SSO token exchange started",{"ion.event":"ion.sso.token.exchange_started","ion.module":"sso","ion.operation":"token.exchange",...w1(z,"oidc.token_url"),...w1(T,"oidc.redirect_uri"),hasClientSecret:Boolean(H.clientSecret)});let I=await fetch(z,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:E.toString()});$.debug("SSO token exchange response received",{"ion.event":"ion.sso.token.response_received","ion.module":"sso","ion.operation":"token.exchange","http.status_code":I.status,"duration.ms":$5(P)}),$.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 M=await I.json();if($.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":$5(P)}),!I.ok){$.error("Token exchange error",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":I.status,"duration.ms":$5(P),...JJ(M)});let V=M;throw Error(`Token exchange failed: ${V.error||I.statusText} - ${V.error_description||""}`.trim())}let Y=await J.tokenResponse.validate(M);if(Y.issues)throw $.error("Token response validation failed",{"ion.event":"ion.sso.token.response_validation_failed","ion.operation":"token.exchange","ion.outcome":"failure","duration.ms":$5(P),"validation.issues":P1(Y.issues)}),Error(`Token response validation failed: ${Y.issues}`);return $.debug("SSO token exchange completed",{"ion.event":"ion.sso.token.exchange_completed","ion.module":"sso","ion.operation":"token.exchange","ion.outcome":"success","duration.ms":$5(P),tokenType:Y.value.token_type,hasAccessToken:Boolean(Y.value.access_token),hasIdToken:Boolean(Y.value.id_token),hasRefreshToken:Boolean(Y.value.refresh_token),expiresIn:Y.value.expires_in}),Y.value}catch(P){throw $.error("Error during token exchange",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure",...O9(P)}),P}}async function f5(Q){return h1(async()=>{if(!H)throw Error("ionite SSO Manager not initialized");o();let B=c(H.tokenUrl,"Missing 'tokenUrl' from SSO Config"),F=c(H.clientId,"Missing 'clientId' from SSO Config"),z=new URLSearchParams;if(z.append("grant_type","refresh_token"),z.append("refresh_token",Q),z.append("client_id",F),H.clientSecret)z.append("client_secret",H.clientSecret);let O=await fetch(B,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:z.toString()}),w=await O.json();if(!O.ok){$.error("Token refresh error",{"ion.operation":"token.refresh","ion.outcome":"failure",response:w});let E=w;throw Error(`Token refresh failed: ${E.error||O.statusText} - ${E.error_description||""}`.trim())}let T=await J.tokenResponse.validate(w);if(T.issues)throw $.error("Token refresh response validation failed",{"ion.event":"ion.sso.token.refresh_validation_failed","ion.operation":"token.refresh","ion.outcome":"failure","validation.issues":P1(T.issues)}),Error(`Token refresh response validation failed: ${T.issues}`);return T.value},void 0,void 0,void 0,$)}async function h5(Q){try{if(!H)throw Error("ionite SSO Manager not initialized");if(!H.revocationEndpoint)return;let B=c(H.clientId,"Missing 'clientId' from SSO Config"),F=new URLSearchParams;if(F.append("token",Q),F.append("token_type_hint","refresh_token"),F.append("client_id",B),H.clientSecret)F.append("client_secret",H.clientSecret);let z=await fetch(H.revocationEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:F.toString()});if(!z.ok)$.warn("Token revocation failed",{"ion.operation":"token.revoke","ion.outcome":"degraded",status:z.status,statusText:z.statusText});else $.info("Token revoked successfully",{"ion.module":"sso"})}catch(B){$.warn("Error revoking token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},B)}}async function g5(){if(!H)throw Error("ionite SSO Manager not initialized");let Q=H.authority;if(!H.jwksUri&&!Q)throw Error("Missing 'jwksUri' or 'authority' from SSO Config. OIDC configuration is required for this operation.");let B=H.jwksUri||`${Q}/protocol/openid-connect/certs`;return r5(B,$)}async function m5(Q,B){let F=Date.now(),z=c(H.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify ID tokens."),O=c(H.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify ID tokens."),w=H.jwksUri||`${z}/protocol/openid-connect/certs`;$.debug("SSO ID token verification started",{"ion.event":"ion.sso.id_token.verify_started","ion.module":"sso","ion.operation":"id_token.verify",...w1(w,"oidc.jwks_uri")});let T;try{T=await I5({idToken:Q,jwksUri:w,issuer:z,audience:O,expectedNonce:B,log:$})}catch(P){throw $.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":$5(F)},P),P}$.debug("SSO ID token signature verified",{"ion.event":"ion.sso.id_token.signature_verified","ion.module":"sso","ion.operation":"id_token.verify","duration.ms":$5(F)});let E=await J.idTokenClaims.validate(T);if(E.issues)throw $.error("ID token claims validation failed",{"ion.event":"ion.sso.id_token.validation_failed","ion.operation":"id_token.validate","ion.outcome":"failure","duration.ms":$5(F),"validation.issues":P1(E.issues)}),Error(`ID token claims validation failed: ${E.issues}`);return $.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":$5(F),"user.id":E.value.sub,hasIssuer:Boolean(E.value.iss),hasAudience:Boolean(E.value.aud)}),E.value}function _5(Q="SSO sessionStore is required for opaque session cookies."){if(!H.sessionStore)throw Error(Q);return H.sessionStore}async function S5(Q,B){try{await Q.create(B)}catch(F){if(!await Q.get(B.sid))throw F;await Q.update(B.sid,B)}}function O5(Q){if(!Q)return;if(Q instanceof Date)return Q;let B=new Date(Q);return Number.isNaN(B.getTime())?void 0:B}function W5(Q){let B=Q.tokens;if(!B?.access_token||!B.id_token||!B.token_type)return;return B}async function j5(Q,B=!1){let F=_5(),z=t("session",Q);if(!z)return{tokens:void 0,refreshHeaders:[]};let O=await F.get(z);if(O&&H.tenantId&&O.tenantId&&O.tenantId!==H.tenantId)return{tokens:void 0,refreshHeaders:[["Set-Cookie",u("session")]],sid:z};if(O?.authType!=="sso")return{tokens:void 0,refreshHeaders:[["Set-Cookie",u("session")]],sid:z};let w=W5(O);if(!w)return{tokens:void 0,refreshHeaders:[["Set-Cookie",u("session")]],sid:z};let T=O5(O.expiresAt);if(T?Date.now()>T.getTime():!1)return await F.delete(z),{tokens:void 0,sid:z,refreshHeaders:[["Set-Cookie",u("session")]]};let P=O5(w.expires),I=P?Date.now()>P.getTime():!0;if((B||I)&&w.refresh_token)return p5(z,O,w);return{tokens:w,sid:z,session:O,refreshHeaders:[]}}function p5(Q,B,F){let z=G.get(Q);if(z)return z;let O=_5(),w=(async()=>{let T=await f5(F.refresh_token),{tokenExpiresAt:E,sessionExpiresAt:P}=z5(T);T.expires=E.toISOString();let I=await w5(T,void 0,P),M=I.sso.profile,Y=F5(32),V={...B,sid:Y,tokens:T,claims:M,expiresAt:P,createdAt:new Date};await S5(O,V);try{if(k<=0)await O.delete(Q);else{let{refresh_token:_,...N}=F;await O.update(Q,{tokens:N,expiresAt:new Date(Date.now()+k)})}}catch(_){$.warn("Failed to retire rotated SSO session record",{"ion.operation":"session.rotate","ion.outcome":"degraded"},_)}return{tokens:T,sid:Y,session:V,refreshedUser:I,refreshHeaders:[["Set-Cookie",g("session",Y,P)]]}})();return G.set(Q,w),w.finally(()=>{G.delete(Q)})}async function R(Q,B=!1){return j5(Q,B)}async function q(Q){let{tokens:B}=await R(Q);if(!B)return;return B.access_token}function g(Q,B,F,z=H.cookiesSameSite??"Strict"){if(!H)throw Error("ionite SSO Manager not initialized");if(Q=`${H.cookiesPrefix}.${Q}`,typeof B!=="string")B=btoa(JSON.stringify(B));let O;if(F instanceof Date)O=`Expires=${F.toUTCString()}`;else if(typeof F==="number")O=`Max-Age=${F}`;else throw Error("Invalid expires type",F);if(B.length>4000)throw Error(`Error setting cookie: ${Q}. Cookie length is: ${B.length}`);return`${Q}=${B}; ${O}; Path=${H.cookiesPath}; HttpOnly;${H.cookiesSecure?" Secure;":""} SameSite=${z};`}function u(Q){if(!H)throw Error("ionite SSO Manager not initialized");return`${H.cookiesPrefix}.${Q}=; Max-Age=0; Path=${H.cookiesPath}; HttpOnly;${H.cookiesSecure?" Secure;":""} SameSite=${H.cookiesSameSite};`}function t(Q,B,F=!1){if(!H)throw Error("ionite SSO Manager not initialized");let z=B.headers.get("cookie");if(!z)return null;let O=`${H.cookiesPrefix}.${Q}`,w=z.split(";").find((I)=>I.trim().startsWith(`${O}=`));if(!w)return null;let T=w.indexOf("="),E=w.slice(T+1).trim();if(!F)return E;let P=atob(E);return JSON.parse(P)}function l(Q){return`state_${Q}`}async function e(Q,B){if(!H)throw Error("ionite SSO Manager not initialized");let{loginUrl:F,userUrl:z,tokenUrl:O,refreshUrl:w,logoutUrl:T,logoutBackChannelUrl:E,jwksUrl:P,redirectUri:I}={...H,...B},M=new URL(Q.url).pathname;if(I){let Y;try{Y=new URL(I).pathname}catch{try{let V=new URL(Q.url),_=I.startsWith("//")?I.slice(1):I;Y=new URL(_,V.origin).pathname}catch{Y=I.startsWith("/")?I:`/${I}`}}if(Y===M)return U5(Q)}if(F===M)return v(Q);if(z===M)try{let{tokens:Y,session:V,refreshedUser:_,refreshHeaders:N}=await R(Q);if(!Y)return new Response("User not logged in",{status:401,headers:N});let j=_??(V?.claims?P5(V.claims,Y,O5(V.expiresAt)):void 0);if(!j)return new Response("User not logged in",{status:401,headers:N});let x=await C5(j);return new Response(JSON.stringify(x),{headers:[["Content-Type","application/json"],...N]})}catch(Y){if(Q2(Y))return new Response("User not logged in",{status:401});return $.error("Error resolving SSO user",{"ion.operation":"sso.user","ion.outcome":"degraded"},Y),new Response(JSON.stringify({error:"auth_unavailable"}),{status:503,headers:{"Content-Type":"application/json"}})}if(O===M){let{tokens:Y,refreshHeaders:V}=await R(Q);if(!Y)return new Response("User not logged in",{status:401,headers:V});return new Response(JSON.stringify({token:Y.access_token,expires:Y.expires}),{headers:[["Content-Type","application/json"],...V]})}if(w===M){let{tokens:Y,refreshHeaders:V}=await R(Q,!0);if(!Y)return new Response("User not logged in",{status:401});return new Response("Refresh Complete",{status:200,headers:V})}if(T===M)return i(Q);if(E===M)return G5(Q);if(P===M){let Y=await g5();return new Response(JSON.stringify(Y),{headers:[["Content-Type","application/json"]]})}return new Response("Not Found",{status:404})}return{...H,getUser:Q5,resolveUser:Z5,getJwt:q,initiateLogin:v,logout:i,logoutBackChannel:G5,callbackHandler:U5,handler:e}}function XJ(J){let $={},Z=J.split(";");for(let X of Z){let K=X.trim();if(!K)continue;let W=K.indexOf("=");if(W===-1)continue;let G=K.slice(0,W).trim(),L=K.slice(W+1).trim();$[G]=L}return $}function Q2(J){if(!(J 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(($)=>J.message.includes($))}function Y2(J){return J=J??"SSO Unavailable",new Response(JSON.stringify({error:J}),{status:503,statusText:J,headers:{"Content-Type":"application/json"}})}var I1="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.";async function QJ(J,$){return c($,I1),$.sso?.getUser(J)}async function KJ(J,$){return c($,I1),await $.sso?.resolveUser(J)??{status:"unauthenticated"}}async function YJ(J,$){c($,I1);let Z=$.sso;if(!Z)return Y2();return Z.initiateLogin(J)}async function BJ(J,$){c($,I1);let Z=$.sso;if(!Z)return Y2();return Z.callbackHandler(J)}export{R5 as withSetCookies,e4 as verifyUser,c1 as verifyLogoutToken,g4 as verifyLfvSignature,I5 as verifyIdToken,k4 as stringifyLfvJwks,ZJ as sso,m4 as signLfvPayload,I2 as setJwksRetry,P2 as setJwksClock,f2 as setDiscoveryClock,LJ as sendTenantWebhook,i1 as sameOriginRedirectRules,KJ as resolveUser,e9 as resolveSessionCacheConfig,t1 as resolveRedirect,v1 as resolveProviderBranding,s9 as resolveJwksCacheConfig,R2 as resolveJwkForKid,s2 as resolveCustomer,V1 as resolveCiamProvider,a2 as resolveCapturedRedirect,u4 as resolveCacheConfig,T5 as resolveAfterRedirect,N9 as reconcileSubjectAccess,J1 as pkceChallengeFromVerifier,r9 as parseLfvJwks,q1 as orderedEnabledProviders,e5 as normalizeOidcIssuer,$J as listSsoClientIdsFromCookies,g9 as isRedirectAllowed,YJ as initiateLogin,q4 as iam,j2 as hasScope,N2 as hasRole,M2 as hasPermission,z2 as hasGroup,A2 as hasAnyScope,_2 as hasAny,E2 as hasAllScope,O2 as hasAll,D2 as has,m1 as getVerificationKeyForKid,QJ as getUser,b2 as getPublicKeyFromJwks,y2 as getPublicKeyForKid,y1 as getProviderPreset,r5 as getJwks,o4 as getDiscoveredSessionUsers,r2 as getCustomer,g1 as getCachedVerificationKey,p4 as generateLfvEd25519KeyPair,a1 as generateAppleClientSecret,n1 as fetchUserInfo,M9 as expandRoot,l1 as exchangeAuthorizationCode,o1 as entitlementToScimGroup,$2 as discoverSessions,Z2 as discoverSessionRecords,d1 as discoverOidcEndpoints,d2 as defaultRedirectPolicies,w2 as configureJwksCache,GJ as collectReferencedDefinitions,x2 as clearJwksCache,h2 as clearDiscoveryCache,o2 as ciam,n2 as captureRedirect,BJ as callback,_9 as buildLfvSigningInput,u1 as buildAuthorizationUrl,k9 as blockDangerousUrls,r1 as baseUserToScimUser,q9 as assertTrustedIdTokenClaims,h9 as allowSameOrigin,f9 as allowRelativePaths,l2 as allowOrigins,c2 as allowHosts,WJ as InMemoryTenantStore,D9 as CatalogAdjacencyCache,P9 as CIAM_PROVIDER_PRESETS,W1 as CACHE_BOUNDS};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ionite/core",
3
- "version": "0.0.23-beta.20260825.2",
3
+ "version": "0.0.23-beta.20260828.1",
4
4
  "description": "ionite Core (client-safe main entry; server handlers under ./server)",
5
5
  "private": false,
6
6
  "author": "ionite",