@ionite/core 0.0.24-beta.20260921.8 → 0.0.24-beta.20260922.9
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 +12 -3
- package/dist/index.js +1 -1
- package/dist/server.d.ts +12 -3
- package/dist/server.js +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1498,11 +1498,13 @@ type AccessRequestCreate = {
|
|
|
1498
1498
|
subjectType: SubjectType;
|
|
1499
1499
|
targetType: EntitlementType;
|
|
1500
1500
|
target: string;
|
|
1501
|
+
operation: "grant" | "revoke";
|
|
1501
1502
|
justification?: string;
|
|
1502
1503
|
};
|
|
1503
1504
|
type AccessRequestResult = {
|
|
1504
1505
|
id: string;
|
|
1505
1506
|
status: "pending" | "approved" | "denied";
|
|
1507
|
+
operation: "grant" | "revoke";
|
|
1506
1508
|
trackingUrl: string;
|
|
1507
1509
|
};
|
|
1508
1510
|
/** SCIM resource types the delta patch adapter addresses. */
|
|
@@ -2257,13 +2259,17 @@ type IamPrincipalKind = {
|
|
|
2257
2259
|
delta?: IamDeltaMode;
|
|
2258
2260
|
};
|
|
2259
2261
|
type IAMAccessRequestsConfig = {
|
|
2260
|
-
create: (request: AccessRequestCreate) => Promise<
|
|
2262
|
+
create: (request: AccessRequestCreate) => Promise<{
|
|
2263
|
+
request: AccessRequestResult;
|
|
2264
|
+
created: boolean;
|
|
2265
|
+
}>;
|
|
2261
2266
|
};
|
|
2262
2267
|
type AccessRequestSubmit = {
|
|
2263
2268
|
subject: AccessChange["subject"];
|
|
2264
2269
|
subjectType: SubjectType;
|
|
2265
2270
|
targetType: EntitlementType;
|
|
2266
2271
|
target: AccessChange["target"];
|
|
2272
|
+
operation: "grant" | "revoke";
|
|
2267
2273
|
justification?: string;
|
|
2268
2274
|
};
|
|
2269
2275
|
type IAMEntitlementRequestUrlContext = {
|
|
@@ -5829,18 +5835,21 @@ type Authz = {
|
|
|
5829
5835
|
*/
|
|
5830
5836
|
grant(change: AccessChange): Promise<AccessChange>;
|
|
5831
5837
|
/**
|
|
5832
|
-
* Submit
|
|
5833
|
-
* policy is `'iam-request'`.
|
|
5838
|
+
* Submit one grant or revoke request on a principal's behalf. Allowed only when that kind's
|
|
5839
|
+
* assignment policy is `'iam-request'`. One operation maps to one approval decision, status,
|
|
5840
|
+
* and tracking URL. Authenticated with the module-wide `deltaAudience` workload client.
|
|
5834
5841
|
*/
|
|
5835
5842
|
requestAccess(change: {
|
|
5836
5843
|
subject: AccessChange["subject"];
|
|
5837
5844
|
subjectType: SubjectType;
|
|
5838
5845
|
targetType: EntitlementType;
|
|
5839
5846
|
target: AccessChange["target"];
|
|
5847
|
+
operation: "grant" | "revoke";
|
|
5840
5848
|
justification?: string;
|
|
5841
5849
|
}): Promise<{
|
|
5842
5850
|
id: string;
|
|
5843
5851
|
status: "pending" | "approved" | "denied";
|
|
5852
|
+
operation: "grant" | "revoke";
|
|
5844
5853
|
trackingUrl: string;
|
|
5845
5854
|
}>;
|
|
5846
5855
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{E,X,o,h,S,b,r,R,i,Q,U,u,e,d,W,M,V,H,ee,F,A,I,y,v,j,x,n,c,ne,k,J,re,se,w,N,L,l,a,t,D,oe,Y,ie,C,p,ae,ce,P,ue,m,T,G,B,de,s,f,g,pe,me,q,K}from"./shared/core-j5xhxcmq.js";var Je="0.0.24-beta.
|
|
1
|
+
import{E,X,o,h,S,b,r,R,i,Q,U,u,e,d,W,M,V,H,ee,F,A,I,y,v,j,x,n,c,ne,k,J,re,se,w,N,L,l,a,t,D,oe,Y,ie,C,p,ae,ce,P,ue,m,T,G,B,de,s,f,g,pe,me,q,K}from"./shared/core-j5xhxcmq.js";var Je="0.0.24-beta.20260922.9";class he extends Error{constructor(O,_){super(O,_.cause!==void 0?{cause:_.cause}:void 0);this.name="ConfigSourceError",this.kind=_.kind,this.recoverable=_.recoverable,this.code=_.code,this.status=_.status,this.path=_.path,this.sourceType=_.sourceType,Object.setPrototypeOf(this,he.prototype)}}function Ye(O){return O instanceof he}var Se=["workload"],Ie={id:"ion:iam:read",name:"Read Identities (SCIM)",description:"Authorizes a workload to list and read Users, Groups, Workloads, and Customers via the SCIM endpoints.",requestable:!1,permissionTypes:["DataRead"],assignableSubjectTypes:Se,recommendedSubjectTypes:Se},we={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:Se,recommendedSubjectTypes:Se},xe={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:Se,recommendedSubjectTypes:Se},Pe={id:"ion:iam:workloads:write",name:"Manage Workloads (SCIM Workloads)",description:"Authorizes a workload to create, replace, modify, and delete Workload principals via SCIM, including access-root revocation on delete.",requestable:!1,permissionTypes:["DataCreate","DataWrite","DataDelete"],assignableSubjectTypes:Se,recommendedSubjectTypes:Se},Oe={id:"ion:iam:customers:write",name:"Manage Customers (SCIM Customers)",description:"Authorizes a workload to create, replace, modify, and delete Customer principals via SCIM, including access-root revocation on delete.",requestable:!1,permissionTypes:["DataCreate","DataWrite","DataDelete"],assignableSubjectTypes:Se,recommendedSubjectTypes:Se},_e={id:"ion:iam:access-requests:write",name:"Submit Access Requests",description:"Authorizes a workload to submit an access request on a principal's behalf via the AccessRequests endpoint.",requestable:!1,permissionTypes:["DataCreate"],assignableSubjectTypes:Se,recommendedSubjectTypes:Se},ve={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:Se,recommendedSubjectTypes:Se},Ke={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:Se},Me={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:Se,recommendedSubjectTypes:Se},Ne={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:Se,recommendedSubjectTypes:Se},Ze=[Ie,we,xe,Pe,Oe,_e,ve,Ke,Me,Ne],Qe={"iam.read":{permission:Ie,subjectType:["workload"]},"iam.users.write":{permission:we,subjectType:["workload"]},"iam.groups.write":{permission:xe,subjectType:["workload"]},"iam.workloads.write":{permission:Pe,subjectType:["workload"]},"iam.customers.write":{permission:Oe,subjectType:["workload"]},"iam.access-requests.write":{permission:_e,subjectType:["workload"]},"capabilitiez.read":{permission:ve,subjectType:["workload"]},"ciam.magic-link.create":{permission:Ke,subjectType:["workload","user"]},"authz.oaa.sync":{permission:Me,subjectType:["workload"]},"tenant.manage":{permission:Ne,subjectType:["workload"]}};var Xe=["sessionStore","userStore","customerStore","accessStore","tokenStore","magicLinkStore","store"];function We(O){if(O===null||typeof O!=="object")return O;let _={};for(let[z,Z]of Object.entries(O)){if(Xe.includes(z)||z==="validators"||z==="setStores")continue;_[z]=Z!==null&&typeof Z==="object"&&!Array.isArray(Z)&&Object.getPrototypeOf(Z)===Object.prototype?We(Z):Z}return _}function et(O){return We(O)}function be(O,_){if(!O||typeof O!=="object"||Array.isArray(O))throw Error(`${_} must be an object.`);return O}function Re(O,_){if(O===void 0)return;if(typeof O!=="string"||O.length===0||!Number.isFinite(Date.parse(O)))throw Error(`${_} must be a valid timestamp string.`);return O}function je(O,_,z){if(!Array.isArray(O)||!z.allowEmpty&&O.length===0)throw Error(`${_} keys must be ${z.allowEmpty?"an":"a non-empty"} array.`);let Z=new Set;return O.map((ge,te)=>{let le=be(ge,`${_} keys[${te}]`);if(typeof le.id!=="string"||le.id.length===0)throw Error(`${_} keys[${te}].id must be a non-empty string.`);if(Z.has(le.id))throw Error(`${_} contains duplicate key id "${le.id}".`);if(Z.add(le.id),!["pending","active","deprecated","rotated","revoked"].includes(String(le.state)))throw Error(`${_} keys[${te}].state is invalid.`);if(le.value!==void 0&&(typeof le.value!=="string"||le.value.length===0))throw Error(`${_} keys[${te}].value must be a non-empty string when present.`);let fe=le.meta===void 0?void 0:be(le.meta,`${_} keys[${te}].meta`);return{id:le.id,state:le.state,...le.value===void 0?{}:{value:le.value},...le.notBefore===void 0?{}:{notBefore:Re(le.notBefore,`${_} keys[${te}].notBefore`)},...le.notAfter===void 0?{}:{notAfter:Re(le.notAfter,`${_} keys[${te}].notAfter`)},...le.createdAt===void 0?{}:{createdAt:Re(le.createdAt,`${_} keys[${te}].createdAt`)},...le.activatedAt===void 0?{}:{activatedAt:Re(le.activatedAt,`${_} keys[${te}].activatedAt`)},...le.deprecatedAt===void 0?{}:{deprecatedAt:Re(le.deprecatedAt,`${_} keys[${te}].deprecatedAt`)},...le.rotatedAt===void 0?{}:{rotatedAt:Re(le.rotatedAt,`${_} keys[${te}].rotatedAt`)},...le.revokedAt===void 0?{}:{revokedAt:Re(le.revokedAt,`${_} keys[${te}].revokedAt`)},...fe?{meta:{...fe}}:{}}})}function tt(O,_,z){if(O===void 0)return;if(!Array.isArray(O))throw Error(`${z} slots must be an array.`);let Z=new Set,ge=O.map((te,le)=>{if(te===null)return null;if(typeof te!=="string"||te.length===0)throw Error(`${z} slots[${le}] must be a non-empty key id or null.`);if(Z.has(te))throw Error(`${z} slots contain duplicate key id "${te}".`);Z.add(te);let fe=_.find((ye)=>ye.id===te);if(!fe)throw Error(`${z} slot key "${te}" is not present in keys.`);if(fe.state!=="active")throw Error(`${z} slot key "${te}" must have state "active".`);if(!fe.value)throw Error(`${z} slot key "${te}" must include a value.`);return te});if(_.length===0&&ge.some((te)=>te!==null))throw Error(`${z} slots must be omitted or all-null when keys is empty.`);return ge}function ot(O){let z=be(O,"KMS pool");if(z.kind!=="kms")throw Error('KMS pool kind must be "kms".');let Z=je(z.keys,"KMS pool",{allowEmpty:!0}),ge=tt(z.slots,Z,"KMS pool");return ge?{kind:"kms",slots:ge,keys:Z}:{kind:"kms",keys:Z}}function rt(O){let z=be(O,"KMS pool control document");if(z.kind!=="kms")throw Error('KMS pool control document kind must be "kms".');return{kind:"kms",keys:je(z.keys,"KMS pool control document",{allowEmpty:!0})}}var nt={trace:"TRACE",debug:"DEBUG",info:"INFO ",warn:"WARN ",error:"ERROR"};function qe(O){if(typeof O==="string")return O;try{return JSON.stringify(O)??String(O)}catch{return String(O)}}function Ee(O){let _=qe(O);return/^[A-Za-z0-9_./:@+|-]+$/.test(_)?_:JSON.stringify(_)}function st(O){return qe(O).replaceAll("\r","\\r").replaceAll(`
|
|
2
2
|
`,"\\n")}function $e(O,_,z){if(z==null)return;if(z instanceof Error){if(O.push(`${_}.name=${Ee(z.name)}`),O.push(`${_}.message=${Ee(z.message)}`),z.stack)O.push(`${_}.stack=${Ee(z.stack)}`);return}O.push(`${_}=${Ee(z)}`)}function Te(O,_,z=[],Z=new Date){let ge=st(_ instanceof Error?_.message:_??""),te=[];for(let[le,fe]of z.entries()){if(fe&&typeof fe==="object"&&!Array.isArray(fe)&&!(fe instanceof Error)&&Object.getPrototypeOf(fe)===Object.prototype){for(let[ye,ke]of Object.entries(fe))$e(te,ye,ke);continue}$e(te,`param.${le}`,fe)}return[Z.toISOString(),nt[O],ge,...te].filter(Boolean).join(" ")}var Ue={trace:()=>{},debug:()=>{},info:()=>{},warn:()=>{},error:()=>{}},it=Ue,at={trace:()=>{},debug:console.debug,info:console.info,warn:console.warn,error:console.error},pt={trace:()=>{},debug:()=>{},info:console.info,warn:console.warn,error:console.error},ct={trace:()=>{},debug:()=>{},info:()=>{},warn:console.warn,error:console.error},mt={trace:()=>{},debug:(O,..._)=>globalThis.console.debug(Te("debug",O,_)),info:(O,..._)=>globalThis.console.info(Te("info",O,_)),warn:(O,..._)=>globalThis.console.warn(Te("warn",O,_)),error:(O,..._)=>globalThis.console.error(Te("error",O,_))};function ut(O,_){if(typeof _!=="number"||_<=0)return O;return new Promise((z,Z)=>{let ge=setTimeout(()=>{Z(Error(`Authz catalog entry did not become ready within ${_}ms`))},_);O.then(()=>{clearTimeout(ge),z()},(te)=>{clearTimeout(ge),Z(te)})})}function dt(O,_){let z=!1,Z,ge=_.then(()=>{z=!0},(le)=>{z=!1,Z=le}),te=O;return Object.defineProperty(te,"ready",{enumerable:!1,configurable:!0,value:(le)=>ut(ge.then(()=>{if(!z)throw Z}),le)}),Object.defineProperty(te,"isReady",{enumerable:!1,configurable:!0,value:()=>z}),te}var Le=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 De(O){if(!O.id.trim())throw Error("defineSecretType: id is required");let _=O.mimeType?.trim()||Le[O.format],z=Object.freeze({id:O.id,...O.label?{label:O.label}:{},format:O.format,mimeType:_,...O.schemaUrl?{schemaUrl:O.schemaUrl}:{},typeId:O.id});return Object.freeze({id:O.id,...O.label?{label:O.label}:{},format:O.format,mimeType:_,...O.schemaUrl?{schemaUrl:O.schemaUrl}:{},...O.schema?{schema:O.schema}:{},toRegistryEntry:()=>z})}function lt(O="jsonc"){return{format:O,mimeType:Le[O],typeId:O}}class ze extends Error{constructor(O,_){super(`Secret content type mismatch: expected "${O.mimeType}" (${O.format}) but received "${_.mimeType}" (${_.format})`);this.name="SecretContentTypeMismatchError",this.expected=O,this.received=_}}var gt=De({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 Ve={beforeTenantSegments:["ui"]},Ge={beforeTenantSegments:["api"]};function Fe(O){return(O??[]).map((_)=>_.trim()).filter(Boolean)}function yt(O){let _=O.trim();if(!_)return"/";let z=_.replace(/\\/g,"/").replace(/\/+/g,"/");return z.startsWith("/")?z:`/${z}`}function Be(O){return yt(O).split("/").filter(Boolean)}function Ae(O){return{beforeTenantSegments:Fe(O?.beforeTenantSegments),afterTenantSegments:Fe(O?.afterTenantSegments)}}function ft(O){return{type:"path",ui:Ae(O?.ui??Ve),api:Ae(O?.api??Ge)}}function St(O,_){let z=Ae(_),Z=z.beforeTenantSegments??[],ge=z.afterTenantSegments??[],te=Be(O),le=Z.length+1+ge.length;if(te.length<le)return null;for(let Ce=0;Ce<Z.length;Ce++)if(te[Ce]!==Z[Ce])return null;let fe=Z.length,ye=te[fe];if(!ye)return null;for(let Ce=0;Ce<ge.length;Ce++)if(te[fe+1+Ce]!==ge[Ce])return null;let ke=te.slice(fe+1+ge.length);return{id:decodeURIComponent(ye),restSegments:ke,restPath:ke.length>0?`/${ke.join("/")}`:"/"}}function Ct(O,_="/",z){let Z=Ae(z),ge=Z.beforeTenantSegments??[],te=Z.afterTenantSegments??[],le=Be(_),fe=[...ge,encodeURIComponent(O),...te,...le];return fe.length>0?`/${fe.join("/")}`:"/"}function kt(O){return{"~standard":{version:1,vendor:O,validate:(_)=>{if(typeof _!=="object"||_===null)return{issues:[{message:"Expected an object"}]};let z=_,Z=[],ge={...z},te=["iss","sub"];for(let ye of te)if(ye in z){if(typeof z[ye]!=="string")Z.push({message:`${ye} must be a string`,path:[ye]})}else Z.push({message:`${ye} is required`,path:[ye]});if("aud"in z&&z.aud!==void 0){let ye=z.aud;if(typeof ye!=="string"&&!Array.isArray(ye))Z.push({message:"aud must be a string or array of strings",path:["aud"]});else if(Array.isArray(ye)&&!ye.every((ke)=>typeof ke==="string"))Z.push({message:"aud array must contain only strings",path:["aud"]})}let le=["jti","scope"];for(let ye of le)if(ye in z&&z[ye]!==void 0){if(typeof z[ye]!=="string")Z.push({message:`${ye} must be a string`,path:[ye]})}let fe=["exp","iat"];for(let ye of fe)if(ye in z){if(typeof z[ye]!=="number")Z.push({message:`${ye} must be a number`,path:[ye]})}else Z.push({message:`${ye} is required`,path:[ye]});if(Z.length>0)return{issues:Z};return{value:ge}}}}}function Rt(O){return{"~standard":{version:1,vendor:O,validate:(_)=>{if(typeof _!=="object"||_===null)return{issues:[{message:"Expected an object"}]};let z=_,Z=[],ge={};if("access_token"in z)if(typeof z.access_token==="string")ge.access_token=z.access_token;else Z.push({message:"access_token must be a string",path:["access_token"]});else Z.push({message:"access_token is required",path:["access_token"]});if("token_type"in z)if(typeof z.token_type==="string")ge.token_type=z.token_type;else Z.push({message:"token_type must be a string",path:["token_type"]});else Z.push({message:"token_type is required",path:["token_type"]});if("scope"in z)if(typeof z.scope==="string"||z.scope===void 0)ge.scope=z.scope;else Z.push({message:"scope must be a string",path:["scope"]});if("refresh_token"in z)if(typeof z.refresh_token==="string"||z.refresh_token===void 0)ge.refresh_token=z.refresh_token;else Z.push({message:"refresh_token must be a string",path:["refresh_token"]});if("expires"in z)if(typeof z.expires==="string"||z.expires===void 0)ge.expires=z.expires;else Z.push({message:"expires must be a string",path:["expires"]});if("expires_in"in z)if(typeof z.expires_in==="number"||z.expires_in===void 0)ge.expires_in=z.expires_in;else Z.push({message:"expires_in must be a number",path:["expires_in"]});if(Z.length>0)return{issues:Z};return{value:ge}}}}}function Tt(O){let _=new Uint8Array(O);return crypto.getRandomValues(_),_}function At(O){let _="",z=Tt(O);for(let Z=0;Z<O;Z++){let ge=z[Z]%32;_+="0123456789ABCDEFGHJKMNPQRSTVWXYZ".charAt(ge)}return _}function ht(O,_){let z="";for(let Z=_;Z>0;Z--){let ge=O%32;z="0123456789ABCDEFGHJKMNPQRSTVWXYZ".charAt(ge)+z,O=Math.floor(O/32)}return z}function bt(O){let _=Date.now(),z=ht(_,10),Z=At(16);return`${O??""}${z}${Z}`}export{V as AssignmentPolicyError,U as CANONICAL_RISK_LEVELS,he as ConfigSourceError,u as DEFAULT_RISK_LEVEL,Le as DEFAULT_SECRET_MIME_TYPES,Ge as DEFAULT_TENANT_API_NAMESPACE,Ve as DEFAULT_TENANT_UI_NAMESPACE,ne as ECID_SCHEME,k as EcidFormatError,e as ION_AUTHZ_GROUP_SCHEMA,Me as ION_AUTHZ_OAA_SYNC,ve as ION_CAPABILITIEZ_READ,Ke as ION_CIAM_MAGIC_LINK_CREATE,Qe as ION_ENDPOINT_PERMISSIONS,_e as ION_IAM_ACCESS_REQUESTS_WRITE,Oe as ION_IAM_CUSTOMERS_WRITE,xe as ION_IAM_GROUPS_WRITE,Ie as ION_IAM_READ,we as ION_IAM_USERS_WRITE,Pe as ION_IAM_WORKLOADS_WRITE,g as ION_SCIM_CUSTOMER_SCHEMA,s as ION_SCIM_USER_EXTENSION_URN,f as ION_SCIM_WORKLOAD_SCHEMA,Ze as ION_SDK_PERMISSIONS,Ne as ION_TENANT_MANAGE,G as IoniteError,S as KNOWN_BASE_CUSTOMER_KEYS,h as KNOWN_BASE_USER_KEYS,o as KNOWN_ENTITLEMENT_KEYS,b as KNOWN_WORKLOAD_KEYS,d as PLATFORM_ASSIGNABLE_SUBJECT_TYPES,ze as SecretContentTypeMismatchError,m as StoreConflictError,n as accessRefId,c as accessRootId,w as assertEcid,M as assertRequiredSubjectType,W as assertValidSubjectTypeScoping,Ct as buildTenantPath,I as catalogEntityStore,P as claimsToUser,X as configTrustedClientGrants,r as customAttributes,K as customerResourceSchema,at as debugLogger,ue as decodeUser,p as deepEqualPlain,it as defaultLogger,lt as defaultSecretContentType,F as defineCatalog,De as defineSecretType,j as deprecateRetiredCodeCatalogRows,re as formatEcid,Te as formatLogLine,bt as generateULID,A as getCodeCatalogEntity,me as groupResourceSchema,l as idTokenClaimsSchema,pt as infoLogger,H as isCodeCatalog,B as isConfigLocator,Ye as isConfigSourceError,J as isEcid,T as isStoreConflictError,kt as jwtAssertionClaimsSchema,R as list,i as listGenerator,St as matchTenantPath,Q as matchesListFilter,v as materializeCodeCatalogEntity,y as mergeCodeCatalogEntity,oe as mergeConfig,t as must,Ae as normalizeTenantPathNamespace,ft as normalizeTenantRoutingStrategy,N as oidcCallbackSchema,se as parseEcid,ie as parseJsonc,rt as parseKmsPoolControlDocument,ot as parseKmsPoolDocument,mt as prettyLogger,dt as readyCatalogEntry,gt as remoteConfigSecretType,et as serializeConfig,Ue as silentLogger,ae as stableConfigHash,Y as stripJsonComments,de as tmIntegrationState,ee as toCodeCatalog,L as tokenResponseSchema,C as trimTrailingSlash,E as trustedClientPermissionsForPrincipal,x as unionCatalogRead,pe as userSchema,D as validationFailureResponse,Je as version,ce as waitOn,ct as warnLogger,a as withValidate,q as workloadResourceSchema,Rt as workloadTokenResponseSchema};
|
package/dist/server.d.ts
CHANGED
|
@@ -1364,11 +1364,13 @@ type AccessRequestCreate = {
|
|
|
1364
1364
|
subjectType: SubjectType;
|
|
1365
1365
|
targetType: EntitlementType;
|
|
1366
1366
|
target: string;
|
|
1367
|
+
operation: "grant" | "revoke";
|
|
1367
1368
|
justification?: string;
|
|
1368
1369
|
};
|
|
1369
1370
|
type AccessRequestResult = {
|
|
1370
1371
|
id: string;
|
|
1371
1372
|
status: "pending" | "approved" | "denied";
|
|
1373
|
+
operation: "grant" | "revoke";
|
|
1372
1374
|
trackingUrl: string;
|
|
1373
1375
|
};
|
|
1374
1376
|
/** SCIM resource types the delta patch adapter addresses. */
|
|
@@ -2108,13 +2110,17 @@ type IamPrincipalKind = {
|
|
|
2108
2110
|
delta?: IamDeltaMode;
|
|
2109
2111
|
};
|
|
2110
2112
|
type IAMAccessRequestsConfig = {
|
|
2111
|
-
create: (request: AccessRequestCreate) => Promise<
|
|
2113
|
+
create: (request: AccessRequestCreate) => Promise<{
|
|
2114
|
+
request: AccessRequestResult;
|
|
2115
|
+
created: boolean;
|
|
2116
|
+
}>;
|
|
2112
2117
|
};
|
|
2113
2118
|
type AccessRequestSubmit = {
|
|
2114
2119
|
subject: AccessChange["subject"];
|
|
2115
2120
|
subjectType: SubjectType;
|
|
2116
2121
|
targetType: EntitlementType;
|
|
2117
2122
|
target: AccessChange["target"];
|
|
2123
|
+
operation: "grant" | "revoke";
|
|
2118
2124
|
justification?: string;
|
|
2119
2125
|
};
|
|
2120
2126
|
type IAMEntitlementRequestUrlContext = {
|
|
@@ -5190,18 +5196,21 @@ type Authz = {
|
|
|
5190
5196
|
*/
|
|
5191
5197
|
grant(change: AccessChange): Promise<AccessChange>;
|
|
5192
5198
|
/**
|
|
5193
|
-
* Submit
|
|
5194
|
-
* policy is `'iam-request'`.
|
|
5199
|
+
* Submit one grant or revoke request on a principal's behalf. Allowed only when that kind's
|
|
5200
|
+
* assignment policy is `'iam-request'`. One operation maps to one approval decision, status,
|
|
5201
|
+
* and tracking URL. Authenticated with the module-wide `deltaAudience` workload client.
|
|
5195
5202
|
*/
|
|
5196
5203
|
requestAccess(change: {
|
|
5197
5204
|
subject: AccessChange["subject"];
|
|
5198
5205
|
subjectType: SubjectType;
|
|
5199
5206
|
targetType: EntitlementType;
|
|
5200
5207
|
target: AccessChange["target"];
|
|
5208
|
+
operation: "grant" | "revoke";
|
|
5201
5209
|
justification?: string;
|
|
5202
5210
|
}): Promise<{
|
|
5203
5211
|
id: string;
|
|
5204
5212
|
status: "pending" | "approved" | "denied";
|
|
5213
|
+
operation: "grant" | "revoke";
|
|
5205
5214
|
trackingUrl: string;
|
|
5206
5215
|
}>;
|
|
5207
5216
|
/**
|
package/dist/server.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{E,o,h,S,b,r,i,U,u,e,d,A,I,v,j,x,n,c,_,O,z,te,w,N,L,l,a,t,D,C,p,P,m,T,Z,le,s,f,g,q,K}from"./shared/core-j5xhxcmq.js";var Er="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.",Yn=["user","customer","workload"],Mr={user:async(y,k)=>k.sso?.getUser(y),customer:async(y,k)=>k.ciam?.getCustomer(y),workload:async(y,k)=>{let R=await k.workload?.getWorkloadIdentity?.(y);if(!R)return;let W=R.clientId??R.workloadId??R.claims.sub;return W?{...R,id:W}:void 0}};function jr(y){if(y==="any")return Yn;let k=Array.isArray(y)?y:[y];return Yn.filter((R)=>k.includes(R))}function _r(y){let k=y.headers.get("cookie");if(!k)return[];return k.split(";").map((R)=>R.slice(0,R.indexOf("=")===-1?R.length:R.indexOf("=")).trim()).filter(Boolean)}function Or(y,k){let R=y.headers.get("authorization")?.toLowerCase().startsWith("bearer ")??!1,W=_r(y),V=new Set;for(let H of W){if(H.startsWith("ion.sso"))V.add("user");if(H.startsWith("ion.ciam"))V.add("customer")}let G=W.length>0&&!V.has("user")&&!V.has("customer");return k.filter((H)=>{if(H==="workload")return R;if(W.length===0)return!1;return V.has(H)||G})}function Be(y){return typeof y==="string"?y:y.id}function Xn(y){let{subject:k,subjectType:R}=y,W;if(R==="user")W=k.sso?.scope;else if(R==="customer")W=k.ciam?.scope;else if(R==="workload")W=k.scope;return new Set((W??"").split(/\s+/).filter(Boolean))}function fn(y,k,R){let W=Xn(y),V=k.filter((H)=>W.has(H));return{allow:R==="any"?V.length>0:k.length>0&&V.length===k.length,metadata:{reason:"scope",wantedScopes:k,matchedScopes:V}}}function Mt(y,k){return(R)=>{if(y.length===0)return;let W=Xn(R),V=y.filter((H)=>W.has(H));return(k==="any"?V.length>0:V.length===y.length)?V:void 0}}function Xt(y,k,R){return(W)=>{if(k.length===0||W.subjectType!=="workload")return;let V=E(y.config?.authz,W.subject);if(!V)return;let G=k.filter((Y)=>V.has(Y));return(R==="any"?G.length>0:G.length===k.length)?G:void 0}}function Dr(y,k){if(y.subjectType==="workload"){let R=y.subject.scopesAsEntitlements;if(typeof R==="boolean")return R}return k.config?.authz?.scopesAsEntitlements===!0}function mn(y,k,R,W,V){return{allow:R==="ok",subject:k?.subject,subjectType:k?.subjectType,reason:R,decision:W,response(){if(R==="ok")return new Response(null,{status:204});if(R==="unauthenticated")return y.log.warn("authz.denied",{reason:R,...V()}),Response.json({error:"Unauthorized"},{status:401});if(R==="not_configured")return y.log.warn("authz.denied",{reason:R,subject:k?.subject?.id,subjectType:k?.subjectType,...V()}),Response.json({error:"not_configured"},{status:503});return y.log.warn("authz.denied",{reason:R,subject:k?.subject?.id,subjectType:k?.subjectType,...V()}),Response.json({error:"Forbidden"},{status:403})}}}function Lr(y,k,R){return new Promise((W)=>{let V=[],G=y.length,H=!1,Y=()=>{if(G-=1,G===0&&!H)H=!0,W({outcomes:V})};for(let Q of y)k(Q).then((X)=>{if(V.push({principal:Q,decision:X}),!H&&X.allow){H=!0,W({matched:{principal:Q,decision:X},outcomes:V});return}Y()},(X)=>{R?.(Q,X),V.push({principal:Q,decision:{allow:!1,metadata:{reason:"error"}}}),Y()})})}async function pt(y,k,R,W,V,G,H){t(k,Er);let Y=Or(y,jr(R)),X=(await Promise.all(Y.map(async(ye)=>{let _e=await Mr[ye](y,k);return _e?.id?{subject:_e,subjectType:ye,subjectId:_e.id}:void 0}))).filter((ye)=>ye!==void 0);if(X.length===0)return mn(k,void 0,"unauthenticated",void 0,V);let Pe=async(ye)=>{let _e=k.authz.accessIndex;if(!_e?.isSubjectDisabled)return!1;return _e.isSubjectDisabled(ye.subjectId,ye.subjectType)},xe=async(ye)=>{if(H){let _e=H(ye);if(_e&&_e.length>0){if(await Pe(ye))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"trusted-client",matchedPermissions:_e}}}}if(G&&Dr(ye,k)){let _e=G(ye);if(_e&&_e.length>0){if(await Pe(ye))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"scope",matchedScopes:_e}}}}return W(ye)},{matched:je,outcomes:De}=await Lr(X,xe,(ye,_e)=>{k.log.warn("authz.check_error",{"ion.operation":"authz.check","ion.outcome":"error",subject:ye.subjectId,subjectType:ye.subjectType,error:_e instanceof Error?_e.message:String(_e),...V()})});if(je){if(je.decision.metadata?.reason==="scope")k.log.info("authz.scope_honor",{"ion.operation":"authz.scope_honor","ion.outcome":"allow",subject:je.principal.subjectId,subjectType:je.principal.subjectType,matchedScopes:je.decision.metadata.matchedScopes,...V()});return mn(k,je.principal,"ok",je.decision,V)}let We=De.length>0&&De.every((ye)=>{let _e=ye.decision.metadata?.reason;return _e==="access_index_not_configured"||_e==="error"}),ke=De[0],Le=We?"not_configured":"forbidden";return mn(k,ke?.principal,Le,ke?.decision,V)}async function Nr(y,k,R,W,V,G="any"){return pt(y,k,G,(H)=>k.authz.has(H.subjectId,R,W,V,H.subjectType),()=>({targetType:R,target:Be(W),resource:V?Be(V):void 0}),V?void 0:Mt([Be(W)],"any"),R==="permission"&&!V?Xt(k,[Be(W)],"any"):void 0)}async function Wr(y,k,R,W,V="any"){return pt(y,k,V,(G)=>k.authz.hasPermission(G.subjectId,R,W,G.subjectType),()=>({targetType:"permission",target:Be(R),resource:W?Be(W):void 0}),W?void 0:Mt([Be(R)],"any"),W?void 0:Xt(k,[Be(R)],"any"))}async function Vr(y,k,R,W,V="any"){return pt(y,k,V,(G)=>k.authz.hasRole(G.subjectId,R,W,G.subjectType),()=>({targetType:"role",target:Be(R),resource:W?Be(W):void 0}),W?void 0:Mt([Be(R)],"any"))}async function qr(y,k,R,W,V="any"){return pt(y,k,V,(G)=>k.authz.hasGroup(G.subjectId,R,W,G.subjectType),()=>({targetType:"group",target:Be(R),resource:W?Be(W):void 0}),W?void 0:Mt([Be(R)],"any"))}async function $r(y,k,R,W="any"){let V=R.filter((H)=>!H.resource).map((H)=>Be(H.target)),G=R.filter((H)=>!H.resource&&H.targetType==="permission").map((H)=>Be(H.target));return pt(y,k,W,(H)=>k.authz.hasAny(H.subjectId,R,H.subjectType),()=>({targets:R.map((H)=>`${H.targetType}:${Be(H.target)}`)}),V.length>0?Mt(V,"any"):void 0,G.length>0?Xt(k,G,"any"):void 0)}async function zr(y,k,R,W="any"){let V=R.length>0&&R.every((Y)=>!Y.resource),G=R.length>0&&R.every((Y)=>!Y.resource&&Y.targetType==="permission"),H=R.map((Y)=>Be(Y.target));return pt(y,k,W,(Y)=>k.authz.hasAll(Y.subjectId,R,Y.subjectType),()=>({targets:R.map((Y)=>`${Y.targetType}:${Be(Y.target)}`)}),V?Mt(H,"all"):void 0,G?Xt(k,H,"all"):void 0)}async function Br(y,k,R,W="any"){return pt(y,k,W,(V)=>Promise.resolve(fn(V,[R],"any")),()=>({scope:R}))}async function Gr(y,k,R,W="any"){return pt(y,k,W,(V)=>Promise.resolve(fn(V,R,"any")),()=>({scopes:R}))}async function Kr(y,k,R,W="any"){return pt(y,k,W,(V)=>Promise.resolve(fn(V,R,"all")),()=>({scopes:R}))}function Fe(y){return typeof y==="string"&&y.length>0?y:void 0}function Zn(y){let k=Fe(y.email);return{sub:String(y.sub??""),email:k,name:Fe(y.name),userName:Fe(y.preferred_username)??k,avatar:Fe(y.picture)}}var Qn={oidc:{flow:"id_token",scope:"openid profile email",branding:{displayName:"Single sign-on"},mapClaims:Zn},google:{flow:"id_token",authorizationUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",jwksUri:"https://www.googleapis.com/oauth2/v3/certs",scope:"openid email profile",branding:{displayName:"Google",iconUrl:"https://www.gstatic.com/firebasejs/ui/2.0.0/images/auth/google.svg",colors:{light:"#ffffff",dark:"#131314",secondary:"#4285F4"},url:"https://accounts.google.com"},mapClaims:Zn},microsoft:{flow:"id_token",authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",jwksUri:"https://login.microsoftonline.com/common/discovery/v2.0/keys",scope:"openid email profile",branding:{displayName:"Microsoft",colors:{light:"#ffffff",dark:"#2f2f2f",secondary:"#0067b8"},url:"https://login.microsoftonline.com"},mapClaims:(y)=>{let k=Fe(y.email)??Fe(y.preferred_username);return{sub:String(y.sub??y.oid??""),email:k,name:Fe(y.name),userName:Fe(y.preferred_username)??k,avatar:Fe(y.picture)}}},apple:{flow:"id_token",authorizationUrl:"https://appleid.apple.com/auth/authorize",tokenUrl:"https://appleid.apple.com/auth/token",jwksUri:"https://appleid.apple.com/auth/keys",scope:"openid email name",extraAuthParams:{response_mode:"form_post"},branding:{displayName:"Apple",colors:{light:"#000000",dark:"#ffffff"},url:"https://appleid.apple.com"},mapClaims:(y)=>{let k=Fe(y.email);return{sub:String(y.sub??""),email:k,name:Fe(y.name),userName:k}}},github:{flow:"userinfo",authorizationUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",userInfoUrl:"https://api.github.com/user",scope:"read:user user:email",branding:{displayName:"GitHub",colors:{light:"#24292f",dark:"#ffffff"},url:"https://github.com"},mapClaims:(y)=>({sub:String(y.id??y.node_id??""),email:Fe(y.email),name:Fe(y.name)??Fe(y.login),userName:Fe(y.login),avatar:Fe(y.avatar_url)})}};function gn(y){if(y==="magic-link")return;return Qn[y]}function Zt(y,k){if(k.type==="magic-link")return;let R=gn(k.type);if(!R)return;return{name:y,type:k.type,flow:R.flow,authorizationUrl:k.authorizationUrl??R.authorizationUrl,tokenUrl:k.tokenUrl??R.tokenUrl,jwksUri:k.jwksUri??R.jwksUri,userInfoUrl:k.userInfoUrl??R.userInfoUrl,scope:k.scope??R.scope,clientId:k.clientId,clientSecret:k.clientSecret,extraAuthParams:R.extraAuthParams,branding:{...R.branding,...k.branding},mapClaims:R.mapClaims,config:k}}function yn(y){return{...gn(y.type)?.branding??{displayName:y.type},...y.branding}}function hn(y){if(!y)return[];return Object.entries(y).filter(([,k])=>k.enabled!==!1).map(([k,R],W)=>({name:k,config:R,index:W})).sort((k,R)=>{let W=k.config.order??Number.MAX_SAFE_INTEGER,V=R.config.order??Number.MAX_SAFE_INTEGER;if(W!==V)return W-V;return k.index-R.index}).map(({name:k,config:R})=>({name:k,config:R}))}var tr=600000,kn=256,et=new Map;function Jr(y){if(typeof y?.ttlMs==="number"&&Number.isFinite(y.ttlMs))tr=Math.min(Math.max(y.ttlMs,60000),86400000);if(typeof y?.maxEntries==="number"&&Number.isFinite(y.maxEntries)){kn=Math.max(1,Math.floor(y.maxEntries));while(et.size>kn){let k=et.keys().next().value;if(k===void 0)break;et.delete(k)}}}function er(y,k){et.delete(y),et.set(y,k);while(et.size>kn){let R=et.keys().next().value;if(R===void 0)break;et.delete(R)}}var Nt=new Map,wn=()=>Date.now();function Hr(y){wn=y??(()=>Date.now())}var bn={};function Fr(y){bn=y??{}}function Yr(y){if(!y)return;if(/\bno-store\b/i.test(y))return 60000;let k=/max-age\s*=\s*(\d+)/i.exec(y);if(!k)return;let R=Number(k[1]);return Number.isFinite(R)?R*1000:void 0}function Xr(y){let R=Yr(y)??tr;return Math.min(Math.max(R,60000),86400000)}async function Cn(y,k=3,R=1000,W=30000,V){let G=Error("Placeholder Error");for(let H=0;H<=k;H++)try{return await y()}catch(Y){if(G=Y instanceof Error?Y:Error(String(Y)),Y instanceof Error&&Y.message.includes("400"))throw Y;if(H===k)throw G;let Q=Math.min(R*2**H,W),X=Math.random()*0.1*Q;await new Promise((Pe)=>setTimeout(Pe,Q+X)),V?.warn(`Retry attempt ${H+1} after ${Q+X}ms delay`)}throw G}async function Wt(y,k,R){let W=et.get(y);if(!R?.forceRefresh&&W&&W.expiresAt>wn())return er(y,W),W.jwks;let V=Nt.get(y);if(V)return V;let G=(async()=>{try{return await Cn(async()=>{let H=await fetch(y);if(!H.ok)throw Error("Failed to fetch JWKS");let Y=await H.json(),Q=Xr(H.headers.get("cache-control"));return er(y,{jwks:Y,expiresAt:wn()+Q,importedKeys:new Map}),Y},bn.maxRetries,bn.baseDelayMs,void 0,k)}catch(H){let Y=et.get(y);if(Y)return k?.warn("JWKS refresh failed; serving last-known-good keys",{"ion.operation":"jwks.refresh","ion.outcome":"degraded"}),Y.jwks;throw H}finally{Nt.delete(y)}})();return Nt.set(y,G),G}function Zr(y){if(y){et.delete(y),Nt.delete(y);return}et.clear(),Nt.clear()}async function Qr(y,k,R){return(await nr(y,k,R)).jwk}async function nr(y,k,R){if(!k?.trim())throw Error("JWT header missing kid");await Wt(y,R);let W=et.get(y),V=W?.jwks.keys.find((G)=>G.kid===k);if(!V)await Wt(y,R,{forceRefresh:!0}),W=et.get(y),V=W?.jwks.keys.find((G)=>G.kid===k);if(!W||!V)throw Error("Public key not found");return{jwk:V,entry:W}}async function Rn(y,k,R,W,V){let{jwk:G,entry:H}=await nr(y,k,V),Y=`${k}\x00${R}`,Q=H.importedKeys.get(Y);if(Q)return Q;let X=W(G);return X.catch(()=>{if(H.importedKeys.get(Y)===X)H.importedKeys.delete(Y)}),H.importedKeys.set(Y,X),X}async function es(y,k){let R=y.keys.find((W)=>W.kid===k);if(!R)throw Error("Public key not found");return rr(R)}function rr(y){return crypto.subtle.importKey("jwk",{kty:y.kty,n:y.n,e:y.e},{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},!1,["verify"])}async function ts(y,k,R){return Rn(y,k,"rs256",rr,R)}var Sn={RS256:{kty:"RSA",importParams:{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},verifyParams:{name:"RSASSA-PKCS1-v1_5"}},ES256:{kty:"EC",crv:"P-256",importParams:{name:"ECDSA",namedCurve:"P-256"},verifyParams:{name:"ECDSA",hash:"SHA-256"}}};async function vn(y,k,R,W){if(typeof R!=="string"||!(R in Sn))throw Error(`Unsupported JWT alg "${String(R)}" (allowed: ${Object.keys(Sn).join(", ")})`);let V=Sn[R];return{key:await Rn(y,k,`oidc:${R}`,(H)=>{if(H.kty!==V.kty)throw Error(`JWK type "${H.kty}" does not match token alg "${R}"`);if(V.kty==="EC"){let Y=H;if(Y.crv!==V.crv)throw Error(`JWK curve "${String(Y.crv)}" does not match token alg "${R}"`);return crypto.subtle.importKey("jwk",{kty:"EC",crv:Y.crv,x:Y.x,y:Y.y},V.importParams,!1,["verify"])}return crypto.subtle.importKey("jwk",{kty:H.kty,n:H.n,e:H.e},V.importParams,!1,["verify"])},W),algorithm:V.verifyParams}}function st(y=32){let k=new Uint8Array(y);return crypto.getRandomValues(k),Array.from(k,(R)=>R.toString(16).padStart(2,"0")).join("").substring(0,y)}function Qt(y){let k="";return y.forEach((R)=>{k+=String.fromCharCode(R)}),btoa(k).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function or(y){let k=y.replace(/-/g,"+").replace(/_/g,"/"),R=k.padEnd(k.length+(4-k.length%4)%4,"="),W=atob(R),V=new Uint8Array(W.length);for(let G=0;G<W.length;G++)V[G]=W.charCodeAt(G);return V}function sr(y){let k=new TextDecoder().decode(or(y));return JSON.parse(k)}async function $t(y){let k=new TextEncoder().encode(y),R=await crypto.subtle.digest("SHA-256",k);return Qt(new Uint8Array(R))}function An(y){let k=new URL(y.authorizationUrl);if(k.searchParams.set("client_id",y.clientId),k.searchParams.set("redirect_uri",y.redirectUri),k.searchParams.set("response_type","code"),k.searchParams.set("scope",y.scope),k.searchParams.set("state",y.state),y.codeChallenge)k.searchParams.set("code_challenge",y.codeChallenge),k.searchParams.set("code_challenge_method","S256");if(y.nonce)k.searchParams.set("nonce",y.nonce);for(let[R,W]of Object.entries(y.extraParams??{}))k.searchParams.set(R,W);return k.toString()}async function Tn(y){let k=new URLSearchParams;if(k.append("grant_type","authorization_code"),k.append("code",y.code),k.append("redirect_uri",y.redirectUri),k.append("client_id",y.clientId),y.clientSecret)k.append("client_secret",y.clientSecret);if(y.codeVerifier)k.append("code_verifier",y.codeVerifier);let R=await fetch(y.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:k.toString()}),W=await R.json();if(!R.ok){let V=W,G=V.error==="invalid_client"&&!y.clientSecret;throw y.log?.error(G?"OIDC authorization-code exchange failed: no client_secret was configured; the provider may require a confidential client":"OIDC authorization-code exchange failed",{"ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":R.status,oidc_error:V.error,...G?{client_auth:"none"}:{}}),Error(`Token exchange failed: ${V.error||R.statusText} - ${V.error_description||""}`.trim())}if(typeof W.access_token!=="string")throw Error("Token exchange response missing access_token");return W}var ar=60;function qt(y){return y.trim().replace(/\/$/,"")}function cr(y){let{claims:k,audience:R}=y,W=qt(y.issuer),V=y.nowSec??Math.floor(Date.now()/1000),G=y.clockSkewSec??ar,H=k.iss;if(typeof H!=="string"||qt(H)!==W)throw Error("ID token issuer mismatch");let Y=k.aud,Q=Array.isArray(Y)?Y.includes(R):typeof Y==="string"&&Y===R,X=typeof k.azp==="string"&&k.azp===R;if(!Q&&!X)throw Error("ID token audience mismatch");if(typeof k.exp!=="number")throw Error("ID token missing exp");if(k.exp<V-G)throw Error("ID token expired");if(y.expectedNonce!==void 0){if(k.nonce!==y.expectedNonce)throw Error("ID token nonce mismatch")}}async function ur(y,k,R){let W=y.split(".");if(W.length!==3)throw Error("Invalid JWT");let V=sr(W[0]),G=sr(W[1]),H=or(W[2]),{key:Y,algorithm:Q}=await vn(k,V.kid,V.alg,R),X=new TextEncoder().encode(`${W[0]}.${W[1]}`);if(!await crypto.subtle.verify(Q,Y,H,X))throw Error("Invalid JWT signature");return{header:V,payload:G}}async function kt(y){let{payload:k}=await ur(y.idToken,y.jwksUri,y.log);return cr({claims:k,issuer:y.issuer,audience:y.audience,clockSkewSec:y.clockSkewSec,expectedNonce:y.expectedNonce}),k}var ns="http://schemas.openid.net/event/backchannel-logout";async function Pn(y){let{payload:k}=await ur(y.logoutToken,y.jwksUri,y.log),R=qt(y.issuer),W=k.iss;if(typeof W!=="string"||qt(W)!==R)throw Error("Logout token issuer mismatch");let V=k.aud,G=Array.isArray(V)?V.includes(y.audience):typeof V==="string"&&V===y.audience,H=typeof k.azp==="string"&&k.azp===y.audience;if(!G&&!H)throw Error("Logout token audience mismatch");if(k.nonce!=null)throw Error("Logout token must not contain a nonce");let Y=k.events;if(!(typeof Y==="object"&&Y!==null&&!Array.isArray(Y)&&Object.hasOwn(Y,ns)))throw Error("Logout token missing back-channel logout event");let X=typeof k.sid==="string"&&k.sid.length>0,Pe=typeof k.sub==="string"&&k.sub.length>0;if(!X&&!Pe)throw Error("Logout token missing sid and sub");if(typeof k.exp==="number"){let xe=Math.floor(Date.now()/1000),je=y.clockSkewSec??ar;if(k.exp<xe-je)throw Error("Logout token expired")}return k}var rs=3600000,ss=60000,is=86400000,os=256,mt=new Map,Vt=new Map;function ir(y,k){mt.delete(y),mt.set(y,k);while(mt.size>os){let R=mt.keys().next().value;if(R===void 0)break;mt.delete(R)}}var In=()=>Date.now();function as(y){In=y??(()=>Date.now())}function cs(y){if(y){mt.delete(y),Vt.delete(y);return}mt.clear(),Vt.clear()}function us(y){let k=y?/max-age\s*=\s*(\d+)/i.exec(y):null,R=k?Number(k[1]):Number.NaN,W=Number.isFinite(R)?R*1000:rs;return Math.min(Math.max(W,ss),is)}async function xn(y){let k=mt.get(y);if(k&&k.expiresAt>In())return ir(y,k),k.endpoints;let R=Vt.get(y);if(R)return R;let W=(async()=>{try{let V=y.replace(/\/$/,""),G=await fetch(`${V}/.well-known/openid-configuration`,{headers:{Accept:"application/json"}});if(!G.ok)throw Error(`OIDC discovery failed for ${y} with status ${G.status}`);let H=await G.json(),Y={authorizationUrl:typeof H.authorization_endpoint==="string"?H.authorization_endpoint:void 0,tokenUrl:typeof H.token_endpoint==="string"?H.token_endpoint:void 0,jwksUri:typeof H.jwks_uri==="string"?H.jwks_uri:void 0,userInfoUrl:typeof H.userinfo_endpoint==="string"?H.userinfo_endpoint:void 0};return ir(y,{endpoints:Y,expiresAt:In()+us(G.headers.get("cache-control"))}),Y}catch(V){let G=mt.get(y);if(G)return G.endpoints;throw V}finally{Vt.delete(y)}})();return Vt.set(y,W),W}async function Un(y,k){let R=await fetch(y,{headers:{Authorization:`Bearer ${k}`,Accept:"application/json","User-Agent":"ionite-ciam"}});if(!R.ok)throw Error(`UserInfo request failed with status ${R.status}`);return await R.json()}function ds(y){let k=y.replace(/-----BEGIN [^-]+-----/g,"").replace(/-----END [^-]+-----/g,"").replace(/\s+/g,""),R=atob(k),W=new Uint8Array(R.length);for(let V=0;V<R.length;V++)W[V]=R.charCodeAt(V);return W}async function En(y){let k=Math.floor(Date.now()/1000),R={alg:"ES256",kid:y.keyId,typ:"JWT"},W={iss:y.teamId,iat:k,exp:k+(y.expiresInSeconds??3600),aud:"https://appleid.apple.com",sub:y.clientId},V=Qt(new TextEncoder().encode(JSON.stringify(R))),G=Qt(new TextEncoder().encode(JSON.stringify(W))),H=`${V}.${G}`,Y=await crypto.subtle.importKey("pkcs8",ds(y.privateKey),{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),Q=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},Y,new TextEncoder().encode(H));return`${H}.${Qt(new Uint8Array(Q))}`}function ls(y){for(let k=0;k<y.length;k++){let R=y.charCodeAt(k);if(R<=31||R===127)return!0}return!1}function ps(y,k){let R=null;try{R=new URL(y,k)}catch{R=null}let W="";try{W=new URL(k).origin}catch{W=""}return{candidate:y,url:R,requestOrigin:W}}function dr(y,k,R){let W=ps(y,R),V=!1;for(let G of k){let H=G(W);if(H==="deny")return!1;if(H==="allow")V=!0}return V}function lr(){return({candidate:y,url:k})=>{if(ls(y))return"deny";if(y.includes("\\"))return"deny";if(y.startsWith("//"))return"deny";if(!k)return"deny";if(k.protocol!=="http:"&&k.protocol!=="https:")return"deny";if(k.username||k.password)return"deny";return"abstain"}}function pr(){return({candidate:y})=>y.startsWith("/")&&!y.startsWith("//")&&!y.startsWith("/\\")?"allow":"abstain"}function mr(){return({url:y,requestOrigin:k})=>y&&k&&y.origin===k?"allow":"abstain"}function ms(...y){let k=new Set(y.map((R)=>{try{return new URL(R).origin}catch{return R}}));return({url:R})=>R&&k.has(R.origin)?"allow":"abstain"}function fs(...y){let k=y.map((R)=>R.toLowerCase());return({url:R})=>{if(!R)return"abstain";let W=R.hostname.toLowerCase();for(let V of k)if(V.startsWith(".")){if(W===V.slice(1)||W.endsWith(V))return"allow"}else if(W===V)return"allow";return"abstain"}}function Mn(){return[lr(),pr(),mr()]}function fr(y,k,R){if(!y)return!1;return dr(y,k,R)}function jn(y,k){if(!y)return k.fallback;return dr(y,k.rules,k.requestUrl)?y:k.fallback}var gs={rules:Mn(),fallback:"/"};function ys(y,k,R="redirect"){let W=new URL(y.url).searchParams.get(R)??void 0;return fr(W,k.rules,y.url)?{redirect:W}:void 0}function hs(y,k){let R=y.context;return jn(R?.redirect,{rules:k.rules,fallback:k.fallback,requestUrl:y.request.url})}function wt(y,k,R){if(y instanceof Response)return{response:y};if(typeof y==="string")return{location:jn(y,{rules:Mn(),fallback:k,requestUrl:R})};return{location:k}}function At(y,k){if(k.length===0)return y;let R=new Headers(y.headers);for(let W of k)R.append("Set-Cookie",W);return new Response(y.body,{status:y.status,statusText:y.statusText,headers:R})}var en="ciam",Ss="id_token",ks="access_token";function ws(y,k,R,W,V,G){if(!R&&!W)return;let H=new WeakMap,Y={...R,...W},Q={...Y,magicLinkTtl:Y.magicLinkTtl??3600,sessionTtl:Y.sessionTtl??86400,cookiesSecure:Y.cookiesSecure!==void 0?Y.cookiesSecure:!0,cookiesSameSite:Y.cookiesSameSite!==void 0?Y.cookiesSameSite:"Strict",cookiesPrefix:Y.cookiesPrefix??(Y.ciamId?`ion.ciam.${Y.ciamId}`:"ion.ciam"),cookiesPath:Y.cookiesPath??"/"};function X(){if(!Q.sessionStore)throw Error("Missing CIAM configuration field: sessionStore. CIAM sessionStore is required for server-side session tracking and first-party logout.");return Q.sessionStore}function Pe(){X()}let xe=y.callbackParams??a(N("ionite.ciam")),je=y.idTokenClaims??a(l("ionite.ciam")),De=y.tokenResponse??a(L("ionite.ciam"));function We(M=32){let B=new Uint8Array(M);return crypto.getRandomValues(B),Array.from(B,(J)=>J.toString(16).padStart(2,"0")).join("").substring(0,M)}function ke(M,B,J,F=Q.cookiesSameSite??"Strict"){if(!Q)throw Error("ionite CIAM Manager not initialized");if(M=`${Q.cookiesPrefix}.${M}`,typeof B!=="string")B=btoa(JSON.stringify(B));let ne;if(J instanceof Date)ne=`Expires=${J.toUTCString()}`;else if(typeof J==="number")ne=`Max-Age=${J}`;else throw Error("Invalid expires type",J);if(B.length>4000)throw Error(`Error setting cookie: ${M}. Cookie length is: ${B.length}`);return`${M}=${B}; ${ne}; Path=${Q.cookiesPath}; HttpOnly;${Q.cookiesSecure?" Secure;":""} SameSite=${F};`}function Le(M){if(!Q)throw Error("ionite CIAM Manager not initialized");return`${Q.cookiesPrefix}.${M}=; Max-Age=0; Path=${Q.cookiesPath}; HttpOnly;${Q.cookiesSecure?" Secure;":""} SameSite=${Q.cookiesSameSite};`}function ye(M,B,J=!1){if(!Q)throw Error("ionite CIAM Manager not initialized");let F=B.headers.get("cookie");if(!F)return null;let ne=`${Q.cookiesPrefix}.${M}`,pe=F.split(";").find((ie)=>ie.trim().startsWith(`${ne}=`));if(!pe)return null;let de=pe.indexOf("="),re=pe.substring(de+1).trim();if(!J)return re;try{let ie=atob(re);return JSON.parse(ie)}catch(ie){return k.error("[CIAM] Failed to parse cookie",{"ion.operation":"cookie.parse","ion.outcome":"failure",cookieName:ne},ie),null}}function _e(M){return`cstate_${M}`}async function Ne(M,B,J,F){let ne=await Q.afterLogin?.({...B,request:M,context:J}),pe=wt(ne,"/",M.url);if(pe.response)return At(pe.response,F.map(([,de])=>de));return new Response(B.ok?"Authentication successful, redirecting":"Authentication failed, redirecting",{status:302,headers:[["Location",pe.location],...F]})}function $e(M,B){return["Set-Cookie",ke("session",M,B)]}function tt(M){if(!M)return;if(M instanceof Date)return M;let B=new Date(M);return Number.isNaN(B.getTime())?void 0:B}async function Ge(M){let B=ye("session",M);if(!B)return;let J=await X().get(B);if(J&&Q.tenantId&&J.tenantId&&J.tenantId!==Q.tenantId)return;if(J?.authType!=="ciam")return;let F=tt(J.expiresAt);if(F&&Date.now()>F.getTime()){await X().delete(B);return}return J}async function Je(M){if(!Q)throw Error("ionite CIAM Manager not initialized");Pe();let B=H.get(M);if(B)return B;let J=nt(M);return H.set(M,J),J}async function nt(M){try{let B=await Ge(M);if(!B?.claims?.sub)return{status:"unauthenticated"};return{status:"authenticated",value:ot(B.claims)}}catch(B){return k.error("CIAM session resolution failed",{"ion.operation":"ciam.session","ion.outcome":"degraded"},B),{status:"degraded",error:B instanceof Error?B:void 0}}}async function Ut(M){let B=await Je(M);return B.status==="authenticated"?B.value:void 0}async function Rt(M){if(!Q)throw Error("ionite CIAM Manager not initialized");Pe();let B;try{B=await Ut(M)}catch{B=void 0}let J=await Q.beforeLogout?.({request:M,user:B});try{let ge=ye("session",M);if(ge)await X().delete(ge)}catch(ge){k.warn("Failed to delete CIAM session",{"ion.operation":"session.delete","ion.outcome":"degraded"},ge)}let F=[["Set-Cookie",Le("session")]],ne=await Q.afterLogout?.({request:M,context:J}),pe=wt(ne,"/",M.url);if(pe.response)return At(pe.response,F.map(([,ge])=>ge));let de=pe.location??"/",re=M.headers.get("accept");if(re?.includes("application/json")||re?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:de}),{status:200,headers:[["Content-Type","application/json"],...F]});return new Response("Logged out",{status:302,headers:[["Location",de],...F]})}function Et(M){return M.id||M.email||`ciam-${M.userName}`}function Dt(M,B,J){return{sub:Et(M),iss:en,aud:en,typ:Ss,exp:Math.floor(J.getTime()/1000),iat:Math.floor(Date.now()/1000),email:M.email,name:M.name,preferred_username:M.userName,picture:M.avatar,sid:B}}function Lt(M,B,J){return{sub:M,iss:en,aud:en,typ:ks,exp:Math.floor(J.getTime()/1000),iat:Math.floor(Date.now()/1000),sid:B,scope:"openid profile email"}}function ot(M){let B=M.exp?new Date(M.exp*1000):new Date;return{id:M.sub,userName:M.preferred_username??"",name:M.name??"",email:M.email??"",avatar:M.picture,userType:"customer",ciam:{profile:M,scope:"openid profile email",tokenType:"Bearer",expires:B}}}async function vt(M){if(!Q)throw Error("ionite CIAM Manager not initialized");if(!V)return new Response(JSON.stringify({error:"Workload authentication required"}),{status:401,headers:{"Content-Type":"application/json"}});if(!await V.getWorkloadIdentity(M))return new Response(JSON.stringify({error:"Unauthorized: Valid workload token required"}),{status:401,headers:{"Content-Type":"application/json"}});let J,F;try{if(!M.headers.get("content-type")?.includes("application/json"))return new Response(JSON.stringify({error:"Content-Type must be application/json"}),{status:400,headers:{"Content-Type":"application/json"}});let Oe=await M.text(),Ee=JSON.parse(Oe);F=typeof Ee?.redirect==="string"&&Ee.redirect.length>0?Ee.redirect:void 0;let ae={userName:Ee.userName,name:Ee.name,email:Ee.email,avatar:Ee.avatar},ee=await y.customer.validate(ae);if(ee.issues)return new Response(JSON.stringify({error:"Missing required fields: userName, name, email"}),{status:400,headers:{"Content-Type":"application/json"}});J=ee.value}catch(Ie){return new Response(JSON.stringify({error:"Invalid JSON in request body"}),{status:400,headers:{"Content-Type":"application/json"}})}let pe=new URL(M.url).searchParams.get("ttl"),de=pe?parseInt(pe,10):Q.magicLinkTtl??3600;if(Number.isNaN(de)||de<=0)return new Response(JSON.stringify({error:"Invalid TTL parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let re=We(32),ie=new Date(Date.now()+de*1000);if(!Q.magicLinkStore)return new Response(JSON.stringify({error:"Magic link store not configured"}),{status:501,headers:{"Content-Type":"application/json"}});try{await Q.magicLinkStore.create(re,J,ie)}catch(Ie){return k.error("Error creating magic link",{"ion.operation":"magic_link.create","ion.outcome":"failure"},Ie),new Response(JSON.stringify({error:"Failed to create magic link"}),{status:500,headers:{"Content-Type":"application/json"}})}let ge=new URL(M.url),be=Q.magicLinkLoginUrl||"/magic-link/login",me=new URL(be,ge.origin);if(me.searchParams.set("token",re),F)me.searchParams.set("redirect",F);return new Response(JSON.stringify({magicLink:me.toString(),expiresAt:ie.toISOString()}),{status:200,headers:{"Content-Type":"application/json"}})}async function gt(M){if(!Q)throw Error("ionite CIAM Manager not initialized");Pe();let J=new URL(M.url).searchParams.get("token");if(!J)return Ne(M,{ok:!1,error:Error("Missing magic-link token")},void 0,[]);if(!Q.magicLinkStore)return Ne(M,{ok:!1,error:Error("Magic link store not configured")},void 0,[]);let F=await Q.magicLinkStore.getAndDelete(J);if(!F)return Ne(M,{ok:!1,error:Error("Magic link invalid, expired, or already used")},void 0,[]);let ne=new Date(Date.now()+(Q.sessionTtl??86400)*1000),pe=We(32),de=Et(F.customer),re=Dt(F.customer,pe,ne),ie=Lt(de,pe,ne),ge=ot(re),be;try{let Ie={sid:pe,sub:de,authType:"ciam",tenantId:Q.tenantId,expiresAt:ne,claims:re,accessClaims:ie,createdAt:new Date};await X().create(Ie),be=Ie}catch(Ie){throw k.warn("Failed to create session",{"ion.operation":"session.create","ion.outcome":"degraded"},Ie),Ie}if(Q.customerStore)try{let Ie=ge.id;if(Ie){let Oe=new Date,Ee=await Q.customerStore.get(Ie);if(Ee||Q.enableJitUserProvisioning){let ae={...Ee??{},...ge,id:Ie,tenantId:Ee?.tenantId,createdAt:Ee?.createdAt??Oe,updatedAt:Oe,userType:Ee?.userType??"customer"};await Q.customerStore.upsert(ae)}}}catch(Ie){k.warn("Failed to store customer",{"ion.operation":"customer.store","ion.outcome":"degraded"},Ie)}let me=[$e(pe,ne)];return Ne(M,{ok:!0,user:ge,session:be},void 0,me)}function at(M,B=200,J=[]){return new Response(JSON.stringify(M),{status:B,headers:[["Content-Type","application/json"],...J]})}function It(M,B){try{return new URL(M).toString()}catch{let J=new URL(B).origin,F=Q.cookiesSecure?J.replace(/^http:\/\//,"https://"):J;return new URL(M,F).toString()}}function lt(){let M=Q.customerLoginUrl||"/auth/customer/login",B=M.includes("?")?"&":"?";return hn(Q.providers).map(({name:J,config:F})=>{let ne=yn(F);return{name:J,type:F.type,displayName:ne.displayName,loginUrl:`${M}${B}provider=${encodeURIComponent(J)}`,iconUrl:ne.iconUrl,colors:ne.colors,url:ne.url}})}async function Ze(M){if(!M)return{};let{authorizationUrl:B,tokenUrl:J,jwksUri:F,userInfoUrl:ne}=M,pe=M.config.authority;if(pe&&(!B||!J||M.flow==="id_token"&&!F))try{let re=await xn(pe);B=B??re.authorizationUrl,J=J??re.tokenUrl,F=F??re.jwksUri,ne=ne??re.userInfoUrl}catch(re){k.error("CIAM provider OIDC discovery failed",{"ion.operation":"ciam.oidc.discovery","ion.outcome":"failure"},re)}return{authorizationUrl:B,tokenUrl:J,jwksUri:F,userInfoUrl:ne}}async function yt(M){if(M.type==="apple"){let{teamId:B,keyId:J,privateKey:F,clientId:ne}=M.config;if(B&&J&&F&&ne)return En({teamId:B,keyId:J,privateKey:F,clientId:ne})}return M.clientSecret}async function ct(M){X();let J=new URL(M.url).searchParams.get("provider");if(!J)return at({error:"Missing required query parameter: provider"},400);let F=Q.providers?.[J];if(!F||F.enabled===!1||F.type==="magic-link")return at({error:`Unknown or disabled CIAM provider: ${J}`},404);let ne=Zt(J,F);if(!ne?.clientId)return at({error:`CIAM provider ${J} is not fully configured`},500);let pe=await Ze(ne);if(!pe.authorizationUrl)return at({error:`CIAM provider ${J} is missing an authorization endpoint`},500);let de=Q.customerCallbackUrl||"/auth/customer/callback",re=It(de,M.url),ie=st(),ge=st(64),be=st(),me=ne.flow==="id_token",Ie=me?await $t(ge):void 0,Oe=await Q.beforeLogin?.({request:M}),Ee=An({authorizationUrl:pe.authorizationUrl,clientId:ne.clientId,redirectUri:re,scope:ne.scope,state:ie,codeChallenge:Ie,nonce:be,extraParams:ne.extraAuthParams}),ae={provider:J,state:ie,codeVerifier:me?ge:void 0,nonce:be,redirectUri:re,...Oe===void 0?{}:{context:Oe}};return new Response("Redirecting to CIAM provider",{status:302,headers:[["Location",Ee],["Set-Cookie",ke(_e(ie),ae,Q.loginStateTtl??600,"Lax")]]})}async function rt(M){if(M.method==="POST"){if((M.headers.get("content-type")??"").includes("application/x-www-form-urlencoded")){let J=await M.text();return Object.fromEntries(new URLSearchParams(J).entries())}}return Object.fromEntries(new URL(M.url).searchParams.entries())}async function ht(M,B){let J=M.mapClaims(B);if(!J.sub)return{ok:!1};let F=`${M.name}:${J.sub}`,ne={id:F,userName:J.userName||J.email||F,name:J.name||"",email:J.email||"",avatar:J.avatar,userType:"customer"},pe=F;if(Q.customerStore){let me=await Q.customerStore.lookup(ne)??await Q.customerStore.get(F);if(pe=me?.id??F,!me&&!Q.enableJitUserProvisioning)return k.warn("CIAM JIT customer provisioning disabled: unknown customer rejected",{"ion.operation":"customer.store","ion.outcome":"skipped"}),{ok:!1};let Ie=new Date,Oe={...me??{},...ne,id:pe,tenantId:me?.tenantId,createdAt:me?.createdAt??Ie,updatedAt:Ie,userType:me?.userType??"customer"};await Q.customerStore.upsert(Oe)}let de=new Date(Date.now()+(Q.sessionTtl??86400)*1000),re=st(32),ie={sub:pe,iss:M.name,aud:M.clientId,exp:Math.floor(de.getTime()/1000),iat:Math.floor(Date.now()/1000),email:J.email,name:J.name,preferred_username:J.userName??J.email,picture:J.avatar,sid:re},ge={sid:re,sub:pe,authType:"ciam",tenantId:Q.tenantId,expiresAt:de,claims:ie,accessClaims:{sub:pe,sid:re,scope:M.scope},createdAt:new Date},be=X();try{await be.create(ge)}catch(me){if(!await be.get(re))throw me;await be.update(re,ge)}return{ok:!0,claims:ie,sid:re,expires:de}}async function Se(M){X();let B,J,F=(ne)=>{let pe=B?[["Set-Cookie",Le(B)]]:[];return Ne(M,{ok:!1,error:ne},J,pe)};try{let ne=await rt(M),pe=await xe.validate(ne);if(pe.issues||!pe.value)return F(Error("Invalid CIAM callback parameters"));let{code:de,state:re}=pe.value;if(!re)return F(Error("Missing CIAM callback state"));B=_e(re);let ie=ye(B,M,!0);if(J=ie?.context,!ie?.provider||!ie.state||ie.state!==re)return k.warn("CIAM callback state verification failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),F(Error("CIAM callback state verification failed"));let ge=Q.providers?.[ie.provider];if(!ge)return F(Error("Unknown CIAM provider"));let be=Zt(ie.provider,ge);if(!be?.clientId)return F(Error("CIAM provider not configured"));let me=await Ze(be);if(!me.tokenUrl)return F(Error("CIAM provider missing token endpoint"));let Ie=await yt(be),Oe=await Tn({tokenUrl:me.tokenUrl,clientId:be.clientId,clientSecret:Ie,redirectUri:ie.redirectUri||It(Q.customerCallbackUrl||"/auth/customer/callback",M.url),code:de,codeVerifier:be.flow==="id_token"?ie.codeVerifier:void 0,log:k}),Ee;if(be.flow==="id_token"){let ue=be.config.authority;if(!Oe.id_token||!me.jwksUri||!ue)return F(Error("CIAM id_token flow misconfigured"));if(!ie.nonce)return F(Error("CIAM callback state cookie missing nonce"));if((await De.validate(Oe)).issues)return k.warn("CIAM token response validation failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),F(Error("CIAM token response validation failed"));Ee=await kt({idToken:Oe.id_token,jwksUri:me.jwksUri,issuer:ue,audience:be.clientId,expectedNonce:ie.nonce,log:k});let he=await je.validate(Ee);if(!he.issues)Ee=he.value}else{if(!me.userInfoUrl)return F(Error("CIAM provider missing userinfo endpoint"));Ee=await Un(me.userInfoUrl,Oe.access_token);let ue=be.config.authority;if(Oe.id_token&&me.jwksUri&&ue){let ce=await kt({idToken:Oe.id_token,jwksUri:me.jwksUri,issuer:ue,audience:be.clientId,expectedNonce:ie.nonce||void 0,log:k}),he=typeof ce.sub==="string"?ce.sub:"";if(he){if(typeof Ee.sub==="string"&&Ee.sub.length>0&&Ee.sub!==he)return k.warn("CIAM UserInfo sub does not match verified id_token sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),F(Error("CIAM UserInfo sub mismatch"));Ee.sub=he}}if(typeof Ee.sub!=="string"||Ee.sub.length===0)return k.warn("CIAM UserInfo response missing sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),F(Error("CIAM UserInfo response missing sub"))}let ae=await ht(be,Ee);if(!ae.ok)return F(Error("Failed to persist CIAM customer"));let ee=ot(ae.claims);k.info("CIAM third-party sign-in succeeded",{"ion.operation":"ciam.oidc.callback","ion.outcome":"success",provider:be.name});let oe=[["Set-Cookie",Le(B)],$e(ae.sid,ae.expires)];return Ne(M,{ok:!0,user:ee,session:void 0},J,oe)}catch(ne){return k.error("Error during CIAM third-party sign-in callback",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"},ne),F(ne)}}async function ve(M){if(!Q)throw Error("ionite CIAM Manager not initialized");Pe();let B=Q.magicLinkUrl||"/magic-link",J=Q.magicLinkLoginUrl||"/magic-link/login",F=Q.logoutUrl||"/auth/customer/logout",ne=Q.customerLoginUrl||"/auth/customer/login",pe=Q.customerCallbackUrl||"/auth/customer/callback",de=Q.customerProvidersUrl||"/auth/customer/providers",re=new URL(M.url).pathname,ie=(ae)=>{if(!ae)return;try{return new URL(ae).pathname}catch{return ae.startsWith("/")?ae:`/${ae}`}};if(ie(B)===re&&M.method==="POST")return vt(M);if(ie(J)===re&&M.method==="GET")return gt(M);if(ie(F)===re&&M.method==="GET")return Rt(M);if(ie(de)===re&&M.method==="GET")return at({providers:lt()});if(ie(ne)===re&&M.method==="GET")return ct(M);if(ie(pe)===re&&(M.method==="GET"||M.method==="POST"))return Se(M);return new Response("Not Found",{status:404})}return{...Q,getCustomer:Ut,resolveCustomer:Je,logout:Rt,handler:ve,listCustomerProviders:lt}}async function bs(y,k){return t(k,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),k.ciam?.getCustomer(y)}async function Cs(y,k){return t(k,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),await k.ciam?.resolveCustomer(y)??{status:"unauthenticated"}}var Rs="urn:ietf:params:scim:schemas:core:2.0:User",gr="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",vs="urn:ietf:params:scim:schemas:core:2.0:Group";function _n(y,k,R){let V=(k==="group"?y.resources:void 0)?.map((G)=>typeof G==="string"?G:G.id).filter(Boolean);return{schemas:[vs,e],id:y.id,externalId:y.providerId,displayName:y.displayName??y.name,members:R,[e]:{type:k,requestable:y.requestable,riskLevel:y.riskLevel??u,providerId:y.providerId,requestUrl:y.requestUrl,source:y.source,deprecated:y.deprecated,description:y.description,resources:V&&V.length>0?V:void 0,assignableSubjectTypes:y.assignableSubjectTypes,recommendedSubjectTypes:y.recommendedSubjectTypes,attributes:r(y,o)}}}function Is(y){if(y.scimName)return y.scimName;if(!y.name)return;let[k,...R]=y.name.split(" ");return{givenName:k,familyName:R.join(" ")||void 0}}function As(y){let k={attributes:r(y,h)};if(y.ecid!==void 0)k.ecid=y.ecid;if(y.accountClass!==void 0)k.accountClass=y.accountClass;return k.ecid!==void 0||k.accountClass!==void 0||k.attributes!==void 0?k:void 0}function Ts(y){return Object.keys(y.scimSchemaExtensions??{}).filter((k)=>k.startsWith("urn:")&&y.scimSchemaExtensions?.[k]!==void 0)}function On(y){let k=y.userName||y.email||y.id||"",R=y.emails??(y.email?[{value:y.email,primary:!0}]:[]),W=new Set([Rs]);if(y.scimEnterprise!==void 0)W.add(gr);let V=As(y);if(V!==void 0)W.add(s);for(let H of Ts(y))W.add(H);let G={};if(y.scimEnterprise!==void 0)G[gr]=y.scimEnterprise;if(V!==void 0)G[s]=V;for(let[H,Y]of Object.entries(y.scimSchemaExtensions??{}))if(H.startsWith("urn:")&&H!==s&&Y!==void 0)G[H]=Y;return{schemas:Array.from(W),id:y.id,externalId:y.externalId,userName:k,displayName:y.displayName??y.name??k,name:Is(y),nickName:y.nickName,profileUrl:y.avatar,title:y.title,userType:y.userType,preferredLanguage:y.preferredLanguage,locale:y.locale,timezone:y.timezone,active:y.active??!0,emails:R,phoneNumbers:y.phoneNumbers,ims:y.ims,photos:y.photos,addresses:y.addresses,groups:y.groups,entitlements:y.entitlements,roles:y.roles,x509Certificates:y.x509Certificates,meta:{resourceType:"User",created:(y.createdAt??y.updatedAt??new Date).toISOString(),lastModified:(y.updatedAt??y.createdAt??new Date).toISOString()},...G}}function Dn(y){return{schemas:[f],id:y.id,externalId:y.externalId,userName:y.clientId??y.id,displayName:y.displayName??y.clientId??y.id,description:y.description,active:y.active??!0,ecid:y.ecid,providerId:y.providerId,requestUrl:y.requestUrl,attributes:r(y,b),meta:{resourceType:"Workload",created:(y.createdAt??y.updatedAt??new Date).toISOString(),lastModified:(y.updatedAt??y.createdAt??new Date).toISOString()}}}function Ln(y){return{schemas:[g],id:y.id,externalId:y.externalId??y.id,userName:y.userName??y.email??y.id,displayName:y.displayName??y.name??y.userName??y.id,active:y.active??!0,emails:y.emails??(y.email?[{value:y.email,primary:!0}]:void 0),providerId:y.providerId,requestUrl:y.requestUrl,attributes:r(y,S),meta:{resourceType:"Customer",created:(y.createdAt??y.updatedAt??new Date).toISOString(),lastModified:(y.updatedAt??y.createdAt??new Date).toISOString()}}}function Nn(y){return{enabled:y?.enabled!==!1,assignment:y?.assignment??"app",delta:y?.delta}}var Kt="application/scim+json",Ps="urn:ietf:params:scim:api:messages:2.0:ListResponse",Bn="urn:ietf:params:scim:api:messages:2.0:Error",Gn="urn:ietf:params:scim:schemas:core:2.0:User",Jt="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",Kn="urn:ietf:params:scim:schemas:core:2.0:Group",xs="urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig",tn="urn:ietf:params:scim:schemas:core:2.0:ResourceType",Tt="urn:ietf:params:scim:schemas:core:2.0:Schema",Us="00000000000000000000000000000000";function Es(y){let k={timestamp:new Date().toISOString()};if(y)k.actor=y;try{let V=globalThis[Symbol.for("opentelemetry.js.api.1")]?.trace?.getActiveSpan?.()?.spanContext?.(),G=V?.traceId;if(G&&G!==Us){if(k.traceId=G,V?.spanId)k.spanId=V.spanId}}catch{}return k}class Ht extends Error{constructor(y){super(y);this.name="SubjectTypeNotAssignableError",Object.setPrototypeOf(this,Ht.prototype)}}async function Cr(y,k,R,W){let V=R.subjectType;if(!d.includes(V))throw new Ht(`Cannot grant ${R.targetType} "${n(R.target)}" to a "${V}" principal: only [${d.join(", ")}] principals are assignable on this platform.`);let G=x(k,y);if(!G&&!W)return;let H=n(R.target),Y;if(W)Y=await W.getNode(R.targetType,H);else if(G)Y=await(R.targetType==="group"?G.groups:R.targetType==="role"?G.roles:G.permissions).get(H);if(!Y)return;let Q=Y.assignableSubjectTypes;if(!Q||Q.length===0||!Q.includes(V))throw new Ht(`Cannot grant ${R.targetType} "${H}" to a "${V}" principal: this entitlement restricts assignment to [${(Q??[]).join(", ")||"none"}].`)}async function Ms(y,k){let R=A(y.codeCatalog,n(k.target));if(!R)return;if(R.kind!==k.targetType)throw Error(`Cannot grant ${k.targetType} "${R.entity.id}": code declares that id as ${R.kind}.`);if(!y.catalogStore)throw Error(`Cannot grant code entitlement "${R.entity.id}": no AccessCatalogStore is wired for materialization.`);await v(R.kind,R.entity,I(y.catalogStore,R.kind))}async function js(y,k,R,W){await Ms(y,k),await Cr(y.catalogStore,y.codeCatalog,k,W);let V={...k,status:k.status??"active",provenance:k.provenance??Es()};if(V.id=c(V),await y.accessStore?.grant(V),y.accessIndex&&(y.catalogStore||y.codeCatalog)){let G=await O(V,{catalog:y.catalogStore,code:y.codeCatalog,resources:y.resources,cache:W});await y.accessIndex.materialize(V.id,G)}return R?.push({op:"add",change:V}),V}async function Bt(y,k,R){let W=k.id??c(k);await y.accessStore?.revoke(k),await y.accessIndex?.removeByRoot(W),R?.push({op:"delete",change:{...k,id:W}})}async function sn(y,k){let R=await _s(y,k),W=await Ds(y,k);return{oaa:R,delta:W}}async function _s(y,k){if(k.length===0||!y.authz.oaa.isReady())return{status:"skipped"};return Ct(y,"authz.oaa.push","OAA incremental access push failed after SCIM mutation; full sync will reconcile",()=>y.authz.oaa.pushAccessChanges(k),{count:k.length})}async function Ct(y,k,R,W,V){try{return await W(),{status:"ok"}}catch(G){return y.log?.warn(R,{"ion.operation":k,"ion.outcome":"degraded",...V,error:dt(G)}),{status:"degraded",reason:dt(G)}}}var Os=6;async function Ds(y,k){let R=y.iamDelta;if(!R?.isReady()||k.length===0)return{status:"skipped"};let W=new Map;for(let Q of k){let X=`${Q.change.subjectType}:${n(Q.change.subject)}\x00${Q.change.targetType}:${n(Q.change.target)}`;W.set(X,Q)}let V=[...W.values()],G=V.map(({op:Q,change:X})=>()=>Q==="add"?R.onGrant(X):R.onRevoke(X)),Y=(await Ls(G,Os)).filter((Q)=>Q.status==="rejected");if(Y.length>0)return y.log?.warn("IAM delta egress degraded after SCIM mutation; IAM server reconcile/aggregation will recover",{"ion.operation":"iam.delta.egress","ion.outcome":"degraded",failed:Y.length,total:V.length,error:dt(Y[0]?.reason)}),{status:"degraded",reason:dt(Y[0]?.reason)};return{status:"ok"}}async function Ls(y,k){let R=Array(y.length),W=0,V=async()=>{while(!0){let H=W++;if(H>=y.length)return;let Y=y[H];if(!Y)continue;try{R[H]={status:"fulfilled",value:await Y()}}catch(Q){R[H]={status:"rejected",reason:Q}}}},G=Array.from({length:Math.min(k,y.length)},V);return await Promise.all(G),R}class an extends Error{constructor(y){super(y);this.name="DerivedRevokeError",Object.setPrototypeOf(this,an.prototype)}}class Ot extends Error{constructor(y,k,R=!1){super(y);this.name="ScimMutationError",this.summary=k,this.clientError=R,Object.setPrototypeOf(this,Ot.prototype)}}function Re(y,k,R){return new Response(JSON.stringify({schemas:[Bn],status:String(y),scimType:R,detail:k}),{status:y,headers:{"Content-Type":Kt}})}function ft(y,k){let R=k?.totalResults??y.length,W=k?.startIndex??1,V=k?.itemsPerPage??y.length;return new Response(JSON.stringify({schemas:[Ps],totalResults:R,startIndex:W,itemsPerPage:V,Resources:y}),{status:200,headers:{"Content-Type":Kt}})}function Xe(y,k=200,R){let W=new Headers({"Content-Type":Kt});if(R)W.set("Location",R);return new Response(JSON.stringify(y),{status:k,headers:W})}function yr(y){return Re(y.clientError?409:500,`${y.message}; authz mutation summary: ${JSON.stringify(y.summary)}`,y.clientError?"mutability":"invalidValue")}function Gt(y){return c(y)}function Wn(y,k){return on(hr(y),hr(k))}function hr(y){let k=new Map;if(!y?.id)return k;for(let R of y.groups??[]){let W={subject:y.id,subjectType:"user",targetType:"group",target:R.value,metadata:R.display||R.type?{display:R.display,type:R.type}:void 0};k.set(Gt(W),W)}for(let R of y.roles??[]){let W={subject:y.id,subjectType:"user",targetType:"role",target:R.value,metadata:R.display||R.type?{display:R.display,type:R.type,primary:R.primary}:void 0};k.set(Gt(W),W)}for(let R of y.entitlements??[]){let W={subject:y.id,subjectType:"user",targetType:"permission",target:R.value,metadata:R.display||R.type?{display:R.display,type:R.type,primary:R.primary}:void 0};k.set(Gt(W),W)}return k}class cn extends Error{constructor(y){super(y);this.name="AmbiguousMemberSubjectTypeError",Object.setPrototypeOf(this,cn.prototype)}}function Ns(y,k,R){if(y.type==="Group")return;if(y.type==="Workload")return"workload";if(y.type==="User")return"user";if(y.type==="Customer")return"customer";let W=k??[];if(W.length===1)return W[0];throw new cn(`SCIM Group member "${y.value}" of entitlement "${R}" omits type, and the entitlement is assignable to more than one principal kind [${W.join(", ")||"none"}]. Set members[].type to User, Workload, or Customer.`)}function nn(y,k,R,W,V){let G=new Map,H=W&&W.length>0?W:void 0;for(let Y of y??[]){let Q=Ns(Y,V,R);if(!Q)continue;let X={subject:Y.value,subjectType:Q,targetType:k,target:R,resources:H,metadata:Y.display||Y.type?{display:Y.display,type:Y.type}:void 0};G.set(Gt(X),X)}return G}function Vn(y){let k=y[e]?.resources;return k&&k.length>0?k:void 0}function Ws(y,k){let R=(V,G)=>[...V??[]].sort().join(",")===[...G??[]].sort().join(","),W=y[e];if(W?.type!==void 0&&W.type!==k.kind)return!0;if(W?.requestable!==void 0&&W.requestable!==k.entity.requestable)return!0;if(W?.resources!==void 0&&!R(W.resources,Jn(k.entity)))return!0;if(W?.assignableSubjectTypes!==void 0&&!R(W.assignableSubjectTypes,k.entity.assignableSubjectTypes))return!0;if(W?.recommendedSubjectTypes!==void 0&&!R(W.recommendedSubjectTypes,k.entity.recommendedSubjectTypes))return!0;return!1}function Vs(y,k){let R=(G,H)=>[...G??[]].sort().join(",")===[...H??[]].sort().join(","),W=y[e],V=k[e];if(W?.type!==void 0&&W.type!==V?.type)return!0;if(W?.requestable!==void 0&&W.requestable!==V?.requestable)return!0;if(W?.resources!==void 0&&!R(W.resources,V?.resources))return!0;if(W?.assignableSubjectTypes!==void 0&&!R(W.assignableSubjectTypes,V?.assignableSubjectTypes))return!0;if(W?.recommendedSubjectTypes!==void 0&&!R(W.recommendedSubjectTypes,V?.recommendedSubjectTypes))return!0;return!1}function qs(y){let k=new Map;for(let R of y)k.set(Gt(R),R);return k}async function Pt(y,k,R,W,V,G){let H=[],Y=new Set,Q=(Pe,xe)=>`${xe}\x00${Pe}`,X=G?G.get(`${R}:${W}`)??[]:k?(await k.listByTarget(R,W)).items:[];for(let Pe of X){let xe=n(Pe.subject),je=Pe.metadata,De=Pe.subjectType==="workload"?"Workload":Pe.subjectType==="customer"?"Customer":je?.type??"User",We=Q(xe,De);if(Y.has(We))continue;Y.add(We),H.push({value:xe,...je?.display?{display:je.display}:{},type:De})}for(let Pe of V??[]){if(Pe.targetType!==R||n(Pe.target)!==W)continue;let xe=n(Pe.subject),je=Q(xe,"Workload");if(Y.has(je))continue;Y.add(je),H.push({value:xe,type:"Workload"})}if(R==="group"){let Pe=await y.groups.get(W);for(let xe of Pe?.groups??[]){let je=n(xe),De=Q(je,"Group");if(!je||Y.has(De))continue;Y.add(De),H.push({value:je,type:"Group"})}}return H.length>0?H:void 0}function on(y,k){let R=[];for(let[W,V]of k)if(!y.has(W))R.push({action:"grant",change:V});for(let[W,V]of y)if(!k.has(W))R.push({action:"revoke",change:V});return R}async function qn(y,k){if(y.oaa.isReady())await y.oaa.pushUser(k)}async function Sr(y,k,R){if(k?.externalId&&k.externalId!==R.externalId)await y?.onUserDelete(k.externalId);await y?.onUserUpsert(R)}async function jt(y,k,R,W){let V={metadataApplied:!1,access:[]},G={status:"skipped"},H=[],Y=new _(y.catalogStore,y.resources,y.codeCatalog);try{try{await k(),V.metadataApplied=!0}catch(Q){for(let X of R)V.access.push({change:X.change,status:"rolled_back"});throw V.metadataApplied=!1,new Ot(`SCIM metadata write failed: ${dt(Q)}`,V,!1)}if(W?.oaa)await Ct(y,"authz.oaa.metadata","OAA metadata projection failed after SCIM write; full sync will reconcile",W.oaa);if(W?.delta&&y.iamDelta?.isReady())G=await Ct(y,"iam.delta.egress","IAM delta metadata projection failed after SCIM write; full aggregation will reconcile",W.delta);for(let Q=0;Q<R.length;Q++){let X=R[Q];try{if(X.action==="grant")await js(y,X.change,H,Y);else await Ks(y,X.change,H);V.access.push({change:X.change,status:"applied"})}catch(Pe){V.access.push({change:X.change,status:"failed",error:Pe});for(let je=Q+1;je<R.length;je++)V.access.push({change:R[je].change,status:"rolled_back"});let xe=Pe instanceof an||Pe instanceof Ht;if(!xe)await Bs(y,X.change,Y);throw new Ot(xe?dt(Pe):`SCIM access mutation failed: ${dt(Pe)}`,V,xe)}}return V}finally{await zs(y),V.egress=await sn(y,H),V.egress.delta=$s(G,V.egress.delta),Gs(y,V)}}function $s(y,k){if(y.status==="degraded")return y;if(k.status==="degraded")return k;return y.status==="ok"||k.status==="ok"?{status:"ok"}:{status:"skipped"}}function dt(y){return y instanceof Error?y.message:String(y)}async function zs(y){try{await y.settleAuthz?.()}catch{}}async function Bs(y,k,R){if(!y.accessIndex||!y.catalogStore&&!y.codeCatalog||!y.accessStore)return;let W=n(k.subject);if(!W)return;let V=k.subjectType;try{await z(W,V,{accessStore:y.accessStore,accessIndex:y.accessIndex,catalogStore:y.catalogStore,code:y.codeCatalog,resources:y.resources},R)}catch(G){y.log?.warn("Per-subject reconcile after failed SCIM access mutation failed",{"ion.operation":"authz.reconcile.subject.repair","ion.outcome":"degraded",subject:W,subjectType:V,error:dt(G)})}}function Gs(y,k){if(!y.onAccessMutation)return;try{y.onAccessMutation(k)}catch{}}async function Ks(y,k,R){if(y.accessStore){let W=k.id??c(k);if(!await y.accessStore.get(W)){if((y.accessIndex?await y.accessIndex.has(k.subject,k.targetType,k.target,k.resources?.[0],k.subjectType):{allow:!1}).allow)throw new an(`Cannot revoke ${k.targetType} "${n(k.target)}" for "${n(k.subject)}": it is not a directly granted root (it is derived from group/role membership). Remove the granting group/role instead.`);await Bt(y,k,R);return}}await Bt(y,k,R)}function _t(y){let k=y[e]?.type??"group";if(k==="group"||k==="role"||k==="permission")return k;throw Error(`Unsupported ionite SCIM Group authz type "${String(k)}"`)}async function $n(y,k,R){if(!y.oaa.isReady())return;if(R==="role"){await y.oaa.pushRole(k);return}if(R==="permission"){await y.oaa.pushPermission(k);return}await y.oaa.pushGroup(k)}function Jn(y){let k=y.resources;if(!k||k.length===0)return;let R=k.map((W)=>typeof W==="string"?W:W.id).filter(Boolean);return R.length>0?R:void 0}function xt(y,k,R){return _n(y,k,R)}function Js(y,k){let R=y[e],V={...r(R?.attributes??{},o),id:k,name:y.displayName,displayName:y.displayName,description:R?.description??y.displayName,requestable:R?.requestable,riskLevel:R?.riskLevel??u,providerId:R?.providerId??y.externalId,requestUrl:R?.requestUrl,assignableSubjectTypes:["user"]};if(R?.resources!==void 0)V.resources=R.resources;return V}function Hs(y){if(!y)return;let k=y.trim().match(/^requestable\s+eq\s+(true|false)$/i);if(!k)return;return{requestable:k[1]?.toLowerCase()==="true"}}function kr(y){if(!y)return;let k=y.trim().match(/^externalId\s+eq\s+"([^"]*)"$/i);return k?k[1]:void 0}function Fs(y){if(!y)return;let k=y.trim(),R=k.match(/^userName\s+eq\s+"([^"]*)"$/i);if(R)return{userName:R[1]};let W=k.match(/^externalId\s+eq\s+"([^"]*)"$/i);if(W)return{externalId:W[1]};let V=k.match(/^meta\.lastModified\s+gt\s+"([^"]*)"$/i);if(V)return{updatedAfter:V[1]};return}function Ys(y,k,R){let W=new Set(["id","schemas"]),V={...y};if(k){let G=new Set(k.split(",").map((H)=>H.trim()).filter(Boolean));for(let H of Object.keys(V))if(!W.has(H)&&!G.has(H))delete V[H]}if(R){for(let G of R.split(",").map((H)=>H.trim()).filter(Boolean))if(!W.has(G))delete V[G]}return V}function wr(y,k){let R=async(G,H,Y)=>{let Q=await y.toScim(G),X=G.id;return{...Q,id:X,meta:{...Q.meta??{},resourceType:y.resourceType,location:X?He(H,`${Y}/${encodeURIComponent(X)}`):void 0}}},W=(G,H)=>{let Y=H.op.toLowerCase();if(!H.path){if(Y!=="remove"&&H.value&&typeof H.value==="object"&&!Array.isArray(H.value))Object.assign(G,H.value);return}if(Y==="remove"){delete G[H.path];return}G[H.path]=H.value};return{handler:async(G,H)=>{if(!await k.validateAuth(G))return Re(401,"Authorization required");let Y=new URL(G.url),Q=H?.basePath??`/${y.resourceType}s`,X=Y.pathname;if(X.startsWith(Q))X=X.substring(Q.length);let Pe=X.match(/^\/([^/]+)$/),xe=Pe?.[1]?decodeURIComponent(Pe[1]):void 0,je=Y.searchParams.get("attributes"),De=Y.searchParams.get("excludedAttributes"),We=(ke)=>Ys(ke,je,De);try{if(xe){if(G.method==="GET"){let ke=await y.store.get(xe);if(!ke)return Re(404,`${y.resourceType} not found`);return Xe(We(await R(ke,G,Q)))}if(G.method==="PUT"||G.method==="PATCH"){let ke=await y.store.get(xe);if(!ke)return Re(404,`${y.resourceType} not found`);let Le=await G.json(),ye=Le;if(G.method==="PATCH"){let Ge=Le.Operations;if(!Array.isArray(Ge))return Re(400,"PATCH requires Operations","invalidSyntax");let Je=await y.toScim(ke);for(let nt of Ge)W(Je,nt);ye=Je}let _e=await bt(y.validator,ye);if(_e.issues)return Re(400,_e.issues.map((Ge)=>Ge.message).join("; "),"invalidValue");let Ne=G.method==="PATCH"?"patch":"replace",$e=await y.store.upsert({...await y.fromScim(_e.value,{existing:ke,mode:Ne}),id:ke.id??xe});if(ke.active!==$e.active)await k.accessIndex?.setSubjectDisabled?.($e.id,y.subjectType,$e.active===!1);let tt=$e.id?He(G,`${Q}/${encodeURIComponent($e.id)}`):void 0;for(let Ge of y.projections??[])await Ct(k,`${Ge.channel}.${y.subjectType}.upsert`,`${y.resourceType} projection degraded after SCIM upsert; aggregation will reconcile`,()=>Ge.upsert($e,ke));return Xe(We(await R($e,G,Q)),200,tt)}if(G.method==="DELETE"){let ke=await y.store.get(xe);if(!ke)return Re(404,`${y.resourceType} not found`);if(k.revokeSubjectAccess)await k.revokeSubjectAccess(xe,y.subjectType);await y.store.delete(xe),await k.accessIndex?.setSubjectDisabled?.(xe,y.subjectType,!1);for(let Le of y.projections??[])await Ct(k,`${Le.channel}.${y.subjectType}.delete`,`${y.resourceType} projection degraded after SCIM delete; aggregation will reconcile`,()=>Le.delete(ke));return new Response(null,{status:204})}return Re(405,"Method not allowed")}if(G.method==="GET"){let ke=parseInt(Y.searchParams.get("startIndex")??"",10),Le=parseInt(Y.searchParams.get("count")??"",10),ye=ke!=null&&!Number.isNaN(ke)?Math.max(0,ke-1):0,_e=Le!=null&&!Number.isNaN(Le)?Le:void 0,Ne=Fs(Y.searchParams.get("filter"));if(Ne?.externalId!==void 0){let Ge=y.store.getByExternalId?await y.store.getByExternalId(Ne.externalId):await y.store.lookup({externalId:Ne.externalId}),Je=Ge?[We(await R(Ge,G,Q))]:[];return ft(Je,{totalResults:Je.length,startIndex:1,itemsPerPage:Je.length})}let $e=await y.store.list({start:ye,limit:_e,filter:Ne}),tt=await Promise.all($e.items.map(async(Ge)=>We(await R(Ge,G,Q))));return ft(tt,{totalResults:$e.total,startIndex:ye+1,itemsPerPage:$e.count})}if(G.method==="POST"){let ke=await G.json(),Le=await bt(y.validator,ke);if(Le.issues)return Re(400,Le.issues.map((Ne)=>Ne.message).join("; "),"invalidValue");let ye=await y.store.upsert(await y.fromScim(Le.value,{mode:"create"}));if(ye.active===!1)await k.accessIndex?.setSubjectDisabled?.(ye.id,y.subjectType,!0);for(let Ne of y.projections??[])await Ct(k,`${Ne.channel}.${y.subjectType}.upsert`,`${y.resourceType} projection degraded after SCIM create; aggregation will reconcile`,()=>Ne.upsert(ye,void 0));let _e=ye.id?He(G,`${Q}/${encodeURIComponent(ye.id)}`):void 0;return Xe(We(await R(ye,G,Q)),201,_e)}return Re(405,"Method not allowed")}catch(ke){if(T(ke))return Re(409,ke.message,"uniqueness");return Re(500,ke instanceof Error?ke.message:"Internal error")}}}}async function Xs(y,k,R,W){let V=[],G=[["group",y.groups],["role",y.roles],["permission",y.permissions]];for(let[Y,Q]of G)for await(let X of i((Pe,xe)=>Q.list({start:Pe,limit:xe,filter:{requestable:!0}})))if(X.providerId===R)V.push({entity:X,type:Y});if(V.length>1)throw new m(`Ambiguous providerId "${R}": ${V.length} entitlements share it (${V.map((Y)=>`${Y.type}:${Y.entity.id}`).join(", ")})`,"unique_violation","providerId");let H=V[0];if(H?.entity.requestable!==!0)return;return xt(H.entity,H.type,await Pt(y,k,H.type,H.entity.id,W))}async function Zs(y,k,R,W){let V=Math.max(0,R.start),G=R.limit!=null?V+R.limit:void 0,H={start:0,limit:G,filter:R.filter},[Y,Q,X]=await Promise.all([y.groups.list(H),y.roles.list(H),y.permissions.list(H)]),Pe=[...Y.items.map((ke)=>({entity:ke,type:"group"})),...Q.items.map((ke)=>({entity:ke,type:"role"})),...X.items.map((ke)=>({entity:ke,type:"permission"}))],xe=Y.total+Q.total+X.total,je=Pe.slice(V,G),De=k?.listByTargets?await k.listByTargets(je.map(({entity:ke,type:Le})=>({targetType:Le,target:ke.id}))):void 0,We=await Promise.all(je.map(async({entity:ke,type:Le})=>xt(ke,Le,await Pt(y,k,Le,ke.id,W,De))));return{resources:We,total:xe,count:We.length}}async function zt(y,k,R,W){let[V,G,H]=await Promise.all([y.groups.get(R),y.roles.get(R),y.permissions.get(R)]);if(V)return xt(V,"group",await Pt(y,k,"group",R,W));if(G)return xt(G,"role",await Pt(y,k,"role",R,W));if(H)return xt(H,"permission",await Pt(y,k,"permission",R,W));return}async function zn(y,k,R,W){let V=_t(k),G=V==="role"?await y.roles.get(R):V==="permission"?await y.permissions.get(R):await y.groups.get(R),H=Js(k,R),Y=G?.assignableSubjectTypes&&G.assignableSubjectTypes.length>0?G.assignableSubjectTypes:["user"],Q={...G??{},...H,source:G?.source??"scim",assignableSubjectTypes:Y},X=W?W.displayName??W.name:G?.name;if(H.displayName===X)delete Q.displayName;if(H.riskLevel===(W?.riskLevel??u))delete Q.riskLevel;let Pe=r(H,o),xe=W?r(W,o):void 0;if(k[e]?.attributes!==void 0){for(let De of Object.keys(r(G??{},o)??{}))if(!(De in(Pe??{})))delete Q[De]}for(let[De,We]of Object.entries(Pe??{}))if(p(We,xe?.[De]))delete Q[De];if(W)Q.name=W.name;let je=V==="role"?y.roles.set(Q):V==="permission"?y.permissions.set(Q):y.groups.set(Q);return await je.ready(),je}async function Qs(y,k){await Promise.all([y.groups.delete(k),y.roles.delete(k),y.permissions.delete(k)])}function rn(){return crypto.randomUUID()}function bt(y,k){let R=y;if(typeof R.validate==="function")return R.validate(k);return Promise.resolve(y["~standard"].validate(k))}function ei(y){if(!y)return;try{return new URL(y).pathname}catch{return y.startsWith("/")?y:`/${y}`}}function ut(y){let k=ei(y);return k?C(k):void 0}function br(...y){for(let k of y){let R=ut(k);if(!R)continue;for(let W of["/Users","/Groups","/Workloads","/Customers"])if(R.endsWith(W))return R.slice(0,-W.length)}return}function He(y,k){return new URL(k,y.url).toString()}function se(y,k,R,W){let{multiValued:V=!1,...G}=W??{};return{name:y,type:k,description:R,multiValued:V,...G}}function ti(y,k){return{schemas:[xs],documentationUri:k?.documentationUri,patch:{supported:!0},bulk:{supported:!1},filter:{supported:!0,maxResults:1000},changePassword:{supported:!1},sort:{supported:!1},etag:{supported:!1},authenticationSchemes:[{type:"oauthbearertoken",name:"OAuth Bearer Token",description:"Use an ionite workload bearer token for IAM discovery and provisioning requests.",primary:!0}],meta:{resourceType:"ServiceProviderConfig",location:He(y.request,`${y.basePath}/ServiceProviderConfig`)}}}function ni(y){let k=[];if(y.supportsUsers)k.push({schemas:[tn],id:"User",name:"User",description:"User Account",endpoint:y.usersUrl,schema:Gn,schemaExtensions:[{schema:Jt,required:!1},{schema:s,required:!1}],meta:{resourceType:"ResourceType",location:He(y.request,`${y.basePath}/ResourceTypes/User`)}});if(y.supportsGroups)k.push({schemas:[tn],id:"Group",name:"Group",description:"Group",endpoint:y.groupsUrl,schema:Kn,schemaExtensions:[{schema:e,required:!1}],meta:{resourceType:"ResourceType",location:He(y.request,`${y.basePath}/ResourceTypes/Group`)}});if(y.supportsWorkloads)k.push({schemas:[tn],id:"Workload",name:"Workload",description:"Workload (machine) principal",endpoint:y.workloadsUrl,schema:f,meta:{resourceType:"ResourceType",location:He(y.request,`${y.basePath}/ResourceTypes/Workload`)}});if(y.supportsCustomers)k.push({schemas:[tn],id:"Customer",name:"Customer",description:"Customer (CIAM) principal",endpoint:y.customersUrl,schema:g,meta:{resourceType:"ResourceType",location:He(y.request,`${y.basePath}/ResourceTypes/Customer`)}});return k}function ri(y){let k=[];if(y.supportsUsers)k.push({schemas:[Tt],id:Gn,name:"User",description:"User Account",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(Gn)}`)},attributes:[se("id","string","Unique identifier for the User.",{multiValued:!1,required:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),se("externalId","string","External identifier from the provisioning client.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",uniqueness:"none"}),se("userName","string","Unique identifier typically used for login.",{multiValued:!1,required:!0,caseExact:!1,mutability:"readWrite",returned:"default",uniqueness:"server"}),se("name","complex","The components of the user name.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",subAttributes:[se("formatted","string","The full name, including titles and suffixes.",{multiValued:!1}),se("familyName","string","The family name of the User.",{multiValued:!1}),se("givenName","string","The given name of the User.",{multiValued:!1}),se("middleName","string","The middle name(s) of the User.",{multiValued:!1}),se("honorificPrefix","string","The honorific prefix(es) of the User.",{multiValued:!1}),se("honorificSuffix","string","The honorific suffix(es) of the User.",{multiValued:!1})]}),se("displayName","string","The name of the User, suitable for display.",{multiValued:!1}),se("nickName","string","The casual way to address the user.",{multiValued:!1}),se("profileUrl","reference","A URL pointing to the User profile.",{multiValued:!1,referenceTypes:["external"]}),se("title","string","The user title, such as Vice President.",{multiValued:!1}),se("userType","string","The relationship between the organization and the User.",{multiValued:!1}),se("preferredLanguage","string","Preferred written or spoken language.",{multiValued:!1}),se("locale","string","Default location for localizing values.",{multiValued:!1}),se("timezone","string","The User time zone.",{multiValued:!1}),se("active","boolean","The User administrative status.",{multiValued:!1}),se("emails","complex","Email addresses for the User.",{multiValued:!0,subAttributes:[se("value","string","Email address value.",{multiValued:!1,required:!0}),se("display","string","Display label for the email.",{multiValued:!1}),se("type","string","Email type such as work or home.",{multiValued:!1}),se("primary","boolean","Primary email indicator.",{multiValued:!1})]}),se("phoneNumbers","complex","Phone numbers for the User.",{multiValued:!0,subAttributes:[se("value","string","Phone number value.",{multiValued:!1,required:!0}),se("display","string","Display label for the phone number.",{multiValued:!1}),se("type","string","Phone number type.",{multiValued:!1}),se("primary","boolean","Primary phone number indicator.",{multiValued:!1})]}),se("photos","complex","Photo URLs for the User.",{multiValued:!0,subAttributes:[se("value","reference","Photo URL.",{multiValued:!1,required:!0,referenceTypes:["external"]}),se("display","string","Display label for the photo.",{multiValued:!1}),se("type","string","Photo type.",{multiValued:!1}),se("primary","boolean","Primary photo indicator.",{multiValued:!1})]}),se("addresses","complex","Physical mailing addresses for the User.",{multiValued:!0,subAttributes:[se("formatted","string","Formatted mailing address.",{multiValued:!1}),se("streetAddress","string","Full street address component.",{multiValued:!1}),se("locality","string","City or locality.",{multiValued:!1}),se("region","string","State or region.",{multiValued:!1}),se("postalCode","string","Postal code.",{multiValued:!1}),se("country","string","Country.",{multiValued:!1}),se("type","string","Address type.",{multiValued:!1}),se("primary","boolean","Primary address indicator.",{multiValued:!1})]}),se("groups","complex","Groups to which the User belongs.",{multiValued:!0,mutability:"readOnly",subAttributes:[se("value","string","Group identifier.",{multiValued:!1,required:!0}),se("$ref","reference","Reference to the Group resource.",{multiValued:!1,referenceTypes:["Group"]}),se("display","string","Display name of the group.",{multiValued:!1}),se("type","string","Relationship type.",{multiValued:!1})]}),se("entitlements","complex","Entitlements for the User.",{multiValued:!0,subAttributes:[se("value","string","Entitlement value.",{multiValued:!1,required:!0}),se("display","string","Display value.",{multiValued:!1}),se("type","string","Entitlement type.",{multiValued:!1}),se("primary","boolean","Primary entitlement indicator.",{multiValued:!1})]}),se("roles","complex","Roles for the User.",{multiValued:!0,subAttributes:[se("value","string","Role value.",{multiValued:!1,required:!0}),se("display","string","Display value.",{multiValued:!1}),se("type","string","Role type.",{multiValued:!1}),se("primary","boolean","Primary role indicator.",{multiValued:!1})]}),se("x509Certificates","complex","Certificates issued to the User.",{multiValued:!0,subAttributes:[se("value","string","Certificate value.",{multiValued:!1,required:!0}),se("display","string","Display value.",{multiValued:!1}),se("type","string","Certificate type.",{multiValued:!1}),se("primary","boolean","Primary certificate indicator.",{multiValued:!1})]})]}),k.push({schemas:[Tt],id:Jt,name:"EnterpriseUser",description:"Enterprise User extension",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(Jt)}`)},attributes:[se("employeeNumber","string","Numeric or alphanumeric identifier assigned to a person.",{multiValued:!1}),se("costCenter","string","Name of a cost center.",{multiValued:!1}),se("organization","string","Name of an organization.",{multiValued:!1}),se("division","string","Name of a division.",{multiValued:!1}),se("department","string","Name of a department.",{multiValued:!1}),se("manager","complex","The User manager.",{multiValued:!1,subAttributes:[se("value","string","Identifier of the manager User resource.",{multiValued:!1}),se("$ref","reference","Reference to the manager User resource.",{multiValued:!1,referenceTypes:["User"]}),se("displayName","string","Display name of the manager.",{multiValued:!1})]})]}),k.push({schemas:[Tt],id:s,name:"IoniteUser",description:"ionite User extension carrying ECID, account purpose, and AppDev custom attributes. See https://ionite.com/docs/llms-ecid.txt.",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(s)}`)},attributes:[se("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}),se("accountClass","string","Account purpose (distinct from userType persona). Open value set: 'daily', 'privileged', 'break_glass', 'service'.",{multiValued:!1}),se("attributes","complex","AppDev custom attributes. IAM may override seeded values.",{multiValued:!1,required:!1,mutability:"readWrite"})]});if(y.supportsGroups)k.push({schemas:[Tt],id:e,name:"IoniteAuthzGroup",description:"ionite authorization metadata for SCIM Group resources.",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(e)}`)},attributes:[se("type","string","Authorization entity kind: group, role, or permission.",{multiValued:!1,required:!1}),se("requestable","boolean","Whether this catalog entry is exposed as assignable access to IAM tooling. Only true entries are served.",{multiValued:!1,required:!1}),se("riskLevel","string",`Advisory access-risk classification. Unset values project as ${u}; canonical values are suggestions, not a closed enum.`,{multiValued:!1,required:!1,mutability:"readWrite",canonicalValues:[...U]}),se("providerId","string","IAM service-provider id captured when this entitlement is materialized at the destination.",{multiValued:!1,required:!1,mutability:"readWrite"}),se("requestUrl","reference","IAM-owned deep link where a principal can request this entitlement.",{multiValued:!1,required:!1,mutability:"readWrite",referenceTypes:["external"]}),se("source","string","Provenance of the catalog row.",{multiValued:!1,required:!1,mutability:"readOnly",canonicalValues:["code","app","scim"]}),se("deprecated","boolean","Whether this retired entitlement may be deleted.",{multiValued:!1,required:!1,mutability:"readOnly"}),se("description","string","Human-readable authorization entity description.",{multiValued:!1,required:!1}),se("resources","string","Resource ids this entitlement is scoped to.",{multiValued:!0,required:!1}),se("assignableSubjectTypes","string","AppDev-owned required audience of principal kinds (user, workload, customer) that may hold this entitlement. Read-only to IAM tooling.",{multiValued:!0,required:!1,mutability:"readOnly",canonicalValues:["user","customer","workload"]}),se("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"]}),se("attributes","complex","AppDev custom attributes. IAM may override seeded values.",{multiValued:!1,required:!1,mutability:"readWrite"})]});if(y.supportsGroups)k.push({schemas:[Tt],id:Kn,name:"Group",description:"Group",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(Kn)}`)},attributes:[se("id","string","Unique identifier for the Group.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),se("externalId","string","External identifier from the provisioning client.",{multiValued:!1,uniqueness:"none"}),se("displayName","string","Human-readable name for the Group.",{multiValued:!1,required:!0,uniqueness:"none"}),se("members","complex","Members of the Group.",{multiValued:!0,subAttributes:[se("value","string","Identifier of the member resource.",{multiValued:!1,required:!0}),se("$ref","reference","Reference to the member resource.",{multiValued:!1,referenceTypes:["User","Group","Workload","Customer"]}),se("display","string","Display name of the member.",{multiValued:!1}),se("type","string","Member type.",{multiValued:!1})]})]});if(y.supportsWorkloads)k.push({schemas:[Tt],id:f,name:"Workload",description:"Workload (machine) principal",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(f)}`)},attributes:[se("id","string","Unique identifier for the Workload.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),se("externalId","string","External identifier from the provisioning client.",{multiValued:!1}),se("userName","string","Login identifier, typically the OAuth clientId.",{multiValued:!1}),se("displayName","string","Human-readable name for the Workload.",{multiValued:!1}),se("description","string","Free-form description of the Workload.",{multiValued:!1}),se("active","boolean","Administrative status of the Workload.",{multiValued:!1}),se("attributes","complex","AppDev custom attributes.",{multiValued:!1,required:!1,mutability:"readWrite"})]});if(y.supportsCustomers)k.push({schemas:[Tt],id:g,name:"Customer",description:"Customer (CIAM) principal",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(g)}`)},attributes:[se("id","string","Unique identifier for the Customer.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),se("externalId","string","External identifier from the provisioning client.",{multiValued:!1}),se("userName","string","Unique identifier typically used for login.",{multiValued:!1}),se("displayName","string","Human-readable name for the Customer.",{multiValued:!1}),se("active","boolean","Administrative status of the Customer.",{multiValued:!1}),se("emails","complex","Email addresses for the Customer.",{multiValued:!0,subAttributes:[se("value","string","Email address.",{multiValued:!1,required:!0}),se("primary","boolean","Whether this is the primary email.",{multiValued:!1})]}),se("attributes","complex","AppDev custom attributes.",{multiValued:!1,required:!1,mutability:"readWrite"})]});return k}function si(y,k,R,W,V,G,H,Y,Q,X,Pe,xe,je,De,We){let ke={authz:W,settleAuthz:We,accessStore:V,accessIndex:G,catalogStore:H,codeCatalog:Y,resources:Q,log:k,iamDelta:xe,onAccessMutation:je};if(!X&&!Pe)return;let ye={...X,...Pe},_e=ye.users?.enabled!==!1,Ne=ye.groups?.enabled!==!1,$e=ye.workloads?.enabled!==!1,tt=ye.customers?.enabled!==!1;if(Boolean(ye.url||ye.userStore||H||Y)&&!R)k.error("IAM requires workload identity for SCIM push/pull operations",{"ion.operation":"workload.require","ion.outcome":"failure"});function Je(){if(!R)throw k.error("IAM requires workload identity for SCIM push/pull operations",{"ion.operation":"workload.require","ion.outcome":"failure"}),Error("IAM requires workload identity for SCIM push/pull operations");return R}async function nt(Se){let ve=Je(),M=Se.headers.get("Authorization");if(!M?.startsWith("Bearer "))return!1;try{let B=M.substring(7);return(await ve.validateToken(B)).valid}catch{return!1}}async function Ut(){let Se=Je(),ve=typeof Se.getServerToken==="function"?await Se.getServerToken():await Se.getToken();return new Headers({"Content-Type":Kt,Accept:Kt,Authorization:`Bearer ${ve}`})}async function Rt(Se,ve,M,B){if(!ye.url)throw Error("IAM URL not configured for outgoing requests");let J=`${ye.url}${ve}`;try{let F=await Ut(),ne=await fetch(J,{method:Se,headers:F,body:M?JSON.stringify(M):void 0}),pe=await ne.json();if(!ne.ok)return{success:!1,error:pe,status:ne.status};let de=await B["~standard"].validate(pe);if(de.issues)return k.error("SCIM response validation failed",{"ion.operation":"scim.response.validate","ion.outcome":"failure",validationIssues:de.issues}),{success:!1,error:{schemas:[Bn],status:"400",scimType:"invalidValue",detail:`Response validation failed: ${de.issues.map((re)=>re.message).join("; ")}`},status:400};return{success:!0,data:de.value,status:ne.status}}catch(F){return{success:!1,error:{schemas:[Bn],status:"500",detail:F instanceof Error?F.message:"Unknown error occurred"},status:500}}}function Et(){return ye.url}function Dt(Se,ve){let M=ut(ve?.usersUrl??ye.usersUrl??"/api/iam/Users")??"/api/iam/Users",B=ut(ve?.groupsUrl??ye.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",J=ut(ve?.workloadsUrl??ye.workloadsUrl??"/api/iam/Workloads")??"/api/iam/Workloads",F=ut(ve?.customersUrl??ye.customersUrl??"/api/iam/Customers")??"/api/iam/Customers",ne=ut(ve?.discovery?.basePath??ye.discovery?.basePath)??br(M,B,J,F);if(!ne)return;return{request:Se,basePath:ne,usersUrl:M,groupsUrl:B,workloadsUrl:J,customersUrl:F,supportsUsers:_e&&Boolean(ye.userStore),supportsGroups:Ne&&Boolean(H||Y),supportsWorkloads:$e&&Boolean(ye.workloadIdentityStore),supportsCustomers:tt&&Boolean(ye.customerStore)}}async function Lt(Se){let ve=ti(Se,ye.discovery);return await ye.discovery?.buildServiceProviderConfig?.(Se,ve)??ve}async function ot(Se){let ve=ni(Se);return await ye.discovery?.buildResourceTypes?.(Se,ve)??ve}async function vt(Se){let ve=ri(Se);return await ye.discovery?.buildSchemas?.(Se,ve)??ve}async function gt(Se,ve){let M=Dt(Se,ve);if(!M)return;let B=C(new URL(Se.url).pathname),{basePath:J}=M;if(B!==J&&!B.startsWith(`${J}/`))return;let F=C(B.slice(J.length)||"/");if(!(F==="/ServiceProviderConfig"||F==="/ResourceTypes"||F.startsWith("/ResourceTypes/")||F==="/Schemas"||F.startsWith("/Schemas/")))return;if(Se.method!=="GET")return Re(405,"Method not allowed");if(!await nt(Se))return Re(401,"Authorization required");if(F==="/ServiceProviderConfig")return Xe(await Lt(M));if(F==="/ResourceTypes")return ft(await ot(M));if(F.startsWith("/ResourceTypes/")){let de=decodeURIComponent(F.slice(15)),re=(await ot(M)).find((ie)=>ie.id===de||ie.name===de);return re?Xe(re):Re(404,"Resource not found")}if(F==="/Schemas")return ft(await vt(M));if(F.startsWith("/Schemas/")){let de=decodeURIComponent(F.slice(9)),re=(await vt(M)).find((ie)=>ie.id===de);return re?Xe(re):Re(404,"Resource not found")}return}let at,It;if(ye.url)It=async(ve,M)=>{let B={...ve,schemas:ve.schemas??["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"]};return Rt("POST","/Users",B,y.user)},at={createGroup:async(ve,M)=>{let B={schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],displayName:ve,externalId:M?.id,members:M?.members};return Rt("POST","/Groups",B,y.group)}};let lt;if(H||Y){let Se=x(Y,H),ve=(ae,ee,oe)=>{let ue=ae[e]??{},ce=_t(ae),he=ae.id,we=he?He(ee,`${oe}/${encodeURIComponent(he)}`):void 0,fe={id:he??ae.externalId??ae.displayName,name:ae.displayName,displayName:ae.displayName,description:ue.description??ae.displayName,requestable:ue.requestable,providerId:ue.providerId??ae.externalId,requestUrl:ue.requestUrl,source:ue.source,deprecated:ue.deprecated,riskLevel:ue.riskLevel,assignableSubjectTypes:ue.assignableSubjectTypes,recommendedSubjectTypes:ue.recommendedSubjectTypes},Ce=ue.requestUrl??ye.entitlementRequestUrl?.(fe,ce,{request:ee});return{...ae,meta:{...ae.meta,resourceType:"Group",location:we},[e]:{...ue,requestUrl:Ce}}},M=(ae)=>A(Y,ae),B=async(ae,ee)=>{if(!H){if(ee)throw Error(`Cannot persist access for code entitlement "${ae.entity.id}": no AccessCatalogStore is wired.`);return ae.entity}try{return await v(ae.kind,ae.entity,I(H,ae.kind))}catch(oe){if(ee)throw oe;return k.warn("Code entitlement discovery materialization failed; serving the code template",{"ion.operation":"iam.catalog.materialize","ion.outcome":"degraded",entitlementId:ae.entity.id,entitlementType:ae.kind,error:dt(oe)}),ae.entity}},J=async(ae)=>{if(!H)return;try{await j(Y,H,ae)}catch(ee){k.warn("Retired code entitlement deprecation failed; serving the last durable row",{"ion.operation":"iam.catalog.deprecate","ion.outcome":"degraded",entitlementId:ae,error:dt(ee)})}},F=(ae,ee)=>Re(403,`Entitlement "${ae}" is declared in application code; its structural definition cannot be ${ee} through SCIM. IAM may change presentation and receipts, while code continues to own structure.`,"mutability"),ne=(ae)=>ae.path==="members"||Boolean(ae.path?.startsWith("members[")),pe=(ae)=>ne(ae)||ae.path==="displayName"||ae.path===`${e}.description`||ae.path===`${e}.riskLevel`||ae.path===`${e}.providerId`||ae.path===`${e}.requestUrl`||ae.path===`${e}.attributes`||Boolean(ae.path?.startsWith(`${e}.attributes.`)),de=(ae)=>ae?.[e]?.requestable===!0,re=(ae)=>Re(404,`Requestable Group ${ae} not found`,"invalidValue"),ie=async(ae,ee)=>{if(!await nt(ae))return Re(401,"Authorization required");let ue=new URL(ae.url),ce=ee?.basePath??"/Groups",he=ue.pathname;if(he.startsWith(ce))he=he.substring(ce.length);let fe=he.match(/^\/([^/]+)$/)?.[1],Ce=ae.method;try{if(fe)switch(Ce){case"GET":return await be(ae,ce,fe);case"PUT":return await Ie(ae,ce,fe);case"PATCH":return await Oe(ae,ce,fe);case"DELETE":return await Ee(fe);default:return Re(405,"Method not allowed")}else if(he===""||he==="/")switch(Ce){case"GET":return await ge(ae,ce);case"POST":return await me(ae,ce);default:return Re(405,"Method not allowed")}return Re(404,"Resource not found")}catch(Ae){if(Ae instanceof Ot)return yr(Ae);if(Ae instanceof cn)return Re(400,Ae.message,"invalidValue");if(T(Ae))return Re(409,Ae.message,"uniqueness");return k.error("Groups inbound handler error",{"ion.operation":"scim.groups.handler","ion.outcome":"failure"},Ae),Re(500,Ae instanceof Error?Ae.message:"Internal server error")}},ge=async(ae,ee)=>{let oe=new URL(ae.url),ue=oe.searchParams.get("startIndex"),ce=oe.searchParams.get("count"),he=ue!=null?parseInt(ue,10):void 0,we=ce!=null?parseInt(ce,10):void 0,fe=he!=null&&!Number.isNaN(he)?Math.max(0,he-1):0,Ce=we!=null&&!Number.isNaN(we)?we:void 0,Ae=oe.searchParams.get("filter"),Me=kr(Ae);if(Me!==void 0){await J();let Te=await Xs(Se,V,Me,De),Ke=Te?[ve(Te,ae,ee)]:[];return ft(Ke,{totalResults:Ke.length,startIndex:1,itemsPerPage:Ke.length})}if(Hs(Ae)?.requestable===!1)return ft([],{totalResults:0,startIndex:1,itemsPerPage:0});let Qe={requestable:!0};if(Y)await Promise.all([...Y.groups.list().filter((Te)=>Te.requestable===!0).map((Te)=>({entity:Te,kind:"group"})),...Y.roles.list().filter((Te)=>Te.requestable===!0).map((Te)=>({entity:Te,kind:"role"})),...Y.permissions.list().filter((Te)=>Te.requestable===!0).map((Te)=>({entity:Te,kind:"permission"}))].map((Te)=>B(Te,!1)));await J();let Ve=await Zs(Se,V,{start:fe,limit:Ce,filter:Qe},De);return ft(Ve.resources.map((Te)=>ve(Te,ae,ee)),{totalResults:Ve.total,startIndex:fe+1,itemsPerPage:Ve.count})},be=async(ae,ee,oe)=>{let ue=M(oe);if(ue&&ue.entity.requestable!==!0)return re(oe);if(ue)await B(ue,!1);await J(oe);let ce=await zt(Se,V,oe,De);if(!de(ce))return re(oe);return Xe(ve(ce,ae,ee))},me=async(ae,ee)=>{let oe=await ae.json(),ue=await bt(y.group,oe);if(ue.issues)return k.error("Group creation validation failed",{"ion.operation":"scim.group.create","ion.outcome":"failure",validationIssues:ue.issues}),Re(400,`Request validation failed: ${ue.issues.map((Ve)=>Ve.message).join("; ")}`,"invalidValue");let ce=ue.value;if(!ce.displayName)return Re(400,"displayName is required","invalidValue");if(ce[e]?.requestable===!1)return Re(400,"SCIM may create only requestable entitlements; non-requestable definitions are App-owned.","invalidValue");if(ce[e]={...ce[e],requestable:!0},!H)return Re(501,"Group creation is not supported: this application declares its catalog in code (authz.catalog) and wires no AccessCatalogStore for SCIM-authored definitions.","invalidValue");let we=_t(ce),fe=rn();if(M(fe))throw new m(`id "${fe}" is reserved by the code catalog`,"unique_violation","id");let Ce=Vn(ce),Ae=on(new Map,nn(ce.members,we,fe,Ce,ce[e]?.assignableSubjectTypes)),Me;await jt(ke,async()=>{Me=await zn(Se,ce,fe)},Ae,{oaa:()=>$n(W,Me,we)});let ze=await Pt(Se,V,we,fe),Qe=ve(xt(Me,we,ze),ae,ee);return Xe(Qe,201,Qe.meta?.location)},Ie=async(ae,ee,oe)=>{let ue=await ae.json(),ce=await bt(y.group,ue);if(ce.issues)return k.error("Group replacement validation failed",{"ion.operation":"scim.group.replace","ion.outcome":"failure",validationIssues:ce.issues}),Re(400,`Request validation failed: ${ce.issues.map((Ke)=>Ke.message).join("; ")}`,"invalidValue");let he=ce.value,we=_t(he),fe=M(oe);if(fe&&fe.entity.requestable!==!0)return re(oe);if(fe){if(await B(fe,!0),Ws(he,fe))return F(oe,"replaced")}let Ce=await zt(Se,V,oe);if(!de(Ce))return re(oe);if(!fe&&Ce[e]?.source==="code"&&Vs(he,Ce))return F(oe,"replaced");let Ae=fe?.kind??we,Me=fe?Jn(fe.entity):Vn(he),ze=V?(await V.listByTarget(Ae,oe)).items:[],Qe=on(qs(ze),nn(he.members,Ae,oe,Me,fe?.entity.assignableSubjectTypes??Ce[e]?.assignableSubjectTypes??he[e]?.assignableSubjectTypes)),Ve;await jt(ke,async()=>{Ve=await zn(Se,he,oe,fe?.entity)},Qe,{oaa:()=>$n(W,Ve,Ae)});let Te=await Pt(Se,V,Ae,oe);return Xe(ve(xt(Ve,Ae,Te),ae,ee))},Oe=async(ae,ee,oe)=>{let ue=M(oe);if(ue&&ue.entity.requestable!==!0)return re(oe);if(ue)await B(ue,!0);let ce=await zt(Se,V,oe);if(!de(ce))return re(oe);let he=await ae.json();if((ue!==void 0||ce[e]?.source==="code")&&(he.Operations??[]).some((Ue)=>!pe(Ue)))return F(oe,"patched");let fe={...ce};for(let Ue of he.Operations??[])if(Ue.op==="replace"&&Ue.path&&Ue.value!==void 0){if(Ue.path==="displayName")fe.displayName=Ue.value;else if(Ue.path===`${e}.requestable`)fe[e]={...fe[e],requestable:Boolean(Ue.value)};else if(Ue.path===`${e}.description`)fe[e]={...fe[e],description:String(Ue.value)};else if(Ue.path===`${e}.riskLevel`)fe[e]={...fe[e],riskLevel:String(Ue.value)};else if(Ue.path===`${e}.providerId`)fe[e]={...fe[e],providerId:String(Ue.value)};else if(Ue.path===`${e}.requestUrl`)fe[e]={...fe[e],requestUrl:String(Ue.value)};else if(Ue.path===`${e}.attributes`&&typeof Ue.value==="object"&&Ue.value!==null&&!Array.isArray(Ue.value))fe[e]={...fe[e],attributes:Ue.value};else if(Ue.path.startsWith(`${e}.attributes.`)){let qe=Ue.path.slice(`${e}.attributes.`.length);fe[e]={...fe[e],attributes:{...fe[e]?.attributes,[qe]:Ue.value}}}}else if(Ue.op==="add"&&Ue.path==="members"&&Ue.value!==void 0){let qe=Ue.value;fe.members=[...fe.members??[],...qe]}else if(Ue.op==="remove"&&Ue.path?.startsWith("members[")){let qe=Ue.path.match(/members\[value eq "([^"]+)"\]/);if(qe)fe.members=(fe.members??[]).filter((St)=>St.value!==qe[1])}else if(Ue.op==="remove"&&Ue.path?.startsWith(`${e}.attributes.`)){let qe=Ue.path.slice(`${e}.attributes.`.length),St={...fe[e]?.attributes};delete St[qe],fe[e]={...fe[e],attributes:St}}let Ce=await bt(y.group,fe);if(Ce.issues)return k.error("Group patch validation failed",{"ion.operation":"scim.group.patch","ion.outcome":"failure",validationIssues:Ce.issues}),Re(400,`Request validation failed: ${Ce.issues.map((Ue)=>Ue.message).join("; ")}`,"invalidValue");let Ae=ue?.kind??_t(fe),Me=ue?Jn(ue.entity):Vn(fe),ze=ue?.entity.assignableSubjectTypes??ce[e]?.assignableSubjectTypes??fe[e]?.assignableSubjectTypes,Qe=on(nn(ce.members,Ae,oe,Me,ze),nn(fe.members,Ae,oe,Me,ze)),Ve,Te=!ue||(he.Operations??[]).some((Ue)=>!ne(Ue));await jt(ke,async()=>{if(Te)Ve=await zn(Se,fe,oe,ue?.entity)},Qe,Te?{oaa:()=>$n(W,Ve,Ae)}:void 0);let Ke=await zt(Se,V,oe);return Xe(ve(Ke,ae,ee))},Ee=async(ae)=>{let ee=M(ae);if(ee&&ee.entity.requestable!==!0)return re(ae);if(ee)await B(ee,!0);let oe=await zt(Se,V,ae);if(!de(oe))return re(ae);let ue=oe[e];if((ee||ue?.source==="code")&&ue?.deprecated!==!0)return Re(403,`Code-owned entitlement "${ae}" can be deleted only after it is marked deprecated.`,"mutability");let ce=_t(oe);if(V){let he=await V.listByTarget(ce,ae),we=[];for(let fe of he.items)await Bt(ke,fe,we);await sn(ke,we)}return await Qs(Se,ae),new Response(null,{status:204})};lt={handler:ie}}let Ze,yt,ct;if(ye.userStore){let{userStore:Se,inboundUsers:ve}=ye,M=(ee)=>ee?.find((oe)=>oe.primary)?.value||ee?.[0]?.value,B=async(ee)=>{if(ve?.mapBaseUserToScim)return await ve.mapBaseUserToScim(ee);return On(ee)},J=async(ee,oe,ue)=>{let ce=await B(ee),he=ce.id??ee.id;return{...ce,id:he,meta:{...ce.meta,resourceType:"User",location:he?He(oe,`${ue}/${encodeURIComponent(he)}`):void 0}}},F=async(ee,oe)=>{if(ve?.mapValidatedScimToBaseUser)return await ve.mapValidatedScimToBaseUser(ee,oe);let ue=new Date,ce=M(ee.emails),he=ee.name?.formatted||[ee.name?.givenName,ee.name?.middleName,ee.name?.familyName].filter(Boolean).join(" ").trim()||ee.displayName,we=ee.id||oe.existing?.id||rn(),fe=ee.userName||ce||oe.existing?.userName||we,Ce=he||ee.displayName||oe.existing?.name||fe,Ae=Object.fromEntries(Object.entries(ee).filter(([Ke,Ue])=>Ke.startsWith("urn:")&&Ke!==Jt&&Ke!==s&&Ue!==void 0)),Me=ee[s],ze=r(Me?.attributes??{},h),Qe=Me?.ecid!==void 0&&Me.ecid!==null?w(Me.ecid):oe.existing?.ecid,Ve=Me?.accountClass??oe.existing?.accountClass,Te=oe.existing?.sso;return{...oe.existing??{},id:we,userName:fe,name:Ce,email:ce||oe.existing?.email||fe,avatar:ee.profileUrl,sso:{...Te??{},profile:{...Te?.profile??{},sub:we,iss:Te?.profile.iss??"iam-provisioned",aud:Te?.profile.aud??"iam-provisioned",exp:Te?.profile.exp??Math.floor(Date.now()/1000)+3600,iat:Te?.profile.iat??Math.floor(Date.now()/1000),email:ce||oe.existing?.email||fe,email_verified:!0,name:Ce,preferred_username:fe},tenant:Te?.tenant??{id:"iam-provisioned",name:"IAM Provisioned"},scope:Te?.scope??"openid profile email",tokenType:Te?.tokenType??"Bearer",expires:Te?.expires??new Date(Date.now()+3600000)},externalId:ee.externalId,ecid:Qe,accountClass:Ve,displayName:ee.displayName,scimName:ee.name,emails:ee.emails,nickName:ee.nickName,title:ee.title,preferredLanguage:ee.preferredLanguage,locale:ee.locale,timezone:ee.timezone,active:ee.active,phoneNumbers:ee.phoneNumbers,ims:ee.ims,photos:ee.photos,addresses:ee.addresses,groups:ee.groups,entitlements:ee.entitlements,roles:ee.roles,x509Certificates:ee.x509Certificates,scimEnterprise:ee[Jt],scimSchemaExtensions:Object.keys(Ae).length>0?Ae:void 0,createdAt:oe.existing?.createdAt??(ee.meta?.created?new Date(ee.meta.created):ue),updatedAt:ee.meta?.lastModified?new Date(ee.meta.lastModified):ue,userType:ee.userType,...ze}},ne=(ee,oe,ue)=>{ee[oe]=ue},pe=(ee,oe,ue)=>{let ce=ee[oe];if(Array.isArray(ce)){ee[oe]=[...ce,...Array.isArray(ue)?ue:[ue]];return}if(ce&&typeof ce==="object"&&!Array.isArray(ce)&&ue&&typeof ue==="object"&&!Array.isArray(ue)){ee[oe]={...ce,...ue};return}ee[oe]=ue},de=(ee,oe,ue)=>{let ce=oe.match(/^(urn:.*:(?:User|Group))(?::(.+))?$/),he=ce?[ce[1],...ce[2]?.split(":")??[]]:oe.split("."),we=ee;for(let Ce of he.slice(0,-1)){let Ae=we[Ce];if(Ae===void 0){if(!ue)return null;we[Ce]={}}else if(Ae===null||typeof Ae!=="object"||Array.isArray(Ae)){if(!ue)return null;we[Ce]={}}we=we[Ce]}let fe=he.at(-1);if(!fe)return null;return{parent:we,key:fe}},re=(ee,oe)=>{let ue=oe.op.toLowerCase();if(!oe.path){if(ue!=="remove"&&oe.value&&typeof oe.value==="object"&&!Array.isArray(oe.value))Object.assign(ee,oe.value);return}let ce=oe.path.match(/^([A-Za-z0-9]+)\[value eq "([^"]+)"\]$/);if(ce&&ue==="remove"){let[,we,fe]=ce,Ce=ee[we];if(Array.isArray(Ce))ee[we]=Ce.filter((Ae)=>!(Ae&&typeof Ae==="object"&&("value"in Ae)&&Ae.value===fe));return}let he=de(ee,oe.path,ue!=="remove");if(!he)return;if(ue==="remove"){delete he.parent[he.key];return}if(ue==="add"){pe(he.parent,he.key,oe.value);return}ne(he.parent,he.key,oe.value)},ie=async(ee,oe)=>{if(!await nt(ee))return Re(401,"Authorization required");let ce=new URL(ee.url),he=oe?.basePath??"/Users",we=ce.pathname;if(we.startsWith(he))we=we.substring(he.length);let Ce=we.match(/^\/([^/]+)$/)?.[1],Ae=ee.method;try{if(Ce)switch(Ae){case"GET":return await be(ee,he,Ce);case"PUT":return await Oe(ee,he,Ce);case"PATCH":return await Ee(ee,he,Ce);case"DELETE":return await ae(Ce);default:return Re(405,"Method not allowed")}else if(we===""||we==="/")switch(Ae){case"GET":return await ge(ee,he);case"POST":return await Ie(ee,he);default:return Re(405,"Method not allowed")}return Re(404,"Resource not found")}catch(Me){if(Me instanceof Ot)return yr(Me);if(T(Me))return Re(409,Me.message,"uniqueness");return k.error("Users inbound handler error",{"ion.operation":"scim.users.handler","ion.outcome":"failure"},Me),Re(500,Me instanceof Error?Me.message:"Internal server error")}},ge=async(ee,oe)=>{let ue=new URL(ee.url),ce=ue.searchParams.get("startIndex"),he=ue.searchParams.get("count"),we=ce!=null?parseInt(ce,10):void 0,fe=he!=null?parseInt(he,10):void 0,Ce=we!=null&&!Number.isNaN(we)?Math.max(0,we-1):0,Ae=fe!=null&&!Number.isNaN(fe)?fe:void 0,Me=kr(ue.searchParams.get("filter"));if(Me!==void 0){let Ve=await Se.lookup({externalId:Me}),Te=Ve?[await J(Ve,ee,oe)]:[];return ft(Te,{totalResults:Te.length,startIndex:1,itemsPerPage:Te.length})}let ze=await Se.list({start:Ce,limit:Ae}),Qe=await Promise.all(ze.items.map((Ve)=>J(Ve,ee,oe)));return ft(Qe,{totalResults:ze.total,startIndex:Ce+1,itemsPerPage:ze.count})},be=async(ee,oe,ue)=>{let ce=await Se.get(ue);if(!ce)return Re(404,`User ${ue} not found`,"invalidValue");return Xe(await J(ce,ee,oe))},me=async(ee,oe)=>{let ue=ke.accessIndex;if(!ue?.setSubjectDisabled||!oe.id)return;let ce=ee?ee.active??!0:!0,he=oe.active??!0;if(ee&&ce===he)return;if(!ee&&he)return;await ue.setSubjectDisabled(oe.id,"user",!he)},Ie=async(ee,oe)=>{let ue=await ee.json(),ce=await bt(y.user,ue);if(ce.issues)return k.error("User creation validation failed",{"ion.operation":"scim.user.create","ion.outcome":"failure",validationIssues:ce.issues}),Re(400,`Request validation failed: ${ce.issues.map((Ce)=>Ce.message).join("; ")}`,"invalidValue");let he=ce.value;if(!he.userName&&!he.emails?.[0]?.value)return Re(400,"userName or email is required","invalidValue");let we=await F(he,{mode:"create"});await jt(ke,async()=>{await Se.upsert(we),await me(void 0,we)},Wn(void 0,we),{oaa:async()=>{await qn(W,we)},delta:async()=>{await ke.iamDelta?.onUserUpsert(we)}});let fe=await J(we,ee,oe);return Xe(fe,201,fe.meta?.location)},Oe=async(ee,oe,ue)=>{let ce=await Se.get(ue);if(!ce)return Re(404,`User ${ue} not found`,"invalidValue");let he=await ee.json(),we=await bt(y.user,he);if(we.issues)return k.error("User replacement validation failed",{"ion.operation":"scim.user.replace","ion.outcome":"failure",validationIssues:we.issues}),Re(400,`Request validation failed: ${we.issues.map((Ae)=>Ae.message).join("; ")}`,"invalidValue");let fe=we.value,Ce=await F({...fe,id:ue},{existing:ce,mode:"replace"});return Ce.createdAt=ce.createdAt,Ce.updatedAt=new Date,await jt(ke,async()=>{await Se.upsert(Ce),await me(ce,Ce)},Wn(ce,Ce),{oaa:async()=>{await qn(W,Ce)},delta:async()=>{await Sr(ke.iamDelta,ce,Ce)}}),Xe(await J(Ce,ee,oe))},Ee=async(ee,oe,ue)=>{let ce=await Se.get(ue);if(!ce)return Re(404,`User ${ue} not found`,"invalidValue");let we=(await ee.json()).Operations??[],Ce={...await B(ce)};for(let ze of we)re(Ce,ze);let Ae=await bt(y.user,Ce);if(Ae.issues)return k.error("User patch validation failed",{"ion.operation":"scim.user.patch","ion.outcome":"failure",validationIssues:Ae.issues}),Re(400,`Request validation failed: ${Ae.issues.map((ze)=>ze.message).join("; ")}`,"invalidValue");let Me=await F(Ae.value,{existing:ce,mode:"patch"});return Me.updatedAt=new Date,await jt(ke,async()=>{await Se.upsert(Me),await me(ce,Me)},Wn(ce,Me),{oaa:async()=>{await qn(W,Me)},delta:async()=>{await Sr(ke.iamDelta,ce,Me)}}),Xe(await J(Me,ee,oe))},ae=async(ee)=>{let oe=await Se.get(ee);if(!oe)return Re(404,`User ${ee} not found`,"invalidValue");if(V){let ue=[];for await(let ce of i((he,we)=>V.listBySubject(ee,"user",{start:he,limit:we})))await Bt(ke,ce,ue);await sn(ke,ue)}if(await Se.delete(ee),await ke.accessIndex?.setSubjectDisabled?.(ee,"user",!1),oe.externalId&&ke.iamDelta?.isReady())await Ct(ke,"iam.delta.egress","IAM delta user delete failed after SCIM write; full aggregation will reconcile",()=>ke.iamDelta?.onUserDelete(oe.externalId)??Promise.resolve(),{id:ee,kind:"user"});else if(ke.iamDelta?.isReady())ke.log?.warn("IAM delta: deleted User has no externalId; destination delete skipped",{"ion.operation":"iam.delta.delete","ion.outcome":"skipped",id:ee,kind:"user"});if(ke.authz.oaa.isReady())await Ct(ke,"authz.oaa.delete","OAA incremental user delete failed; full sync will reconcile",()=>ke.authz.oaa.deleteUser(ee),{id:ee,kind:"user"});return new Response(null,{status:204})};Ze={handler:ie}}let rt=async(Se,ve)=>{if(!V)return;let M=[];for await(let B of i((J,F)=>V.listBySubject(Se,ve,{start:J,limit:F})))await Bt(ke,B,M);await sn(ke,M)};if(ye.workloadIdentityStore){let{workloadIdentityStore:Se,inboundWorkloads:ve}=ye;yt=wr({resourceType:"Workload",subjectType:"workload",store:Se,validator:y.workload??q,toScim:async(M)=>await(ve?.mapBaseWorkloadToScim?.(M)??Dn(M)),fromScim:async(M,B)=>{if(ve?.mapValidatedScimToBaseWorkload)return ve.mapValidatedScimToBaseWorkload(M,B);let J=B.existing,F=M,ne=F.id?.trim()||J?.id||rn(),pe=r(F.attributes??{},b);return{...J??{},id:ne,externalId:F.externalId??J?.externalId,clientId:F.userName??J?.clientId??ne,displayName:F.displayName??J?.displayName,description:F.description??J?.description,active:F.active??J?.active??!0,providerId:J?.providerId,requestUrl:J?.requestUrl,...pe}},projections:[{channel:"oaa",upsert:async(M)=>{if(W.oaa.isReady())await W.oaa.pushWorkload(M)},delete:async(M)=>{if(W.oaa.isReady())await W.oaa.deleteWorkload(M.id)}},{channel:"delta",upsert:async(M,B)=>{let J=B?.externalId??B?.id,F=M.externalId??M.id;if(J&&J!==F)await xe?.onWorkloadDelete(J);await xe?.onWorkloadUpsert(M)},delete:async(M)=>{await xe?.onWorkloadDelete(M.externalId??M.id)}}]},{validateAuth:nt,accessStore:V,accessIndex:G,revokeSubjectAccess:rt,log:k})}if(ye.customerStore){let{customerStore:Se,inboundCustomers:ve}=ye;ct=wr({resourceType:"Customer",subjectType:"customer",store:Se,validator:y.customer??K,toScim:async(M)=>await(ve?.mapBaseCustomerToScim?.(M)??Ln(M)),fromScim:async(M,B)=>{if(ve?.mapValidatedScimToBaseCustomer)return ve.mapValidatedScimToBaseCustomer(M,B);let J=B.existing,F=M,ne=F.id?.trim()||J?.id||rn(),pe=r(F.attributes??{},S),de=F.emails?.find((re)=>re.primary)?.value??F.emails?.[0]?.value;return{...J??{},id:ne,externalId:F.externalId??J?.externalId??ne,userName:F.userName??J?.userName??ne,name:F.displayName??J?.name??F.userName??ne,email:de??J?.email??"",displayName:F.displayName??J?.displayName,emails:F.emails??J?.emails,active:F.active??J?.active??!0,providerId:J?.providerId,requestUrl:J?.requestUrl,...pe}},projections:[{channel:"oaa",upsert:async(M)=>{if(W.oaa.isReady())await W.oaa.pushCustomer(M)},delete:async(M)=>{if(W.oaa.isReady()&&M.id)await W.oaa.deleteCustomer(M.id)}},{channel:"delta",upsert:async(M,B)=>{let J=B?.externalId??B?.id,F=M.externalId??M.id;if(J&&J!==F)await xe?.onCustomerDelete(J);await xe?.onCustomerUpsert(M)},delete:async(M)=>{let B=M.externalId??M.id;if(B)await xe?.onCustomerDelete(B)}}]},{validateAuth:nt,accessStore:V,accessIndex:G,revokeSubjectAccess:rt,log:k})}async function ht(Se,ve){Je();let M=new URL(Se.url).pathname,B=ut(ve?.usersUrl??ye.usersUrl??"/api/iam/Users")??"/api/iam/Users",J=ut(ve?.groupsUrl??ye.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",F=ut(ve?.workloadsUrl??ye.workloadsUrl??"/api/iam/Workloads")??"/api/iam/Workloads",ne=ut(ve?.customersUrl??ye.customersUrl??"/api/iam/Customers")??"/api/iam/Customers",pe=`${br(B,J,F,ne)??"/api/iam"}/AccessRequests`,de=await gt(Se,ve);if(de)return de;let re=(ie)=>M===ie||M.startsWith(`${ie}/`);if(re(B)){if(!_e)return Re(404,"SCIM Users endpoint is disabled by RemoteConfig");if(!Ze)return Re(501,"SCIM Users endpoint is enabled by RemoteConfig but no user store capability is wired by the application.");return Ze.handler(Se,{basePath:B})}if(re(J)){if(!Ne)return Re(404,"SCIM Groups endpoint is disabled by RemoteConfig");if(!lt)return Re(501,"SCIM Groups endpoint is enabled by RemoteConfig but no AccessCatalogStore capability is wired by the application.");return lt.handler(Se,{basePath:J})}if(re(F)){if(!$e)return Re(404,"SCIM Workloads endpoint is disabled by RemoteConfig");if(!yt)return Re(501,"SCIM Workloads endpoint is enabled by RemoteConfig but no workload identity store capability is wired by the application.");return yt.handler(Se,{basePath:F})}if(re(ne)){if(!tt)return Re(404,"SCIM Customers endpoint is disabled by RemoteConfig");if(!ct)return Re(501,"SCIM Customers endpoint is enabled by RemoteConfig but no customer store capability is wired by the application.");return ct.handler(Se,{basePath:ne})}if(re(pe)){if(!ye.accessRequests)return Re(404,"AccessRequests endpoint is not configured");if(Se.method!=="POST")return Re(405,"Method not allowed");if(!await nt(Se))return Re(401,"Authorization required");let ie;try{ie=await Se.json()}catch{return Re(400,"Request body must be valid JSON","invalidSyntax")}if(typeof ie.subject!=="string"||!ie.subject||typeof ie.target!=="string"||!ie.target||ie.subjectType!=="user"&&ie.subjectType!=="workload"&&ie.subjectType!=="customer"||ie.targetType!=="group"&&ie.targetType!=="role"&&ie.targetType!=="permission")return Re(400,"subject, subjectType, targetType, and target are required","invalidValue");let ge=await ye.accessRequests.create({subject:ie.subject,subjectType:ie.subjectType,targetType:ie.targetType,target:ie.target,justification:typeof ie.justification==="string"?ie.justification:void 0});return Xe(ge,201,ge.trackingUrl)}return Re(404,"Resource not found")}return{...ye,users:Nn(ye.users),workloads:Nn(ye.workloads),customers:Nn(ye.customers),groups:{enabled:Ne},createUser:It,getBaseUrl:Et,groups_outbound:at,groups_inbound:lt,users_inbound:Ze,workloads_inbound:yt,customers_inbound:ct,handler:ht,delta:xe}}function Hn(y,k){let R=new TextEncoder().encode(y),W=typeof k==="string"?new TextEncoder().encode(k):k,V=new Uint8Array(R.length+1+W.length);return V.set(R,0),V[R.length]=46,V.set(W,R.length+1),V}function ii(y){let k=y.replace(/-/g,"+").replace(/_/g,"/"),R=k.length%4===0?"":"=".repeat(4-k.length%4),W=atob(k+R),V=new Uint8Array(W.length);for(let G=0;G<W.length;G++)V[G]=W.charCodeAt(G);return V}function oi(y){let k="";for(let R of y)k+=String.fromCharCode(R);return btoa(k).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function Rr(y){let k=JSON.parse(y);if(!k||typeof k!=="object"||!Array.isArray(k.keys))throw Error("Invalid JWKS: expected { keys: [...] }");return k}function ai(y){return JSON.stringify(y)}async function ci(y){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:y.x},{name:"Ed25519"},!0,["verify"])}async function ui(y){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:y.x,d:y.d},{name:"Ed25519"},!0,["sign"])}async function di(y){let R=(typeof y.jwks==="string"?Rr(y.jwks):y.jwks).keys.find((W)=>W.kid===y.kid&&W.kty==="OKP"&&W.crv==="Ed25519");if(!R?.x)return!1;try{let W=await ci(R),V=Hn(y.requestId,y.rawBody),G=ii(y.signatureB64Url);return crypto.subtle.verify({name:"Ed25519"},W,G,V)}catch{return!1}}async function li(y){let k=await ui(y.privateKeyJwk),R=Hn(y.requestId,y.rawBody),W=await crypto.subtle.sign({name:"Ed25519"},k,R);return oi(new Uint8Array(W))}async function pi(y){let k=await crypto.subtle.generateKey({name:"Ed25519"},!0,["sign","verify"]),R=await crypto.subtle.exportKey("jwk",k.privateKey),V=(await crypto.subtle.exportKey("jwk",k.publicKey)).x,G=R.d;if(!V||!G)throw Error("Failed to export Ed25519 key material (missing x/d)");return{privateJwk:{kty:"OKP",crv:"Ed25519",x:V,d:G,kid:y,alg:"EdDSA",use:"sig"},publicJwks:{keys:[{kty:"OKP",crv:"Ed25519",x:V,kid:y,alg:"EdDSA",use:"sig"}]}}}var Ft={jwksTtlSeconds:{min:60,max:86400,default:600},jwksMaxEntries:{min:16,max:4096,default:256},sessionReadTtlSeconds:{min:1,max:300,default:30},sessionReadMaxEntries:{min:16,max:65536,default:1024}};function un(y,k){if(typeof y!=="number"||!Number.isFinite(y))return k.default;let R=Math.floor(y);if(R<k.min)return k.min;if(R>k.max)return k.max;return R}function vr(y){return{ttlMs:un(y?.ttlSeconds,Ft.jwksTtlSeconds)*1000,maxEntries:un(y?.maxEntries,Ft.jwksMaxEntries)}}function Ir(y){let k=y?.read;return{read:{enabled:k?.enabled===!0,ttlMs:un(k?.ttlSeconds,Ft.sessionReadTtlSeconds)*1000,maxEntries:un(k?.maxEntries,Ft.sessionReadMaxEntries)}}}function mi(y){return{jwks:vr(y?.jwks),session:Ir(y?.session)}}function fi(y){let k={};if(!y)return k;let R=y.split(";");for(let W of R){let V=W.trim();if(!V)continue;let G=V.indexOf("=");if(G===-1)continue;k[V.slice(0,G).trim()]=V.slice(G+1).trim()}return k}function Ar(y){if(!y.expiresAt)return!1;let k=y.expiresAt instanceof Date?y.expiresAt:new Date(y.expiresAt);return!Number.isNaN(k.getTime())&&Date.now()>k.getTime()}function gi(y){if(!y||typeof y!=="object"||Array.isArray(y))return;let{access_token:k,id_token:R,refresh_token:W,tokens:V,...G}=y;return G}function it(y,k){let R=y[k];return typeof R==="string"?R:""}function yi(y,k){let R=y.exp;if(typeof R==="number")return new Date(R*1000);if(typeof R==="string"&&R.trim()){let W=Number(R);if(!Number.isNaN(W))return new Date(W*1000)}if(k instanceof Date)return k;if(k){let W=new Date(k);if(!Number.isNaN(W.getTime()))return W}return new Date}function hi(y){let k=y.claims;if(!k?.sub||typeof k.sub!=="string")return;let R=yi(k,y.expiresAt);if(y.authType==="sso")return{id:k.sub,userName:it(k,"preferred_username"),name:it(k,"name"),email:it(k,"email"),avatar:it(k,"picture")||void 0,sso:{profile:k,tenant:{id:it(k,"idp")||it(k,"iss"),name:it(k,"iss")},tokenType:"Bearer",expires:R}};return{id:k.sub,userName:it(k,"preferred_username"),name:it(k,"name"),email:it(k,"email"),avatar:it(k,"picture")||void 0,userType:"customer",ciam:{profile:k,scope:"openid profile email",tokenType:"Bearer",expires:R}}}function Si(y){if(y.authType!=="sso"&&y.authType!=="ciam")return;if(Ar(y))return;return{sid:y.sid,authType:y.authType,tenantId:typeof y.tenantId==="string"?y.tenantId:void 0,sub:y.sub,expiresAt:y.expiresAt,createdAt:y.createdAt,claims:gi(y.claims)}}function ki(y,k){if(!y.endsWith(".session"))return!1;if(!k||k.length===0)return!0;return k.some((R)=>y===`${R}.session`)}function wi(y){if(y===void 0)return;let k=(Array.isArray(y)?y:[y]).map((R)=>R.trim()).filter((R)=>R.length>0);return k.length>0?k:void 0}async function Tr(y,k,R){return(await Pr(y,k,R)).map(Si).filter((V)=>Boolean(V))}async function Pr(y,k,R){let W=fi(y.headers.get("cookie")),V=wi(R?.cookiesPrefix),G=[],H=new Set;for(let[Y,Q]of Object.entries(W)){if(!ki(Y,V)||!Q)continue;if(H.has(Q))continue;H.add(Q);let X=await k.get(Q);if(!X)continue;if(X.authType!=="sso"&&X.authType!=="ciam")continue;if(Ar(X))continue;G.push(X)}return G}async function bi(y,k,R){return(await Tr(y,k,R)).map(hi).filter((V)=>Boolean(V))}var Ci="@ionite/core",Ri=a(l(Ci));async function vi(y,k){let R=await kt({idToken:y,jwksUri:k.jwksUri,issuer:k.issuer,audience:k.audience}),W=await Ri.validate(R);if(W.issues)throw Error(`ID token claims validation failed: ${W.issues.map((H)=>H.message).join("; ")}`);let V=W.value;if(V===void 0)throw Error("ID token claims missing");return P(V)}function Ye(y){return Date.now()-y}function Fn(y){if(y instanceof Error)return{"error.name":y.name,"error.message":y.message};return{"error.name":typeof y,"error.message":String(y)}}function dn(y,k){if(!y)return{};try{let R=new URL(y);return{[`${k}.origin`]:R.origin,[`${k}.path`]:R.pathname}}catch{return{[`${k}.path`]:y.startsWith("/")?y:`/${y}`}}}function ln(y,k=5){if(!Array.isArray(y))return[String(y)];return y.slice(0,k).map((R)=>{if(!R||typeof R!=="object")return String(R);let W=R,V=Array.isArray(W.path)?W.path.join("."):String(W.path??""),G=typeof W.message==="string"?W.message:String(W.message??"validation failed");return V?`${V}: ${G}`:G})}function Ii(y){if(!y||typeof y!=="object")return{};let k=y;return{oidc_error:typeof k.error==="string"?k.error:void 0,oidc_error_description:typeof k.error_description==="string"?k.error_description:void 0,oidc_error_uri:typeof k.error_uri==="string"?k.error_uri:void 0}}function Ai(y,k={}){let R=typeof y==="string"?y:y?.headers.get("cookie")??void 0;if(!R)return[];let V=`${k.cookiePrefix??"ion.sso"}.`,G=new Set;for(let H of Object.keys(Pi(R))){if(!H.startsWith(V))continue;let Y=H.slice(V.length),Q=Y.lastIndexOf(".");if(Q<=0)continue;let X=Y.slice(0,Q).trim();if(X)G.add(X)}return Array.from(G)}function Ti(y,k,R,W,V){if(!R&&!W)return;let G=new WeakMap,H=new Map,Y={...R,...W},Q=!!(Y.authority&&Y.tokenUrl&&Y.authorizationUrl&&Y.clientId&&Y.redirectUri&&Y.scope),X={...Y,authority:Q?t(Y.authority,"Missing 'authority' from SSO Config"):Y.authority,tokenUrl:Q?t(Y.tokenUrl,"Missing 'tokenUrl' from SSO Config"):Y.tokenUrl,authorizationUrl:Q?t(Y.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"):Y.authorizationUrl,clientId:Q?t(Y.clientId,"Missing 'clientId' from SSO Config"):Y.clientId,redirectUri:Q?t(Y.redirectUri,"Missing 'redirectUri' from SSO Config"):Y.redirectUri,scope:Q?t(Y.scope,"Missing 'scope' from SSO Config"):Y.scope,responseType:Y.responseType??"code",cookiesSecure:Y.cookiesSecure!==void 0?Y.cookiesSecure:!0,cookiesSameSite:Y.cookiesSameSite!==void 0?Y.cookiesSameSite:"Strict",cookiesPrefix:Y.cookiesPrefix??(Y.clientId?`ion.sso.${Y.clientId}`:"ion.sso"),cookiesPath:Y.cookiesPath??"/"},Pe=Math.min(600,Math.max(0,Math.floor(Number(X.rotationGraceSeconds??60))||0))*1000,xe=Math.floor(Number(X.sessionWindowSeconds??86400)),je=Number.isFinite(xe)&&xe>=1?xe:86400;function De(){let M=[];if(!X.authority)M.push("authority");if(!X.tokenUrl)M.push("tokenUrl");if(!X.authorizationUrl)M.push("authorizationUrl");if(!X.clientId)M.push("clientId");if(!X.redirectUri)M.push("redirectUri");if(!X.scope)M.push("scope");if(M.length>0)throw Error(`Missing OIDC configuration fields: ${M.join(", ")}. OIDC configuration is required for SSO operations. Please provide these fields either in your vault configuration or in the SSO config when initializing ionite.`)}async function We(M){if(!X)throw Error("ionite SSO Manager not initialized");let B=G.get(M);if(B)return B;let J=ke(M);return G.set(M,J),J}async function ke(M){try{let{tokens:B,session:J,refreshedUser:F}=await Ze(M);if(!B)return{status:"unauthenticated"};if(F)return{status:"authenticated",value:F};if(J?.claims)return{status:"authenticated",value:Je(J.claims,B,gt(J.expiresAt))};return{status:"unauthenticated"}}catch(B){if(xr(B))return{status:"unauthenticated"};return k.error("Error parsing user from cookies",{"ion.operation":"cookie.parse","ion.outcome":"degraded"},B),{status:"degraded",error:B instanceof Error?B:void 0}}}async function Le(M){let B=await We(M);return B.status==="authenticated"?B.value:void 0}async function ye(M){if(!X)throw Error("ionite SSO Manager not initialized");De();let B=t(X.redirectUri,"Missing 'redirectUri' from SSO Config"),J=t(X.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"),F=t(X.clientId,"Missing 'clientId' from SSO Config"),ne=t(X.scope,"Missing 'scope' from SSO Config"),pe=X.cookiesSecure?M.url.replace(/^http:\/\//,"https://"):M.url,de=st(),re=st(64),ie=st(),ge=B;try{new URL(ge)}catch{if(pe)try{let Ee=new URL(pe),ae=ge.startsWith("//")?ge.slice(1):ge.startsWith("/")?ge:`/${ge}`;ge=new URL(ae,Ee.origin).toString()}catch{try{let Ee=new URL(J),ae=ge.startsWith("//")?ge.slice(1):ge.startsWith("/")?ge:`/${ge}`;ge=new URL(ae,Ee.origin).toString()}catch{throw Error(`Invalid redirectUri: "${B}". It must be a valid absolute URL.`)}}}let be=new URL(J);be.searchParams.append("client_id",F),be.searchParams.append("redirect_uri",ge),be.searchParams.append("response_type","code"),be.searchParams.append("scope",ne),be.searchParams.append("state",de),be.searchParams.append("nonce",ie);let me=await $t(re);be.searchParams.append("code_challenge",me),be.searchParams.append("code_challenge_method","S256");let Ie=await X.beforeLogin?.({request:M}),Oe=Ie===void 0?{state:de,codeVerifier:re,nonce:ie}:{state:de,codeVerifier:re,nonce:ie,context:Ie};return new Response("Redirecting to SSO Provider",{status:302,headers:{Location:be.toString(),"Set-Cookie":ct(Se(de),Oe,X.loginStateTtl??600,"Lax")}})}async function _e(M){if(!X)throw Error("ionite SSO Manager not initialized");let B;try{B=await Le(M)}catch{B=void 0}let J=await X.beforeLogout?.({request:M,user:B}),F=ht("session",M),ne;try{ne=await Ze(M);let me=ne.tokens?.refresh_token??ht("refresh",M);if(me)await Et(me)}catch(me){k.warn("Failed to revoke token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},me)}if(X.sessionStore)try{let me=ne?.sid??F;if(me)await X.sessionStore.delete(me)}catch(me){k.warn("Failed to delete session",{"ion.operation":"session.delete","ion.outcome":"degraded"},me)}let pe=[["Set-Cookie",rt("session")]],de=await X.afterLogout?.({request:M,context:J}),re=wt(de,"/",M.url);if(re.response){let me=new Headers(re.response.headers);for(let[,Ie]of pe)me.append("Set-Cookie",Ie);return new Response(re.response.body,{status:re.response.status,statusText:re.response.statusText,headers:me})}let ie=re.location??"/",ge=M.headers.get("accept");if(ge?.includes("application/json")||ge?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:ie}),{status:200,headers:[["Content-Type","application/json"],...pe]});return new Response("Logged out",{status:302,headers:[["Location",ie],...pe]})}async function Ne(M){if(!X)throw Error("ionite SSO Manager not initialized");if(!X.sessionStore)throw Error("Back-Channel Logout requires sessionStore configuration");try{if(!M.headers.get("content-type")?.includes("application/x-www-form-urlencoded"))return new Response("Invalid Content-Type, expected application/x-www-form-urlencoded",{status:400});let J=await M.text(),ne=new URLSearchParams(J).get("logout_token");if(!ne)return new Response("Missing logout_token parameter",{status:400});let pe=t(X.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify logout tokens."),de=t(X.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify logout tokens."),re=X.jwksUri||`${pe}/protocol/openid-connect/certs`,ie=await Pn({logoutToken:ne,jwksUri:re,issuer:pe,audience:de,log:k}),ge=typeof ie.sid==="string"?ie.sid:void 0;if(!ge)return k.warn("Back-Channel Logout: logout_token missing sid claim",{"ion.operation":"backchannel_logout","ion.outcome":"failure"}),new Response("Invalid logout_token: missing sid claim",{status:400});return await X.sessionStore.delete(ge),k.info("Back-Channel Logout: successfully deleted session",{"ion.module":"sso",sid:ge}),new Response("OK",{status:200})}catch(B){return k.error("Error during back-channel logout",{"ion.operation":"backchannel_logout","ion.outcome":"failure"},B),new Response("Internal Server Error",{status:500})}}async function $e(M){if(!X)throw Error("ionite SSO Manager not initialized");let B=Date.now(),J=new URL(M.url),F=new URLSearchParams(J.search);k.debug("SSO callback received",{"ion.event":"ion.sso.callback.received","ion.module":"sso","ion.operation":"sign_in.callback","http.method":M.method,"url.path":J.pathname,hasCode:F.has("code"),hasState:F.has("state"),hasError:F.has("error"),...dn(F.get("iss")??void 0,"oidc.issuer")});let ne=Object.fromEntries(F.entries()),pe=await y.callbackParams.validate(ne);if(pe.issues)return k.warn("SSO callback parameter validation failed",{"ion.event":"ion.sso.callback.validation_failed","ion.operation":"sign_in.callback","ion.outcome":"failure","validation.issues":ln(pe.issues)}),D(pe.issues,"OIDC callback parameters validation failed");let{code:de,state:re}=pe.value,ie;try{let ge=t(re,'OIDC "state" was not present in the callback parameters'),be=ht(Se(ge),M,!0),{codeVerifier:me,state:Ie,nonce:Oe,context:Ee}=be??{};ie=Ee,k.debug("SSO callback state cookie read",{"ion.event":"ion.sso.callback.state_cookie_read","ion.module":"sso","ion.operation":"sign_in.callback",hasStateCookie:Boolean(be),hasCodeVerifier:Boolean(me),hasStateVerifier:Boolean(Ie),hasNonce:Boolean(Oe),hasContext:Ee!==void 0});let ae=t(me,'OIDC "codeVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');t(Ie,'OIDC "stateVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');let ee=t(Oe,'OIDC "nonce" was not present in cookies, ensure that the SSO login was initiated correctly'),oe=t(de,'OIDC "code" was not present in the callback parameters');if(re!==Ie)throw k.warn("SSO callback state verification failed",{"ion.event":"ion.sso.callback.state_verification_failed","ion.operation":"sign_in.callback","ion.outcome":"failure"}),Error('SSO State Verifier failed, the "state" request parameter does not equal the "state" in the SSO cookie');k.debug("SSO callback state verified",{"ion.event":"ion.sso.callback.state_verified","ion.module":"sso","ion.operation":"sign_in.callback"});let ue=X.cookiesSecure?M.url.replace(/^http:\/\//,"https://"):M.url,ce=await Ut(oe,ae,ue),{tokenExpiresAt:he,sessionExpiresAt:we}=tt(ce);ce.expires=he.toISOString();let fe=Date.now();k.debug("SSO ID token parsing started",{"ion.event":"ion.sso.id_token.parse_started","ion.module":"sso","ion.operation":"id_token.parse"});let Ce=await Ge(ce,ee,we);k.debug("SSO ID token parsing completed",{"ion.event":"ion.sso.id_token.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":Ye(fe),"user.id":Ce.id});let Ae,Me;{let Te=ot("SSO requires sessionStore configuration for opaque session cookies."),Ke=typeof Ce.sso.profile.sid==="string"?Ce.sso.profile.sid:void 0,Ue=Ke||st(32),qe=Ce.id;if(k.debug("SSO session creation evaluated",{"ion.event":"ion.sso.session.create_evaluated","ion.module":"sso","ion.operation":"session.create",hasSid:Boolean(Ue),hasIdpSid:Boolean(Ke),hasSub:Boolean(qe),"user.id":qe}),!qe)throw Error("Session creation failed: missing sub in ID token claims");let St=Date.now(),Yt={sid:Ue,sub:qe,idpSid:Ke,authType:"sso",tenantId:X.tenantId,tokens:ce,claims:Ce.sso.profile,expiresAt:we,createdAt:new Date};await vt(Te,Yt),Me=Yt,Ae=["Set-Cookie",ct("session",Ue,we)],k.info("SSO session created",{"ion.event":"ion.sso.session.created","ion.operation":"session.create","ion.outcome":"success","duration.ms":Ye(St),"user.id":qe})}if(X.userStore)try{let Te=Ce.id;if(Te){let Ke=new Date,Ue=Date.now();k.debug("SSO user store lookup started",{"ion.event":"ion.sso.user.lookup_started","ion.module":"sso","ion.operation":"user.lookup","user.id":Te});let qe=await X.userStore.get(Te);if(k.debug("SSO user store lookup completed",{"ion.event":"ion.sso.user.lookup_completed","ion.module":"sso","ion.operation":"user.lookup","duration.ms":Ye(Ue),"user.id":Te,found:Boolean(qe)}),qe||X.enableJitUserProvisioning){let St=Date.now(),Yt={...qe??{},...Ce,id:Te,tenantId:qe?.tenantId,createdAt:qe?.createdAt??Ke,updatedAt:Ke};await X.userStore.upsert(Yt),k.info("SSO user stored",{"ion.event":"ion.sso.user.stored","ion.operation":"user.store","ion.outcome":"success","duration.ms":Ye(St),"user.id":Te,existing:Boolean(qe),jitProvisioning:Boolean(X.enableJitUserProvisioning)})}else k.warn("JIT user provisioning disabled: user not found in store and will not be created",{"ion.event":"ion.sso.user.skipped","ion.operation":"user.store","ion.outcome":"skipped","user.id":Te})}else k.warn("User storage skipped: missing sub in ID token claims",{"ion.event":"ion.sso.user.skipped","ion.operation":"user.store","ion.outcome":"skipped"})}catch(Te){k.warn("Failed to store user",{"ion.event":"ion.sso.user.store_failed","ion.operation":"user.store","ion.outcome":"degraded",...Fn(Te)})}k.info("SSO sign-in succeeded",{"ion.event":"ion.sso.sign_in.succeeded","ion.operation":"sign_in.callback","ion.outcome":"success","duration.ms":Ye(B),"user.id":Ce.id});let ze=[["Set-Cookie",rt(Se(ge))],...Ae?[Ae]:[]],Qe=await X.afterLogin?.({ok:!0,request:M,user:Ce,session:Me,context:ie}),Ve=wt(Qe,"/",M.url);if(Ve.response)return At(Ve.response,ze.map(([,Te])=>Te));return new Response("Authentication successful, redirecting",{status:302,headers:[["Location",Ve.location],...ze]})}catch(ge){k.error("Error during sign-in callback",{"ion.event":"ion.sso.sign_in.callback_failed","ion.operation":"sign_in.callback","ion.outcome":"failure","duration.ms":Ye(B),...Fn(ge)});let be=re?[["Set-Cookie",rt(Se(re))]]:[],me=await X.afterLogin?.({ok:!1,request:M,error:ge,context:ie}),Ie=wt(me,"/",M.url);if(Ie.response)return At(Ie.response,be.map(([,Oe])=>Oe));return new Response("Authentication failed, redirecting",{status:302,headers:[["Location",Ie.location],...be]})}}function tt(M){let B=Date.now(),J=Number(M.expires_in??3600)||3600,F=new Date(B+J*1000),ne;if(M.refresh_expires_in!=null&&Number.isFinite(Number(M.refresh_expires_in)))ne=Number(M.refresh_expires_in);else if(M.refresh_token)ne=je;else ne=J;return{tokenExpiresAt:F,sessionExpiresAt:new Date(B+ne*1000)}}async function Ge(M,B,J){if(!X)throw Error("ionite SSO Manager not initialized");let F=Date.now(),ne=await Lt(M.id_token,B);return k.debug("SSO user parsed from ID token",{"ion.event":"ion.sso.user.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":Ye(F),"user.id":ne.sub,hasEmail:Boolean(ne.email),hasName:Boolean(ne.name)}),Je(ne,M,J)}function Je(M,B,J){let F=J??tt(B).sessionExpiresAt,ne=M.ecid!==void 0&&M.ecid!==null?w(M.ecid):void 0;return{id:M.sub,userName:M.preferred_username||"",name:M.name||"",email:M.email||"",emails:[{value:M.email||"",primary:!0}],...ne?{ecid:ne}:{},avatar:M.picture,sso:{profile:{...M},tenant:{id:M.idp||M.iss||"",name:M.iss||""},scope:B.scope,tokenType:B.token_type,sessionState:B.session_state,expires:F}}}async function nt(M){if(!X.userStore)return M;let B=await X.userStore.lookup(M);if(!B)return M;return{...M,...B,id:M.id,sso:M.sso}}async function Ut(M,B,J){if(!X)throw Error("ionite SSO Manager not initialized");De();let F=t(X.tokenUrl,"Missing 'tokenUrl' from SSO Config"),ne=t(X.redirectUri,"Missing 'redirectUri' from SSO Config"),pe=t(X.clientId,"Missing 'clientId' from SSO Config"),de=ne;try{new URL(de)}catch{if(J)try{let ie=new URL(J),ge=de.startsWith("//")?de.slice(1):de.startsWith("/")?de:`/${de}`;de=new URL(ge,ie.origin).toString()}catch{try{let ie=new URL(F),ge=de.startsWith("//")?de.slice(1):de.startsWith("/")?de:`/${de}`;de=new URL(ge,ie.origin).toString()}catch{throw Error(`Invalid redirectUri: "${ne}". It must be a valid absolute URL.`)}}}let re=new URLSearchParams;if(re.append("grant_type","authorization_code"),re.append("code",M),re.append("redirect_uri",de),re.append("client_id",pe),X.clientSecret)re.append("client_secret",X.clientSecret);re.append("code_verifier",B);try{let ie=Date.now();k.debug("SSO token exchange started",{"ion.event":"ion.sso.token.exchange_started","ion.module":"sso","ion.operation":"token.exchange",...dn(F,"oidc.token_url"),...dn(de,"oidc.redirect_uri"),hasClientSecret:Boolean(X.clientSecret)});let ge=await fetch(F,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:re.toString()});k.debug("SSO token exchange response received",{"ion.event":"ion.sso.token.response_received","ion.module":"sso","ion.operation":"token.exchange","http.status_code":ge.status,"duration.ms":Ye(ie)}),k.debug("SSO token exchange response body read started",{"ion.event":"ion.sso.token.response_body_read_started","ion.module":"sso","ion.operation":"token.exchange"});let be=await ge.json();if(k.debug("SSO token exchange response body read completed",{"ion.event":"ion.sso.token.response_body_read_completed","ion.module":"sso","ion.operation":"token.exchange","duration.ms":Ye(ie)}),!ge.ok){k.error("Token exchange error",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":ge.status,"duration.ms":Ye(ie),...Ii(be)});let Ie=be;throw Error(`Token exchange failed: ${Ie.error||ge.statusText} - ${Ie.error_description||""}`.trim())}let me=await y.tokenResponse.validate(be);if(me.issues)throw k.error("Token response validation failed",{"ion.event":"ion.sso.token.response_validation_failed","ion.operation":"token.exchange","ion.outcome":"failure","duration.ms":Ye(ie),"validation.issues":ln(me.issues)}),Error(`Token response validation failed: ${me.issues}`);return k.debug("SSO token exchange completed",{"ion.event":"ion.sso.token.exchange_completed","ion.module":"sso","ion.operation":"token.exchange","ion.outcome":"success","duration.ms":Ye(ie),tokenType:me.value.token_type,hasAccessToken:Boolean(me.value.access_token),hasIdToken:Boolean(me.value.id_token),hasRefreshToken:Boolean(me.value.refresh_token),expiresIn:me.value.expires_in}),me.value}catch(ie){throw k.error("Error during token exchange",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure",...Fn(ie)}),ie}}async function Rt(M){return Cn(async()=>{if(!X)throw Error("ionite SSO Manager not initialized");De();let B=t(X.tokenUrl,"Missing 'tokenUrl' from SSO Config"),J=t(X.clientId,"Missing 'clientId' from SSO Config"),F=new URLSearchParams;if(F.append("grant_type","refresh_token"),F.append("refresh_token",M),F.append("client_id",J),X.clientSecret)F.append("client_secret",X.clientSecret);let ne=await fetch(B,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:F.toString()}),pe=await ne.json();if(!ne.ok){k.error("Token refresh error",{"ion.operation":"token.refresh","ion.outcome":"failure",response:pe});let re=pe;throw Error(`Token refresh failed: ${re.error||ne.statusText} - ${re.error_description||""}`.trim())}let de=await y.tokenResponse.validate(pe);if(de.issues)throw k.error("Token refresh response validation failed",{"ion.event":"ion.sso.token.refresh_validation_failed","ion.operation":"token.refresh","ion.outcome":"failure","validation.issues":ln(de.issues)}),Error(`Token refresh response validation failed: ${de.issues}`);return de.value},void 0,void 0,void 0,k)}async function Et(M){try{if(!X)throw Error("ionite SSO Manager not initialized");if(!X.revocationEndpoint)return;let B=t(X.clientId,"Missing 'clientId' from SSO Config"),J=new URLSearchParams;if(J.append("token",M),J.append("token_type_hint","refresh_token"),J.append("client_id",B),X.clientSecret)J.append("client_secret",X.clientSecret);let F=await fetch(X.revocationEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:J.toString()});if(!F.ok)k.warn("Token revocation failed",{"ion.operation":"token.revoke","ion.outcome":"degraded",status:F.status,statusText:F.statusText});else k.info("Token revoked successfully",{"ion.module":"sso"})}catch(B){k.warn("Error revoking token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},B)}}async function Dt(){if(!X)throw Error("ionite SSO Manager not initialized");let M=X.authority;if(!X.jwksUri&&!M)throw Error("Missing 'jwksUri' or 'authority' from SSO Config. OIDC configuration is required for this operation.");let B=X.jwksUri||`${M}/protocol/openid-connect/certs`;return Wt(B,k)}async function Lt(M,B){let J=Date.now(),F=t(X.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify ID tokens."),ne=t(X.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify ID tokens."),pe=X.jwksUri||`${F}/protocol/openid-connect/certs`;k.debug("SSO ID token verification started",{"ion.event":"ion.sso.id_token.verify_started","ion.module":"sso","ion.operation":"id_token.verify",...dn(pe,"oidc.jwks_uri")});let de;try{de=await kt({idToken:M,jwksUri:pe,issuer:F,audience:ne,expectedNonce:B,log:k})}catch(ie){throw k.error("SSO ID token verification failed",{"ion.event":"ion.sso.id_token.verify_failed","ion.module":"sso","ion.operation":"id_token.verify","ion.outcome":"failure","duration.ms":Ye(J)},ie),ie}k.debug("SSO ID token signature verified",{"ion.event":"ion.sso.id_token.signature_verified","ion.module":"sso","ion.operation":"id_token.verify","duration.ms":Ye(J)});let re=await y.idTokenClaims.validate(de);if(re.issues)throw k.error("ID token claims validation failed",{"ion.event":"ion.sso.id_token.validation_failed","ion.operation":"id_token.validate","ion.outcome":"failure","duration.ms":Ye(J),"validation.issues":ln(re.issues)}),Error(`ID token claims validation failed: ${re.issues}`);return k.debug("SSO ID token claims validated",{"ion.event":"ion.sso.id_token.claims_validated","ion.module":"sso","ion.operation":"id_token.validate","ion.outcome":"success","duration.ms":Ye(J),"user.id":re.value.sub,hasIssuer:Boolean(re.value.iss),hasAudience:Boolean(re.value.aud)}),re.value}function ot(M="SSO sessionStore is required for opaque session cookies."){if(!X.sessionStore)throw Error(M);return X.sessionStore}async function vt(M,B){try{await M.create(B)}catch(J){if(!await M.get(B.sid))throw J;await M.update(B.sid,B)}}function gt(M){if(!M)return;if(M instanceof Date)return M;let B=new Date(M);return Number.isNaN(B.getTime())?void 0:B}function at(M){let B=M.tokens;if(!B?.access_token||!B.id_token||!B.token_type)return;return B}async function It(M,B=!1){let J=ot(),F=ht("session",M);if(!F)return{tokens:void 0,refreshHeaders:[]};let ne=await J.get(F);if(ne&&X.tenantId&&ne.tenantId&&ne.tenantId!==X.tenantId)return{tokens:void 0,refreshHeaders:[["Set-Cookie",rt("session")]],sid:F};if(ne?.authType!=="sso")return{tokens:void 0,refreshHeaders:[["Set-Cookie",rt("session")]],sid:F};let pe=at(ne);if(!pe)return{tokens:void 0,refreshHeaders:[["Set-Cookie",rt("session")]],sid:F};let de=gt(ne.expiresAt);if(de?Date.now()>de.getTime():!1)return await J.delete(F),{tokens:void 0,sid:F,refreshHeaders:[["Set-Cookie",rt("session")]]};let ie=gt(pe.expires),ge=ie?Date.now()>ie.getTime():!0;if((B||ge)&&pe.refresh_token)return lt(F,ne,pe);return{tokens:pe,sid:F,session:ne,refreshHeaders:[]}}function lt(M,B,J){let F=H.get(M);if(F)return F;let ne=ot(),pe=(async()=>{let de=await Rt(J.refresh_token),{tokenExpiresAt:re,sessionExpiresAt:ie}=tt(de);de.expires=re.toISOString();let ge=await Ge(de,void 0,ie),be=ge.sso.profile,me=st(32),Ie={...B,sid:me,tokens:de,claims:be,expiresAt:ie,createdAt:new Date};await vt(ne,Ie);try{if(Pe<=0)await ne.delete(M);else{let{refresh_token:Oe,...Ee}=J;await ne.update(M,{tokens:Ee,expiresAt:new Date(Date.now()+Pe)})}}catch(Oe){k.warn("Failed to retire rotated SSO session record",{"ion.operation":"session.rotate","ion.outcome":"degraded"},Oe)}return{tokens:de,sid:me,session:Ie,refreshedUser:ge,refreshHeaders:[["Set-Cookie",ct("session",me,ie)]]}})();return H.set(M,pe),pe.finally(()=>{H.delete(M)})}async function Ze(M,B=!1){return It(M,B)}async function yt(M){let{tokens:B}=await Ze(M);if(!B)return;return B.access_token}function ct(M,B,J,F=X.cookiesSameSite??"Strict"){if(!X)throw Error("ionite SSO Manager not initialized");if(M=`${X.cookiesPrefix}.${M}`,typeof B!=="string")B=btoa(JSON.stringify(B));let ne;if(J instanceof Date)ne=`Expires=${J.toUTCString()}`;else if(typeof J==="number")ne=`Max-Age=${J}`;else throw Error("Invalid expires type",J);if(B.length>4000)throw Error(`Error setting cookie: ${M}. Cookie length is: ${B.length}`);return`${M}=${B}; ${ne}; Path=${X.cookiesPath}; HttpOnly;${X.cookiesSecure?" Secure;":""} SameSite=${F};`}function rt(M){if(!X)throw Error("ionite SSO Manager not initialized");return`${X.cookiesPrefix}.${M}=; Max-Age=0; Path=${X.cookiesPath}; HttpOnly;${X.cookiesSecure?" Secure;":""} SameSite=${X.cookiesSameSite};`}function ht(M,B,J=!1){if(!X)throw Error("ionite SSO Manager not initialized");let F=B.headers.get("cookie");if(!F)return null;let ne=`${X.cookiesPrefix}.${M}`,pe=F.split(";").find((ge)=>ge.trim().startsWith(`${ne}=`));if(!pe)return null;let de=pe.indexOf("="),re=pe.slice(de+1).trim();if(!J)return re;let ie=atob(re);return JSON.parse(ie)}function Se(M){return`state_${M}`}async function ve(M,B){if(!X)throw Error("ionite SSO Manager not initialized");let{loginUrl:J,userUrl:F,tokenUrl:ne,refreshUrl:pe,logoutUrl:de,logoutBackChannelUrl:re,jwksUrl:ie,redirectUri:ge}={...X,...B},be=new URL(M.url).pathname;if(ge){let me;try{me=new URL(ge).pathname}catch{try{let Ie=new URL(M.url),Oe=ge.startsWith("//")?ge.slice(1):ge;me=new URL(Oe,Ie.origin).pathname}catch{me=ge.startsWith("/")?ge:`/${ge}`}}if(me===be)return $e(M)}if(J===be)return ye(M);if(F===be)try{let{tokens:me,session:Ie,refreshedUser:Oe,refreshHeaders:Ee}=await Ze(M);if(!me)return new Response("User not logged in",{status:401,headers:Ee});let ae=Oe??(Ie?.claims?Je(Ie.claims,me,gt(Ie.expiresAt)):void 0);if(!ae)return new Response("User not logged in",{status:401,headers:Ee});let ee=await nt(ae);return new Response(JSON.stringify(ee),{headers:[["Content-Type","application/json"],...Ee]})}catch(me){if(xr(me))return new Response("User not logged in",{status:401});return k.error("Error resolving SSO user",{"ion.operation":"sso.user","ion.outcome":"degraded"},me),new Response(JSON.stringify({error:"auth_unavailable"}),{status:503,headers:{"Content-Type":"application/json"}})}if(ne===be){let{tokens:me,refreshHeaders:Ie}=await Ze(M);if(!me)return new Response("User not logged in",{status:401,headers:Ie});return new Response(JSON.stringify({token:me.access_token,expires:me.expires}),{headers:[["Content-Type","application/json"],...Ie]})}if(pe===be){let{tokens:me,refreshHeaders:Ie}=await Ze(M,!0);if(!me)return new Response("User not logged in",{status:401});return new Response("Refresh Complete",{status:200,headers:Ie})}if(de===be)return _e(M);if(re===be)return Ne(M);if(ie===be){let me=await Dt();return new Response(JSON.stringify(me),{headers:[["Content-Type","application/json"]]})}return new Response("Not Found",{status:404})}return{...X,getUser:Le,resolveUser:We,getJwt:yt,initiateLogin:ye,logout:_e,logoutBackChannel:Ne,callbackHandler:$e,handler:ve}}function Pi(y){let k={},R=y.split(";");for(let W of R){let V=W.trim();if(!V)continue;let G=V.indexOf("=");if(G===-1)continue;let H=V.slice(0,G).trim(),Y=V.slice(G+1).trim();k[H]=Y}return k}function xr(y){if(!(y instanceof Error))return!1;return["Public key not found","Invalid JWT","Invalid JWT signature","ID token expired","ID token issuer mismatch","ID token audience mismatch","ID token nonce mismatch","ID token missing exp","invalid_grant"].some((k)=>y.message.includes(k))}function Ur(y){return y=y??"SSO Unavailable",new Response(JSON.stringify({error:y}),{status:503,statusText:y,headers:{"Content-Type":"application/json"}})}var pn="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.";async function xi(y,k){return t(k,pn),k.sso?.getUser(y)}async function Ui(y,k){return t(k,pn),await k.sso?.resolveUser(y)??{status:"unauthenticated"}}async function Ei(y,k){t(k,pn);let R=k.sso;if(!R)return Ur();return R.initiateLogin(y)}async function Mi(y,k){t(k,pn);let R=k.sso;if(!R)return Ur();return R.callbackHandler(y)}export{Ft as CACHE_BOUNDS,Qn as CIAM_PROVIDER_PRESETS,_ as CatalogAdjacencyCache,Z as InMemoryTenantStore,fs as allowHosts,ms as allowOrigins,pr as allowRelativePaths,mr as allowSameOrigin,Cr as assertSubjectTypeAssignable,cr as assertTrustedIdTokenClaims,Ln as baseCustomerToScim,On as baseUserToScimUser,Dn as baseWorkloadToScim,lr as blockDangerousUrls,An as buildAuthorizationUrl,Hn as buildLfvSigningInput,Mi as callback,ys as captureRedirect,ws as ciam,cs as clearDiscoveryCache,Zr as clearJwksCache,te as collectReferencedDefinitions,Jr as configureJwksCache,gs as defaultRedirectPolicies,xn as discoverOidcEndpoints,Pr as discoverSessionRecords,Tr as discoverSessions,_n as entitlementToScimGroup,Tn as exchangeAuthorizationCode,O as expandRoot,Un as fetchUserInfo,En as generateAppleClientSecret,pi as generateLfvEd25519KeyPair,Rn as getCachedVerificationKey,bs as getCustomer,bi as getDiscoveredSessionUsers,Wt as getJwks,gn as getProviderPreset,ts as getPublicKeyForKid,es as getPublicKeyFromJwks,xi as getUser,vn as getVerificationKeyForKid,Nr as has,zr as hasAll,Kr as hasAllScope,$r as hasAny,Gr as hasAnyScope,qr as hasGroup,Wr as hasPermission,Vr as hasRole,Br as hasScope,si as iam,Ei as initiateLogin,fr as isRedirectAllowed,Ai as listSsoClientIdsFromCookies,qt as normalizeOidcIssuer,hn as orderedEnabledProviders,Rr as parseLfvJwks,$t as pkceChallengeFromVerifier,z as reconcileSubjectAccess,wt as resolveAfterRedirect,mi as resolveCacheConfig,hs as resolveCapturedRedirect,Zt as resolveCiamProvider,Cs as resolveCustomer,Qr as resolveJwkForKid,vr as resolveJwksCacheConfig,yn as resolveProviderBranding,jn as resolveRedirect,Ir as resolveSessionCacheConfig,Ui as resolveUser,Mn as sameOriginRedirectRules,le as sendTenantWebhook,as as setDiscoveryClock,Hr as setJwksClock,Fr as setJwksRetry,li as signLfvPayload,Ti as sso,ai as stringifyLfvJwks,kt as verifyIdToken,di as verifyLfvSignature,Pn as verifyLogoutToken,vi as verifyUser,At as withSetCookies};
|
|
1
|
+
import{E,o,h,S,b,r,i,U,u,e,d,A,I,v,j,x,n,c,_,O,z,te,w,N,L,l,a,t,D,C,p,P,m,T,Z,le,s,f,g,q,K}from"./shared/core-j5xhxcmq.js";var Er="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.",Yn=["user","customer","workload"],Mr={user:async(y,k)=>k.sso?.getUser(y),customer:async(y,k)=>k.ciam?.getCustomer(y),workload:async(y,k)=>{let R=await k.workload?.getWorkloadIdentity?.(y);if(!R)return;let W=R.clientId??R.workloadId??R.claims.sub;return W?{...R,id:W}:void 0}};function jr(y){if(y==="any")return Yn;let k=Array.isArray(y)?y:[y];return Yn.filter((R)=>k.includes(R))}function _r(y){let k=y.headers.get("cookie");if(!k)return[];return k.split(";").map((R)=>R.slice(0,R.indexOf("=")===-1?R.length:R.indexOf("=")).trim()).filter(Boolean)}function Or(y,k){let R=y.headers.get("authorization")?.toLowerCase().startsWith("bearer ")??!1,W=_r(y),V=new Set;for(let H of W){if(H.startsWith("ion.sso"))V.add("user");if(H.startsWith("ion.ciam"))V.add("customer")}let G=W.length>0&&!V.has("user")&&!V.has("customer");return k.filter((H)=>{if(H==="workload")return R;if(W.length===0)return!1;return V.has(H)||G})}function Be(y){return typeof y==="string"?y:y.id}function Xn(y){let{subject:k,subjectType:R}=y,W;if(R==="user")W=k.sso?.scope;else if(R==="customer")W=k.ciam?.scope;else if(R==="workload")W=k.scope;return new Set((W??"").split(/\s+/).filter(Boolean))}function fn(y,k,R){let W=Xn(y),V=k.filter((H)=>W.has(H));return{allow:R==="any"?V.length>0:k.length>0&&V.length===k.length,metadata:{reason:"scope",wantedScopes:k,matchedScopes:V}}}function Mt(y,k){return(R)=>{if(y.length===0)return;let W=Xn(R),V=y.filter((H)=>W.has(H));return(k==="any"?V.length>0:V.length===y.length)?V:void 0}}function Xt(y,k,R){return(W)=>{if(k.length===0||W.subjectType!=="workload")return;let V=E(y.config?.authz,W.subject);if(!V)return;let G=k.filter((Y)=>V.has(Y));return(R==="any"?G.length>0:G.length===k.length)?G:void 0}}function Dr(y,k){if(y.subjectType==="workload"){let R=y.subject.scopesAsEntitlements;if(typeof R==="boolean")return R}return k.config?.authz?.scopesAsEntitlements===!0}function mn(y,k,R,W,V){return{allow:R==="ok",subject:k?.subject,subjectType:k?.subjectType,reason:R,decision:W,response(){if(R==="ok")return new Response(null,{status:204});if(R==="unauthenticated")return y.log.warn("authz.denied",{reason:R,...V()}),Response.json({error:"Unauthorized"},{status:401});if(R==="not_configured")return y.log.warn("authz.denied",{reason:R,subject:k?.subject?.id,subjectType:k?.subjectType,...V()}),Response.json({error:"not_configured"},{status:503});return y.log.warn("authz.denied",{reason:R,subject:k?.subject?.id,subjectType:k?.subjectType,...V()}),Response.json({error:"Forbidden"},{status:403})}}}function Lr(y,k,R){return new Promise((W)=>{let V=[],G=y.length,H=!1,Y=()=>{if(G-=1,G===0&&!H)H=!0,W({outcomes:V})};for(let Q of y)k(Q).then((X)=>{if(V.push({principal:Q,decision:X}),!H&&X.allow){H=!0,W({matched:{principal:Q,decision:X},outcomes:V});return}Y()},(X)=>{R?.(Q,X),V.push({principal:Q,decision:{allow:!1,metadata:{reason:"error"}}}),Y()})})}async function pt(y,k,R,W,V,G,H){t(k,Er);let Y=Or(y,jr(R)),X=(await Promise.all(Y.map(async(ye)=>{let _e=await Mr[ye](y,k);return _e?.id?{subject:_e,subjectType:ye,subjectId:_e.id}:void 0}))).filter((ye)=>ye!==void 0);if(X.length===0)return mn(k,void 0,"unauthenticated",void 0,V);let Pe=async(ye)=>{let _e=k.authz.accessIndex;if(!_e?.isSubjectDisabled)return!1;return _e.isSubjectDisabled(ye.subjectId,ye.subjectType)},xe=async(ye)=>{if(H){let _e=H(ye);if(_e&&_e.length>0){if(await Pe(ye))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"trusted-client",matchedPermissions:_e}}}}if(G&&Dr(ye,k)){let _e=G(ye);if(_e&&_e.length>0){if(await Pe(ye))return{allow:!1,metadata:{reason:"subject_disabled"}};return{allow:!0,metadata:{reason:"scope",matchedScopes:_e}}}}return W(ye)},{matched:je,outcomes:De}=await Lr(X,xe,(ye,_e)=>{k.log.warn("authz.check_error",{"ion.operation":"authz.check","ion.outcome":"error",subject:ye.subjectId,subjectType:ye.subjectType,error:_e instanceof Error?_e.message:String(_e),...V()})});if(je){if(je.decision.metadata?.reason==="scope")k.log.info("authz.scope_honor",{"ion.operation":"authz.scope_honor","ion.outcome":"allow",subject:je.principal.subjectId,subjectType:je.principal.subjectType,matchedScopes:je.decision.metadata.matchedScopes,...V()});return mn(k,je.principal,"ok",je.decision,V)}let We=De.length>0&&De.every((ye)=>{let _e=ye.decision.metadata?.reason;return _e==="access_index_not_configured"||_e==="error"}),ke=De[0],Le=We?"not_configured":"forbidden";return mn(k,ke?.principal,Le,ke?.decision,V)}async function Nr(y,k,R,W,V,G="any"){return pt(y,k,G,(H)=>k.authz.has(H.subjectId,R,W,V,H.subjectType),()=>({targetType:R,target:Be(W),resource:V?Be(V):void 0}),V?void 0:Mt([Be(W)],"any"),R==="permission"&&!V?Xt(k,[Be(W)],"any"):void 0)}async function Wr(y,k,R,W,V="any"){return pt(y,k,V,(G)=>k.authz.hasPermission(G.subjectId,R,W,G.subjectType),()=>({targetType:"permission",target:Be(R),resource:W?Be(W):void 0}),W?void 0:Mt([Be(R)],"any"),W?void 0:Xt(k,[Be(R)],"any"))}async function Vr(y,k,R,W,V="any"){return pt(y,k,V,(G)=>k.authz.hasRole(G.subjectId,R,W,G.subjectType),()=>({targetType:"role",target:Be(R),resource:W?Be(W):void 0}),W?void 0:Mt([Be(R)],"any"))}async function qr(y,k,R,W,V="any"){return pt(y,k,V,(G)=>k.authz.hasGroup(G.subjectId,R,W,G.subjectType),()=>({targetType:"group",target:Be(R),resource:W?Be(W):void 0}),W?void 0:Mt([Be(R)],"any"))}async function $r(y,k,R,W="any"){let V=R.filter((H)=>!H.resource).map((H)=>Be(H.target)),G=R.filter((H)=>!H.resource&&H.targetType==="permission").map((H)=>Be(H.target));return pt(y,k,W,(H)=>k.authz.hasAny(H.subjectId,R,H.subjectType),()=>({targets:R.map((H)=>`${H.targetType}:${Be(H.target)}`)}),V.length>0?Mt(V,"any"):void 0,G.length>0?Xt(k,G,"any"):void 0)}async function zr(y,k,R,W="any"){let V=R.length>0&&R.every((Y)=>!Y.resource),G=R.length>0&&R.every((Y)=>!Y.resource&&Y.targetType==="permission"),H=R.map((Y)=>Be(Y.target));return pt(y,k,W,(Y)=>k.authz.hasAll(Y.subjectId,R,Y.subjectType),()=>({targets:R.map((Y)=>`${Y.targetType}:${Be(Y.target)}`)}),V?Mt(H,"all"):void 0,G?Xt(k,H,"all"):void 0)}async function Br(y,k,R,W="any"){return pt(y,k,W,(V)=>Promise.resolve(fn(V,[R],"any")),()=>({scope:R}))}async function Gr(y,k,R,W="any"){return pt(y,k,W,(V)=>Promise.resolve(fn(V,R,"any")),()=>({scopes:R}))}async function Kr(y,k,R,W="any"){return pt(y,k,W,(V)=>Promise.resolve(fn(V,R,"all")),()=>({scopes:R}))}function Fe(y){return typeof y==="string"&&y.length>0?y:void 0}function Zn(y){let k=Fe(y.email);return{sub:String(y.sub??""),email:k,name:Fe(y.name),userName:Fe(y.preferred_username)??k,avatar:Fe(y.picture)}}var Qn={oidc:{flow:"id_token",scope:"openid profile email",branding:{displayName:"Single sign-on"},mapClaims:Zn},google:{flow:"id_token",authorizationUrl:"https://accounts.google.com/o/oauth2/v2/auth",tokenUrl:"https://oauth2.googleapis.com/token",jwksUri:"https://www.googleapis.com/oauth2/v3/certs",scope:"openid email profile",branding:{displayName:"Google",iconUrl:"https://www.gstatic.com/firebasejs/ui/2.0.0/images/auth/google.svg",colors:{light:"#ffffff",dark:"#131314",secondary:"#4285F4"},url:"https://accounts.google.com"},mapClaims:Zn},microsoft:{flow:"id_token",authorizationUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/authorize",tokenUrl:"https://login.microsoftonline.com/common/oauth2/v2.0/token",jwksUri:"https://login.microsoftonline.com/common/discovery/v2.0/keys",scope:"openid email profile",branding:{displayName:"Microsoft",colors:{light:"#ffffff",dark:"#2f2f2f",secondary:"#0067b8"},url:"https://login.microsoftonline.com"},mapClaims:(y)=>{let k=Fe(y.email)??Fe(y.preferred_username);return{sub:String(y.sub??y.oid??""),email:k,name:Fe(y.name),userName:Fe(y.preferred_username)??k,avatar:Fe(y.picture)}}},apple:{flow:"id_token",authorizationUrl:"https://appleid.apple.com/auth/authorize",tokenUrl:"https://appleid.apple.com/auth/token",jwksUri:"https://appleid.apple.com/auth/keys",scope:"openid email name",extraAuthParams:{response_mode:"form_post"},branding:{displayName:"Apple",colors:{light:"#000000",dark:"#ffffff"},url:"https://appleid.apple.com"},mapClaims:(y)=>{let k=Fe(y.email);return{sub:String(y.sub??""),email:k,name:Fe(y.name),userName:k}}},github:{flow:"userinfo",authorizationUrl:"https://github.com/login/oauth/authorize",tokenUrl:"https://github.com/login/oauth/access_token",userInfoUrl:"https://api.github.com/user",scope:"read:user user:email",branding:{displayName:"GitHub",colors:{light:"#24292f",dark:"#ffffff"},url:"https://github.com"},mapClaims:(y)=>({sub:String(y.id??y.node_id??""),email:Fe(y.email),name:Fe(y.name)??Fe(y.login),userName:Fe(y.login),avatar:Fe(y.avatar_url)})}};function gn(y){if(y==="magic-link")return;return Qn[y]}function Zt(y,k){if(k.type==="magic-link")return;let R=gn(k.type);if(!R)return;return{name:y,type:k.type,flow:R.flow,authorizationUrl:k.authorizationUrl??R.authorizationUrl,tokenUrl:k.tokenUrl??R.tokenUrl,jwksUri:k.jwksUri??R.jwksUri,userInfoUrl:k.userInfoUrl??R.userInfoUrl,scope:k.scope??R.scope,clientId:k.clientId,clientSecret:k.clientSecret,extraAuthParams:R.extraAuthParams,branding:{...R.branding,...k.branding},mapClaims:R.mapClaims,config:k}}function yn(y){return{...gn(y.type)?.branding??{displayName:y.type},...y.branding}}function hn(y){if(!y)return[];return Object.entries(y).filter(([,k])=>k.enabled!==!1).map(([k,R],W)=>({name:k,config:R,index:W})).sort((k,R)=>{let W=k.config.order??Number.MAX_SAFE_INTEGER,V=R.config.order??Number.MAX_SAFE_INTEGER;if(W!==V)return W-V;return k.index-R.index}).map(({name:k,config:R})=>({name:k,config:R}))}var tr=600000,kn=256,et=new Map;function Jr(y){if(typeof y?.ttlMs==="number"&&Number.isFinite(y.ttlMs))tr=Math.min(Math.max(y.ttlMs,60000),86400000);if(typeof y?.maxEntries==="number"&&Number.isFinite(y.maxEntries)){kn=Math.max(1,Math.floor(y.maxEntries));while(et.size>kn){let k=et.keys().next().value;if(k===void 0)break;et.delete(k)}}}function er(y,k){et.delete(y),et.set(y,k);while(et.size>kn){let R=et.keys().next().value;if(R===void 0)break;et.delete(R)}}var Nt=new Map,wn=()=>Date.now();function Hr(y){wn=y??(()=>Date.now())}var bn={};function Fr(y){bn=y??{}}function Yr(y){if(!y)return;if(/\bno-store\b/i.test(y))return 60000;let k=/max-age\s*=\s*(\d+)/i.exec(y);if(!k)return;let R=Number(k[1]);return Number.isFinite(R)?R*1000:void 0}function Xr(y){let R=Yr(y)??tr;return Math.min(Math.max(R,60000),86400000)}async function Cn(y,k=3,R=1000,W=30000,V){let G=Error("Placeholder Error");for(let H=0;H<=k;H++)try{return await y()}catch(Y){if(G=Y instanceof Error?Y:Error(String(Y)),Y instanceof Error&&Y.message.includes("400"))throw Y;if(H===k)throw G;let Q=Math.min(R*2**H,W),X=Math.random()*0.1*Q;await new Promise((Pe)=>setTimeout(Pe,Q+X)),V?.warn(`Retry attempt ${H+1} after ${Q+X}ms delay`)}throw G}async function Wt(y,k,R){let W=et.get(y);if(!R?.forceRefresh&&W&&W.expiresAt>wn())return er(y,W),W.jwks;let V=Nt.get(y);if(V)return V;let G=(async()=>{try{return await Cn(async()=>{let H=await fetch(y);if(!H.ok)throw Error("Failed to fetch JWKS");let Y=await H.json(),Q=Xr(H.headers.get("cache-control"));return er(y,{jwks:Y,expiresAt:wn()+Q,importedKeys:new Map}),Y},bn.maxRetries,bn.baseDelayMs,void 0,k)}catch(H){let Y=et.get(y);if(Y)return k?.warn("JWKS refresh failed; serving last-known-good keys",{"ion.operation":"jwks.refresh","ion.outcome":"degraded"}),Y.jwks;throw H}finally{Nt.delete(y)}})();return Nt.set(y,G),G}function Zr(y){if(y){et.delete(y),Nt.delete(y);return}et.clear(),Nt.clear()}async function Qr(y,k,R){return(await nr(y,k,R)).jwk}async function nr(y,k,R){if(!k?.trim())throw Error("JWT header missing kid");await Wt(y,R);let W=et.get(y),V=W?.jwks.keys.find((G)=>G.kid===k);if(!V)await Wt(y,R,{forceRefresh:!0}),W=et.get(y),V=W?.jwks.keys.find((G)=>G.kid===k);if(!W||!V)throw Error("Public key not found");return{jwk:V,entry:W}}async function Rn(y,k,R,W,V){let{jwk:G,entry:H}=await nr(y,k,V),Y=`${k}\x00${R}`,Q=H.importedKeys.get(Y);if(Q)return Q;let X=W(G);return X.catch(()=>{if(H.importedKeys.get(Y)===X)H.importedKeys.delete(Y)}),H.importedKeys.set(Y,X),X}async function es(y,k){let R=y.keys.find((W)=>W.kid===k);if(!R)throw Error("Public key not found");return rr(R)}function rr(y){return crypto.subtle.importKey("jwk",{kty:y.kty,n:y.n,e:y.e},{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},!1,["verify"])}async function ts(y,k,R){return Rn(y,k,"rs256",rr,R)}var Sn={RS256:{kty:"RSA",importParams:{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},verifyParams:{name:"RSASSA-PKCS1-v1_5"}},ES256:{kty:"EC",crv:"P-256",importParams:{name:"ECDSA",namedCurve:"P-256"},verifyParams:{name:"ECDSA",hash:"SHA-256"}}};async function vn(y,k,R,W){if(typeof R!=="string"||!(R in Sn))throw Error(`Unsupported JWT alg "${String(R)}" (allowed: ${Object.keys(Sn).join(", ")})`);let V=Sn[R];return{key:await Rn(y,k,`oidc:${R}`,(H)=>{if(H.kty!==V.kty)throw Error(`JWK type "${H.kty}" does not match token alg "${R}"`);if(V.kty==="EC"){let Y=H;if(Y.crv!==V.crv)throw Error(`JWK curve "${String(Y.crv)}" does not match token alg "${R}"`);return crypto.subtle.importKey("jwk",{kty:"EC",crv:Y.crv,x:Y.x,y:Y.y},V.importParams,!1,["verify"])}return crypto.subtle.importKey("jwk",{kty:H.kty,n:H.n,e:H.e},V.importParams,!1,["verify"])},W),algorithm:V.verifyParams}}function st(y=32){let k=new Uint8Array(y);return crypto.getRandomValues(k),Array.from(k,(R)=>R.toString(16).padStart(2,"0")).join("").substring(0,y)}function Qt(y){let k="";return y.forEach((R)=>{k+=String.fromCharCode(R)}),btoa(k).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function or(y){let k=y.replace(/-/g,"+").replace(/_/g,"/"),R=k.padEnd(k.length+(4-k.length%4)%4,"="),W=atob(R),V=new Uint8Array(W.length);for(let G=0;G<W.length;G++)V[G]=W.charCodeAt(G);return V}function sr(y){let k=new TextDecoder().decode(or(y));return JSON.parse(k)}async function $t(y){let k=new TextEncoder().encode(y),R=await crypto.subtle.digest("SHA-256",k);return Qt(new Uint8Array(R))}function An(y){let k=new URL(y.authorizationUrl);if(k.searchParams.set("client_id",y.clientId),k.searchParams.set("redirect_uri",y.redirectUri),k.searchParams.set("response_type","code"),k.searchParams.set("scope",y.scope),k.searchParams.set("state",y.state),y.codeChallenge)k.searchParams.set("code_challenge",y.codeChallenge),k.searchParams.set("code_challenge_method","S256");if(y.nonce)k.searchParams.set("nonce",y.nonce);for(let[R,W]of Object.entries(y.extraParams??{}))k.searchParams.set(R,W);return k.toString()}async function Tn(y){let k=new URLSearchParams;if(k.append("grant_type","authorization_code"),k.append("code",y.code),k.append("redirect_uri",y.redirectUri),k.append("client_id",y.clientId),y.clientSecret)k.append("client_secret",y.clientSecret);if(y.codeVerifier)k.append("code_verifier",y.codeVerifier);let R=await fetch(y.tokenUrl,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:k.toString()}),W=await R.json();if(!R.ok){let V=W,G=V.error==="invalid_client"&&!y.clientSecret;throw y.log?.error(G?"OIDC authorization-code exchange failed: no client_secret was configured; the provider may require a confidential client":"OIDC authorization-code exchange failed",{"ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":R.status,oidc_error:V.error,...G?{client_auth:"none"}:{}}),Error(`Token exchange failed: ${V.error||R.statusText} - ${V.error_description||""}`.trim())}if(typeof W.access_token!=="string")throw Error("Token exchange response missing access_token");return W}var ar=60;function qt(y){return y.trim().replace(/\/$/,"")}function cr(y){let{claims:k,audience:R}=y,W=qt(y.issuer),V=y.nowSec??Math.floor(Date.now()/1000),G=y.clockSkewSec??ar,H=k.iss;if(typeof H!=="string"||qt(H)!==W)throw Error("ID token issuer mismatch");let Y=k.aud,Q=Array.isArray(Y)?Y.includes(R):typeof Y==="string"&&Y===R,X=typeof k.azp==="string"&&k.azp===R;if(!Q&&!X)throw Error("ID token audience mismatch");if(typeof k.exp!=="number")throw Error("ID token missing exp");if(k.exp<V-G)throw Error("ID token expired");if(y.expectedNonce!==void 0){if(k.nonce!==y.expectedNonce)throw Error("ID token nonce mismatch")}}async function ur(y,k,R){let W=y.split(".");if(W.length!==3)throw Error("Invalid JWT");let V=sr(W[0]),G=sr(W[1]),H=or(W[2]),{key:Y,algorithm:Q}=await vn(k,V.kid,V.alg,R),X=new TextEncoder().encode(`${W[0]}.${W[1]}`);if(!await crypto.subtle.verify(Q,Y,H,X))throw Error("Invalid JWT signature");return{header:V,payload:G}}async function kt(y){let{payload:k}=await ur(y.idToken,y.jwksUri,y.log);return cr({claims:k,issuer:y.issuer,audience:y.audience,clockSkewSec:y.clockSkewSec,expectedNonce:y.expectedNonce}),k}var ns="http://schemas.openid.net/event/backchannel-logout";async function Pn(y){let{payload:k}=await ur(y.logoutToken,y.jwksUri,y.log),R=qt(y.issuer),W=k.iss;if(typeof W!=="string"||qt(W)!==R)throw Error("Logout token issuer mismatch");let V=k.aud,G=Array.isArray(V)?V.includes(y.audience):typeof V==="string"&&V===y.audience,H=typeof k.azp==="string"&&k.azp===y.audience;if(!G&&!H)throw Error("Logout token audience mismatch");if(k.nonce!=null)throw Error("Logout token must not contain a nonce");let Y=k.events;if(!(typeof Y==="object"&&Y!==null&&!Array.isArray(Y)&&Object.hasOwn(Y,ns)))throw Error("Logout token missing back-channel logout event");let X=typeof k.sid==="string"&&k.sid.length>0,Pe=typeof k.sub==="string"&&k.sub.length>0;if(!X&&!Pe)throw Error("Logout token missing sid and sub");if(typeof k.exp==="number"){let xe=Math.floor(Date.now()/1000),je=y.clockSkewSec??ar;if(k.exp<xe-je)throw Error("Logout token expired")}return k}var rs=3600000,ss=60000,is=86400000,os=256,mt=new Map,Vt=new Map;function ir(y,k){mt.delete(y),mt.set(y,k);while(mt.size>os){let R=mt.keys().next().value;if(R===void 0)break;mt.delete(R)}}var In=()=>Date.now();function as(y){In=y??(()=>Date.now())}function cs(y){if(y){mt.delete(y),Vt.delete(y);return}mt.clear(),Vt.clear()}function us(y){let k=y?/max-age\s*=\s*(\d+)/i.exec(y):null,R=k?Number(k[1]):Number.NaN,W=Number.isFinite(R)?R*1000:rs;return Math.min(Math.max(W,ss),is)}async function xn(y){let k=mt.get(y);if(k&&k.expiresAt>In())return ir(y,k),k.endpoints;let R=Vt.get(y);if(R)return R;let W=(async()=>{try{let V=y.replace(/\/$/,""),G=await fetch(`${V}/.well-known/openid-configuration`,{headers:{Accept:"application/json"}});if(!G.ok)throw Error(`OIDC discovery failed for ${y} with status ${G.status}`);let H=await G.json(),Y={authorizationUrl:typeof H.authorization_endpoint==="string"?H.authorization_endpoint:void 0,tokenUrl:typeof H.token_endpoint==="string"?H.token_endpoint:void 0,jwksUri:typeof H.jwks_uri==="string"?H.jwks_uri:void 0,userInfoUrl:typeof H.userinfo_endpoint==="string"?H.userinfo_endpoint:void 0};return ir(y,{endpoints:Y,expiresAt:In()+us(G.headers.get("cache-control"))}),Y}catch(V){let G=mt.get(y);if(G)return G.endpoints;throw V}finally{Vt.delete(y)}})();return Vt.set(y,W),W}async function Un(y,k){let R=await fetch(y,{headers:{Authorization:`Bearer ${k}`,Accept:"application/json","User-Agent":"ionite-ciam"}});if(!R.ok)throw Error(`UserInfo request failed with status ${R.status}`);return await R.json()}function ds(y){let k=y.replace(/-----BEGIN [^-]+-----/g,"").replace(/-----END [^-]+-----/g,"").replace(/\s+/g,""),R=atob(k),W=new Uint8Array(R.length);for(let V=0;V<R.length;V++)W[V]=R.charCodeAt(V);return W}async function En(y){let k=Math.floor(Date.now()/1000),R={alg:"ES256",kid:y.keyId,typ:"JWT"},W={iss:y.teamId,iat:k,exp:k+(y.expiresInSeconds??3600),aud:"https://appleid.apple.com",sub:y.clientId},V=Qt(new TextEncoder().encode(JSON.stringify(R))),G=Qt(new TextEncoder().encode(JSON.stringify(W))),H=`${V}.${G}`,Y=await crypto.subtle.importKey("pkcs8",ds(y.privateKey),{name:"ECDSA",namedCurve:"P-256"},!1,["sign"]),Q=await crypto.subtle.sign({name:"ECDSA",hash:"SHA-256"},Y,new TextEncoder().encode(H));return`${H}.${Qt(new Uint8Array(Q))}`}function ls(y){for(let k=0;k<y.length;k++){let R=y.charCodeAt(k);if(R<=31||R===127)return!0}return!1}function ps(y,k){let R=null;try{R=new URL(y,k)}catch{R=null}let W="";try{W=new URL(k).origin}catch{W=""}return{candidate:y,url:R,requestOrigin:W}}function dr(y,k,R){let W=ps(y,R),V=!1;for(let G of k){let H=G(W);if(H==="deny")return!1;if(H==="allow")V=!0}return V}function lr(){return({candidate:y,url:k})=>{if(ls(y))return"deny";if(y.includes("\\"))return"deny";if(y.startsWith("//"))return"deny";if(!k)return"deny";if(k.protocol!=="http:"&&k.protocol!=="https:")return"deny";if(k.username||k.password)return"deny";return"abstain"}}function pr(){return({candidate:y})=>y.startsWith("/")&&!y.startsWith("//")&&!y.startsWith("/\\")?"allow":"abstain"}function mr(){return({url:y,requestOrigin:k})=>y&&k&&y.origin===k?"allow":"abstain"}function ms(...y){let k=new Set(y.map((R)=>{try{return new URL(R).origin}catch{return R}}));return({url:R})=>R&&k.has(R.origin)?"allow":"abstain"}function fs(...y){let k=y.map((R)=>R.toLowerCase());return({url:R})=>{if(!R)return"abstain";let W=R.hostname.toLowerCase();for(let V of k)if(V.startsWith(".")){if(W===V.slice(1)||W.endsWith(V))return"allow"}else if(W===V)return"allow";return"abstain"}}function Mn(){return[lr(),pr(),mr()]}function fr(y,k,R){if(!y)return!1;return dr(y,k,R)}function jn(y,k){if(!y)return k.fallback;return dr(y,k.rules,k.requestUrl)?y:k.fallback}var gs={rules:Mn(),fallback:"/"};function ys(y,k,R="redirect"){let W=new URL(y.url).searchParams.get(R)??void 0;return fr(W,k.rules,y.url)?{redirect:W}:void 0}function hs(y,k){let R=y.context;return jn(R?.redirect,{rules:k.rules,fallback:k.fallback,requestUrl:y.request.url})}function wt(y,k,R){if(y instanceof Response)return{response:y};if(typeof y==="string")return{location:jn(y,{rules:Mn(),fallback:k,requestUrl:R})};return{location:k}}function At(y,k){if(k.length===0)return y;let R=new Headers(y.headers);for(let W of k)R.append("Set-Cookie",W);return new Response(y.body,{status:y.status,statusText:y.statusText,headers:R})}var en="ciam",Ss="id_token",ks="access_token";function ws(y,k,R,W,V,G){if(!R&&!W)return;let H=new WeakMap,Y={...R,...W},Q={...Y,magicLinkTtl:Y.magicLinkTtl??3600,sessionTtl:Y.sessionTtl??86400,cookiesSecure:Y.cookiesSecure!==void 0?Y.cookiesSecure:!0,cookiesSameSite:Y.cookiesSameSite!==void 0?Y.cookiesSameSite:"Strict",cookiesPrefix:Y.cookiesPrefix??(Y.ciamId?`ion.ciam.${Y.ciamId}`:"ion.ciam"),cookiesPath:Y.cookiesPath??"/"};function X(){if(!Q.sessionStore)throw Error("Missing CIAM configuration field: sessionStore. CIAM sessionStore is required for server-side session tracking and first-party logout.");return Q.sessionStore}function Pe(){X()}let xe=y.callbackParams??a(N("ionite.ciam")),je=y.idTokenClaims??a(l("ionite.ciam")),De=y.tokenResponse??a(L("ionite.ciam"));function We(M=32){let B=new Uint8Array(M);return crypto.getRandomValues(B),Array.from(B,(J)=>J.toString(16).padStart(2,"0")).join("").substring(0,M)}function ke(M,B,J,F=Q.cookiesSameSite??"Strict"){if(!Q)throw Error("ionite CIAM Manager not initialized");if(M=`${Q.cookiesPrefix}.${M}`,typeof B!=="string")B=btoa(JSON.stringify(B));let ne;if(J instanceof Date)ne=`Expires=${J.toUTCString()}`;else if(typeof J==="number")ne=`Max-Age=${J}`;else throw Error("Invalid expires type",J);if(B.length>4000)throw Error(`Error setting cookie: ${M}. Cookie length is: ${B.length}`);return`${M}=${B}; ${ne}; Path=${Q.cookiesPath}; HttpOnly;${Q.cookiesSecure?" Secure;":""} SameSite=${F};`}function Le(M){if(!Q)throw Error("ionite CIAM Manager not initialized");return`${Q.cookiesPrefix}.${M}=; Max-Age=0; Path=${Q.cookiesPath}; HttpOnly;${Q.cookiesSecure?" Secure;":""} SameSite=${Q.cookiesSameSite};`}function ye(M,B,J=!1){if(!Q)throw Error("ionite CIAM Manager not initialized");let F=B.headers.get("cookie");if(!F)return null;let ne=`${Q.cookiesPrefix}.${M}`,pe=F.split(";").find((se)=>se.trim().startsWith(`${ne}=`));if(!pe)return null;let de=pe.indexOf("="),re=pe.substring(de+1).trim();if(!J)return re;try{let se=atob(re);return JSON.parse(se)}catch(se){return k.error("[CIAM] Failed to parse cookie",{"ion.operation":"cookie.parse","ion.outcome":"failure",cookieName:ne},se),null}}function _e(M){return`cstate_${M}`}async function Ne(M,B,J,F){let ne=await Q.afterLogin?.({...B,request:M,context:J}),pe=wt(ne,"/",M.url);if(pe.response)return At(pe.response,F.map(([,de])=>de));return new Response(B.ok?"Authentication successful, redirecting":"Authentication failed, redirecting",{status:302,headers:[["Location",pe.location],...F]})}function $e(M,B){return["Set-Cookie",ke("session",M,B)]}function tt(M){if(!M)return;if(M instanceof Date)return M;let B=new Date(M);return Number.isNaN(B.getTime())?void 0:B}async function Ge(M){let B=ye("session",M);if(!B)return;let J=await X().get(B);if(J&&Q.tenantId&&J.tenantId&&J.tenantId!==Q.tenantId)return;if(J?.authType!=="ciam")return;let F=tt(J.expiresAt);if(F&&Date.now()>F.getTime()){await X().delete(B);return}return J}async function Je(M){if(!Q)throw Error("ionite CIAM Manager not initialized");Pe();let B=H.get(M);if(B)return B;let J=nt(M);return H.set(M,J),J}async function nt(M){try{let B=await Ge(M);if(!B?.claims?.sub)return{status:"unauthenticated"};return{status:"authenticated",value:ot(B.claims)}}catch(B){return k.error("CIAM session resolution failed",{"ion.operation":"ciam.session","ion.outcome":"degraded"},B),{status:"degraded",error:B instanceof Error?B:void 0}}}async function Ut(M){let B=await Je(M);return B.status==="authenticated"?B.value:void 0}async function Rt(M){if(!Q)throw Error("ionite CIAM Manager not initialized");Pe();let B;try{B=await Ut(M)}catch{B=void 0}let J=await Q.beforeLogout?.({request:M,user:B});try{let fe=ye("session",M);if(fe)await X().delete(fe)}catch(fe){k.warn("Failed to delete CIAM session",{"ion.operation":"session.delete","ion.outcome":"degraded"},fe)}let F=[["Set-Cookie",Le("session")]],ne=await Q.afterLogout?.({request:M,context:J}),pe=wt(ne,"/",M.url);if(pe.response)return At(pe.response,F.map(([,fe])=>fe));let de=pe.location??"/",re=M.headers.get("accept");if(re?.includes("application/json")||re?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:de}),{status:200,headers:[["Content-Type","application/json"],...F]});return new Response("Logged out",{status:302,headers:[["Location",de],...F]})}function Et(M){return M.id||M.email||`ciam-${M.userName}`}function Dt(M,B,J){return{sub:Et(M),iss:en,aud:en,typ:Ss,exp:Math.floor(J.getTime()/1000),iat:Math.floor(Date.now()/1000),email:M.email,name:M.name,preferred_username:M.userName,picture:M.avatar,sid:B}}function Lt(M,B,J){return{sub:M,iss:en,aud:en,typ:ks,exp:Math.floor(J.getTime()/1000),iat:Math.floor(Date.now()/1000),sid:B,scope:"openid profile email"}}function ot(M){let B=M.exp?new Date(M.exp*1000):new Date;return{id:M.sub,userName:M.preferred_username??"",name:M.name??"",email:M.email??"",avatar:M.picture,userType:"customer",ciam:{profile:M,scope:"openid profile email",tokenType:"Bearer",expires:B}}}async function vt(M){if(!Q)throw Error("ionite CIAM Manager not initialized");if(!V)return new Response(JSON.stringify({error:"Workload authentication required"}),{status:401,headers:{"Content-Type":"application/json"}});if(!await V.getWorkloadIdentity(M))return new Response(JSON.stringify({error:"Unauthorized: Valid workload token required"}),{status:401,headers:{"Content-Type":"application/json"}});let J,F;try{if(!M.headers.get("content-type")?.includes("application/json"))return new Response(JSON.stringify({error:"Content-Type must be application/json"}),{status:400,headers:{"Content-Type":"application/json"}});let Oe=await M.text(),Ee=JSON.parse(Oe);F=typeof Ee?.redirect==="string"&&Ee.redirect.length>0?Ee.redirect:void 0;let ae={userName:Ee.userName,name:Ee.name,email:Ee.email,avatar:Ee.avatar},ee=await y.customer.validate(ae);if(ee.issues)return new Response(JSON.stringify({error:"Missing required fields: userName, name, email"}),{status:400,headers:{"Content-Type":"application/json"}});J=ee.value}catch(Ie){return new Response(JSON.stringify({error:"Invalid JSON in request body"}),{status:400,headers:{"Content-Type":"application/json"}})}let pe=new URL(M.url).searchParams.get("ttl"),de=pe?parseInt(pe,10):Q.magicLinkTtl??3600;if(Number.isNaN(de)||de<=0)return new Response(JSON.stringify({error:"Invalid TTL parameter"}),{status:400,headers:{"Content-Type":"application/json"}});let re=We(32),se=new Date(Date.now()+de*1000);if(!Q.magicLinkStore)return new Response(JSON.stringify({error:"Magic link store not configured"}),{status:501,headers:{"Content-Type":"application/json"}});try{await Q.magicLinkStore.create(re,J,se)}catch(Ie){return k.error("Error creating magic link",{"ion.operation":"magic_link.create","ion.outcome":"failure"},Ie),new Response(JSON.stringify({error:"Failed to create magic link"}),{status:500,headers:{"Content-Type":"application/json"}})}let fe=new URL(M.url),be=Q.magicLinkLoginUrl||"/magic-link/login",me=new URL(be,fe.origin);if(me.searchParams.set("token",re),F)me.searchParams.set("redirect",F);return new Response(JSON.stringify({magicLink:me.toString(),expiresAt:se.toISOString()}),{status:200,headers:{"Content-Type":"application/json"}})}async function gt(M){if(!Q)throw Error("ionite CIAM Manager not initialized");Pe();let J=new URL(M.url).searchParams.get("token");if(!J)return Ne(M,{ok:!1,error:Error("Missing magic-link token")},void 0,[]);if(!Q.magicLinkStore)return Ne(M,{ok:!1,error:Error("Magic link store not configured")},void 0,[]);let F=await Q.magicLinkStore.getAndDelete(J);if(!F)return Ne(M,{ok:!1,error:Error("Magic link invalid, expired, or already used")},void 0,[]);let ne=new Date(Date.now()+(Q.sessionTtl??86400)*1000),pe=We(32),de=Et(F.customer),re=Dt(F.customer,pe,ne),se=Lt(de,pe,ne),fe=ot(re),be;try{let Ie={sid:pe,sub:de,authType:"ciam",tenantId:Q.tenantId,expiresAt:ne,claims:re,accessClaims:se,createdAt:new Date};await X().create(Ie),be=Ie}catch(Ie){throw k.warn("Failed to create session",{"ion.operation":"session.create","ion.outcome":"degraded"},Ie),Ie}if(Q.customerStore)try{let Ie=fe.id;if(Ie){let Oe=new Date,Ee=await Q.customerStore.get(Ie);if(Ee||Q.enableJitUserProvisioning){let ae={...Ee??{},...fe,id:Ie,tenantId:Ee?.tenantId,createdAt:Ee?.createdAt??Oe,updatedAt:Oe,userType:Ee?.userType??"customer"};await Q.customerStore.upsert(ae)}}}catch(Ie){k.warn("Failed to store customer",{"ion.operation":"customer.store","ion.outcome":"degraded"},Ie)}let me=[$e(pe,ne)];return Ne(M,{ok:!0,user:fe,session:be},void 0,me)}function at(M,B=200,J=[]){return new Response(JSON.stringify(M),{status:B,headers:[["Content-Type","application/json"],...J]})}function It(M,B){try{return new URL(M).toString()}catch{let J=new URL(B).origin,F=Q.cookiesSecure?J.replace(/^http:\/\//,"https://"):J;return new URL(M,F).toString()}}function lt(){let M=Q.customerLoginUrl||"/auth/customer/login",B=M.includes("?")?"&":"?";return hn(Q.providers).map(({name:J,config:F})=>{let ne=yn(F);return{name:J,type:F.type,displayName:ne.displayName,loginUrl:`${M}${B}provider=${encodeURIComponent(J)}`,iconUrl:ne.iconUrl,colors:ne.colors,url:ne.url}})}async function Ze(M){if(!M)return{};let{authorizationUrl:B,tokenUrl:J,jwksUri:F,userInfoUrl:ne}=M,pe=M.config.authority;if(pe&&(!B||!J||M.flow==="id_token"&&!F))try{let re=await xn(pe);B=B??re.authorizationUrl,J=J??re.tokenUrl,F=F??re.jwksUri,ne=ne??re.userInfoUrl}catch(re){k.error("CIAM provider OIDC discovery failed",{"ion.operation":"ciam.oidc.discovery","ion.outcome":"failure"},re)}return{authorizationUrl:B,tokenUrl:J,jwksUri:F,userInfoUrl:ne}}async function yt(M){if(M.type==="apple"){let{teamId:B,keyId:J,privateKey:F,clientId:ne}=M.config;if(B&&J&&F&&ne)return En({teamId:B,keyId:J,privateKey:F,clientId:ne})}return M.clientSecret}async function ct(M){X();let J=new URL(M.url).searchParams.get("provider");if(!J)return at({error:"Missing required query parameter: provider"},400);let F=Q.providers?.[J];if(!F||F.enabled===!1||F.type==="magic-link")return at({error:`Unknown or disabled CIAM provider: ${J}`},404);let ne=Zt(J,F);if(!ne?.clientId)return at({error:`CIAM provider ${J} is not fully configured`},500);let pe=await Ze(ne);if(!pe.authorizationUrl)return at({error:`CIAM provider ${J} is missing an authorization endpoint`},500);let de=Q.customerCallbackUrl||"/auth/customer/callback",re=It(de,M.url),se=st(),fe=st(64),be=st(),me=ne.flow==="id_token",Ie=me?await $t(fe):void 0,Oe=await Q.beforeLogin?.({request:M}),Ee=An({authorizationUrl:pe.authorizationUrl,clientId:ne.clientId,redirectUri:re,scope:ne.scope,state:se,codeChallenge:Ie,nonce:be,extraParams:ne.extraAuthParams}),ae={provider:J,state:se,codeVerifier:me?fe:void 0,nonce:be,redirectUri:re,...Oe===void 0?{}:{context:Oe}};return new Response("Redirecting to CIAM provider",{status:302,headers:[["Location",Ee],["Set-Cookie",ke(_e(se),ae,Q.loginStateTtl??600,"Lax")]]})}async function rt(M){if(M.method==="POST"){if((M.headers.get("content-type")??"").includes("application/x-www-form-urlencoded")){let J=await M.text();return Object.fromEntries(new URLSearchParams(J).entries())}}return Object.fromEntries(new URL(M.url).searchParams.entries())}async function ht(M,B){let J=M.mapClaims(B);if(!J.sub)return{ok:!1};let F=`${M.name}:${J.sub}`,ne={id:F,userName:J.userName||J.email||F,name:J.name||"",email:J.email||"",avatar:J.avatar,userType:"customer"},pe=F;if(Q.customerStore){let me=await Q.customerStore.lookup(ne)??await Q.customerStore.get(F);if(pe=me?.id??F,!me&&!Q.enableJitUserProvisioning)return k.warn("CIAM JIT customer provisioning disabled: unknown customer rejected",{"ion.operation":"customer.store","ion.outcome":"skipped"}),{ok:!1};let Ie=new Date,Oe={...me??{},...ne,id:pe,tenantId:me?.tenantId,createdAt:me?.createdAt??Ie,updatedAt:Ie,userType:me?.userType??"customer"};await Q.customerStore.upsert(Oe)}let de=new Date(Date.now()+(Q.sessionTtl??86400)*1000),re=st(32),se={sub:pe,iss:M.name,aud:M.clientId,exp:Math.floor(de.getTime()/1000),iat:Math.floor(Date.now()/1000),email:J.email,name:J.name,preferred_username:J.userName??J.email,picture:J.avatar,sid:re},fe={sid:re,sub:pe,authType:"ciam",tenantId:Q.tenantId,expiresAt:de,claims:se,accessClaims:{sub:pe,sid:re,scope:M.scope},createdAt:new Date},be=X();try{await be.create(fe)}catch(me){if(!await be.get(re))throw me;await be.update(re,fe)}return{ok:!0,claims:se,sid:re,expires:de}}async function Se(M){X();let B,J,F=(ne)=>{let pe=B?[["Set-Cookie",Le(B)]]:[];return Ne(M,{ok:!1,error:ne},J,pe)};try{let ne=await rt(M),pe=await xe.validate(ne);if(pe.issues||!pe.value)return F(Error("Invalid CIAM callback parameters"));let{code:de,state:re}=pe.value;if(!re)return F(Error("Missing CIAM callback state"));B=_e(re);let se=ye(B,M,!0);if(J=se?.context,!se?.provider||!se.state||se.state!==re)return k.warn("CIAM callback state verification failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),F(Error("CIAM callback state verification failed"));let fe=Q.providers?.[se.provider];if(!fe)return F(Error("Unknown CIAM provider"));let be=Zt(se.provider,fe);if(!be?.clientId)return F(Error("CIAM provider not configured"));let me=await Ze(be);if(!me.tokenUrl)return F(Error("CIAM provider missing token endpoint"));let Ie=await yt(be),Oe=await Tn({tokenUrl:me.tokenUrl,clientId:be.clientId,clientSecret:Ie,redirectUri:se.redirectUri||It(Q.customerCallbackUrl||"/auth/customer/callback",M.url),code:de,codeVerifier:be.flow==="id_token"?se.codeVerifier:void 0,log:k}),Ee;if(be.flow==="id_token"){let ue=be.config.authority;if(!Oe.id_token||!me.jwksUri||!ue)return F(Error("CIAM id_token flow misconfigured"));if(!se.nonce)return F(Error("CIAM callback state cookie missing nonce"));if((await De.validate(Oe)).issues)return k.warn("CIAM token response validation failed",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),F(Error("CIAM token response validation failed"));Ee=await kt({idToken:Oe.id_token,jwksUri:me.jwksUri,issuer:ue,audience:be.clientId,expectedNonce:se.nonce,log:k});let he=await je.validate(Ee);if(!he.issues)Ee=he.value}else{if(!me.userInfoUrl)return F(Error("CIAM provider missing userinfo endpoint"));Ee=await Un(me.userInfoUrl,Oe.access_token);let ue=be.config.authority;if(Oe.id_token&&me.jwksUri&&ue){let ce=await kt({idToken:Oe.id_token,jwksUri:me.jwksUri,issuer:ue,audience:be.clientId,expectedNonce:se.nonce||void 0,log:k}),he=typeof ce.sub==="string"?ce.sub:"";if(he){if(typeof Ee.sub==="string"&&Ee.sub.length>0&&Ee.sub!==he)return k.warn("CIAM UserInfo sub does not match verified id_token sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),F(Error("CIAM UserInfo sub mismatch"));Ee.sub=he}}if(typeof Ee.sub!=="string"||Ee.sub.length===0)return k.warn("CIAM UserInfo response missing sub",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"}),F(Error("CIAM UserInfo response missing sub"))}let ae=await ht(be,Ee);if(!ae.ok)return F(Error("Failed to persist CIAM customer"));let ee=ot(ae.claims);k.info("CIAM third-party sign-in succeeded",{"ion.operation":"ciam.oidc.callback","ion.outcome":"success",provider:be.name});let oe=[["Set-Cookie",Le(B)],$e(ae.sid,ae.expires)];return Ne(M,{ok:!0,user:ee,session:void 0},J,oe)}catch(ne){return k.error("Error during CIAM third-party sign-in callback",{"ion.operation":"ciam.oidc.callback","ion.outcome":"failure"},ne),F(ne)}}async function ve(M){if(!Q)throw Error("ionite CIAM Manager not initialized");Pe();let B=Q.magicLinkUrl||"/magic-link",J=Q.magicLinkLoginUrl||"/magic-link/login",F=Q.logoutUrl||"/auth/customer/logout",ne=Q.customerLoginUrl||"/auth/customer/login",pe=Q.customerCallbackUrl||"/auth/customer/callback",de=Q.customerProvidersUrl||"/auth/customer/providers",re=new URL(M.url).pathname,se=(ae)=>{if(!ae)return;try{return new URL(ae).pathname}catch{return ae.startsWith("/")?ae:`/${ae}`}};if(se(B)===re&&M.method==="POST")return vt(M);if(se(J)===re&&M.method==="GET")return gt(M);if(se(F)===re&&M.method==="GET")return Rt(M);if(se(de)===re&&M.method==="GET")return at({providers:lt()});if(se(ne)===re&&M.method==="GET")return ct(M);if(se(pe)===re&&(M.method==="GET"||M.method==="POST"))return Se(M);return new Response("Not Found",{status:404})}return{...Q,getCustomer:Ut,resolveCustomer:Je,logout:Rt,handler:ve,listCustomerProviders:lt}}async function bs(y,k){return t(k,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),k.ciam?.getCustomer(y)}async function Cs(y,k){return t(k,"Ionite instance is required. Create one with ionite(source, config) and pass it to this function."),await k.ciam?.resolveCustomer(y)??{status:"unauthenticated"}}var Rs="urn:ietf:params:scim:schemas:core:2.0:User",gr="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",vs="urn:ietf:params:scim:schemas:core:2.0:Group";function _n(y,k,R){let V=(k==="group"?y.resources:void 0)?.map((G)=>typeof G==="string"?G:G.id).filter(Boolean);return{schemas:[vs,e],id:y.id,externalId:y.providerId,displayName:y.displayName??y.name,members:R,[e]:{type:k,requestable:y.requestable,riskLevel:y.riskLevel??u,providerId:y.providerId,requestUrl:y.requestUrl,source:y.source,deprecated:y.deprecated,description:y.description,resources:V&&V.length>0?V:void 0,assignableSubjectTypes:y.assignableSubjectTypes,recommendedSubjectTypes:y.recommendedSubjectTypes,attributes:r(y,o)}}}function Is(y){if(y.scimName)return y.scimName;if(!y.name)return;let[k,...R]=y.name.split(" ");return{givenName:k,familyName:R.join(" ")||void 0}}function As(y){let k={attributes:r(y,h)};if(y.ecid!==void 0)k.ecid=y.ecid;if(y.accountClass!==void 0)k.accountClass=y.accountClass;return k.ecid!==void 0||k.accountClass!==void 0||k.attributes!==void 0?k:void 0}function Ts(y){return Object.keys(y.scimSchemaExtensions??{}).filter((k)=>k.startsWith("urn:")&&y.scimSchemaExtensions?.[k]!==void 0)}function On(y){let k=y.userName||y.email||y.id||"",R=y.emails??(y.email?[{value:y.email,primary:!0}]:[]),W=new Set([Rs]);if(y.scimEnterprise!==void 0)W.add(gr);let V=As(y);if(V!==void 0)W.add(s);for(let H of Ts(y))W.add(H);let G={};if(y.scimEnterprise!==void 0)G[gr]=y.scimEnterprise;if(V!==void 0)G[s]=V;for(let[H,Y]of Object.entries(y.scimSchemaExtensions??{}))if(H.startsWith("urn:")&&H!==s&&Y!==void 0)G[H]=Y;return{schemas:Array.from(W),id:y.id,externalId:y.externalId,userName:k,displayName:y.displayName??y.name??k,name:Is(y),nickName:y.nickName,profileUrl:y.avatar,title:y.title,userType:y.userType,preferredLanguage:y.preferredLanguage,locale:y.locale,timezone:y.timezone,active:y.active??!0,emails:R,phoneNumbers:y.phoneNumbers,ims:y.ims,photos:y.photos,addresses:y.addresses,groups:y.groups,entitlements:y.entitlements,roles:y.roles,x509Certificates:y.x509Certificates,meta:{resourceType:"User",created:(y.createdAt??y.updatedAt??new Date).toISOString(),lastModified:(y.updatedAt??y.createdAt??new Date).toISOString()},...G}}function Dn(y){return{schemas:[f],id:y.id,externalId:y.externalId,userName:y.clientId??y.id,displayName:y.displayName??y.clientId??y.id,description:y.description,active:y.active??!0,ecid:y.ecid,providerId:y.providerId,requestUrl:y.requestUrl,attributes:r(y,b),meta:{resourceType:"Workload",created:(y.createdAt??y.updatedAt??new Date).toISOString(),lastModified:(y.updatedAt??y.createdAt??new Date).toISOString()}}}function Ln(y){return{schemas:[g],id:y.id,externalId:y.externalId??y.id,userName:y.userName??y.email??y.id,displayName:y.displayName??y.name??y.userName??y.id,active:y.active??!0,emails:y.emails??(y.email?[{value:y.email,primary:!0}]:void 0),providerId:y.providerId,requestUrl:y.requestUrl,attributes:r(y,S),meta:{resourceType:"Customer",created:(y.createdAt??y.updatedAt??new Date).toISOString(),lastModified:(y.updatedAt??y.createdAt??new Date).toISOString()}}}function Nn(y){return{enabled:y?.enabled!==!1,assignment:y?.assignment??"app",delta:y?.delta}}var Kt="application/scim+json",Ps="urn:ietf:params:scim:api:messages:2.0:ListResponse",Bn="urn:ietf:params:scim:api:messages:2.0:Error",Gn="urn:ietf:params:scim:schemas:core:2.0:User",Jt="urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",Kn="urn:ietf:params:scim:schemas:core:2.0:Group",xs="urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig",tn="urn:ietf:params:scim:schemas:core:2.0:ResourceType",Tt="urn:ietf:params:scim:schemas:core:2.0:Schema",Us="00000000000000000000000000000000";function Es(y){let k={timestamp:new Date().toISOString()};if(y)k.actor=y;try{let V=globalThis[Symbol.for("opentelemetry.js.api.1")]?.trace?.getActiveSpan?.()?.spanContext?.(),G=V?.traceId;if(G&&G!==Us){if(k.traceId=G,V?.spanId)k.spanId=V.spanId}}catch{}return k}class Ht extends Error{constructor(y){super(y);this.name="SubjectTypeNotAssignableError",Object.setPrototypeOf(this,Ht.prototype)}}async function Cr(y,k,R,W){let V=R.subjectType;if(!d.includes(V))throw new Ht(`Cannot grant ${R.targetType} "${n(R.target)}" to a "${V}" principal: only [${d.join(", ")}] principals are assignable on this platform.`);let G=x(k,y);if(!G&&!W)return;let H=n(R.target),Y;if(W)Y=await W.getNode(R.targetType,H);else if(G)Y=await(R.targetType==="group"?G.groups:R.targetType==="role"?G.roles:G.permissions).get(H);if(!Y)return;let Q=Y.assignableSubjectTypes;if(!Q||Q.length===0||!Q.includes(V))throw new Ht(`Cannot grant ${R.targetType} "${H}" to a "${V}" principal: this entitlement restricts assignment to [${(Q??[]).join(", ")||"none"}].`)}async function Ms(y,k){let R=A(y.codeCatalog,n(k.target));if(!R)return;if(R.kind!==k.targetType)throw Error(`Cannot grant ${k.targetType} "${R.entity.id}": code declares that id as ${R.kind}.`);if(!y.catalogStore)throw Error(`Cannot grant code entitlement "${R.entity.id}": no AccessCatalogStore is wired for materialization.`);await v(R.kind,R.entity,I(y.catalogStore,R.kind))}async function js(y,k,R,W){await Ms(y,k),await Cr(y.catalogStore,y.codeCatalog,k,W);let V={...k,status:k.status??"active",provenance:k.provenance??Es()};if(V.id=c(V),await y.accessStore?.grant(V),y.accessIndex&&(y.catalogStore||y.codeCatalog)){let G=await O(V,{catalog:y.catalogStore,code:y.codeCatalog,resources:y.resources,cache:W});await y.accessIndex.materialize(V.id,G)}return R?.push({op:"add",change:V}),V}async function Bt(y,k,R){let W=k.id??c(k);await y.accessStore?.revoke(k),await y.accessIndex?.removeByRoot(W),R?.push({op:"delete",change:{...k,id:W}})}async function sn(y,k){let R=await _s(y,k),W=await Ds(y,k);return{oaa:R,delta:W}}async function _s(y,k){if(k.length===0||!y.authz.oaa.isReady())return{status:"skipped"};return Ct(y,"authz.oaa.push","OAA incremental access push failed after SCIM mutation; full sync will reconcile",()=>y.authz.oaa.pushAccessChanges(k),{count:k.length})}async function Ct(y,k,R,W,V){try{return await W(),{status:"ok"}}catch(G){return y.log?.warn(R,{"ion.operation":k,"ion.outcome":"degraded",...V,error:dt(G)}),{status:"degraded",reason:dt(G)}}}var Os=6;async function Ds(y,k){let R=y.iamDelta;if(!R?.isReady()||k.length===0)return{status:"skipped"};let W=new Map;for(let Q of k){let X=`${Q.change.subjectType}:${n(Q.change.subject)}\x00${Q.change.targetType}:${n(Q.change.target)}`;W.set(X,Q)}let V=[...W.values()],G=V.map(({op:Q,change:X})=>()=>Q==="add"?R.onGrant(X):R.onRevoke(X)),Y=(await Ls(G,Os)).filter((Q)=>Q.status==="rejected");if(Y.length>0)return y.log?.warn("IAM delta egress degraded after SCIM mutation; IAM server reconcile/aggregation will recover",{"ion.operation":"iam.delta.egress","ion.outcome":"degraded",failed:Y.length,total:V.length,error:dt(Y[0]?.reason)}),{status:"degraded",reason:dt(Y[0]?.reason)};return{status:"ok"}}async function Ls(y,k){let R=Array(y.length),W=0,V=async()=>{while(!0){let H=W++;if(H>=y.length)return;let Y=y[H];if(!Y)continue;try{R[H]={status:"fulfilled",value:await Y()}}catch(Q){R[H]={status:"rejected",reason:Q}}}},G=Array.from({length:Math.min(k,y.length)},V);return await Promise.all(G),R}class an extends Error{constructor(y){super(y);this.name="DerivedRevokeError",Object.setPrototypeOf(this,an.prototype)}}class Ot extends Error{constructor(y,k,R=!1){super(y);this.name="ScimMutationError",this.summary=k,this.clientError=R,Object.setPrototypeOf(this,Ot.prototype)}}function Re(y,k,R){return new Response(JSON.stringify({schemas:[Bn],status:String(y),scimType:R,detail:k}),{status:y,headers:{"Content-Type":Kt}})}function ft(y,k){let R=k?.totalResults??y.length,W=k?.startIndex??1,V=k?.itemsPerPage??y.length;return new Response(JSON.stringify({schemas:[Ps],totalResults:R,startIndex:W,itemsPerPage:V,Resources:y}),{status:200,headers:{"Content-Type":Kt}})}function Xe(y,k=200,R){let W=new Headers({"Content-Type":Kt});if(R)W.set("Location",R);return new Response(JSON.stringify(y),{status:k,headers:W})}function yr(y){return Re(y.clientError?409:500,`${y.message}; authz mutation summary: ${JSON.stringify(y.summary)}`,y.clientError?"mutability":"invalidValue")}function Gt(y){return c(y)}function Wn(y,k){return on(hr(y),hr(k))}function hr(y){let k=new Map;if(!y?.id)return k;for(let R of y.groups??[]){let W={subject:y.id,subjectType:"user",targetType:"group",target:R.value,metadata:R.display||R.type?{display:R.display,type:R.type}:void 0};k.set(Gt(W),W)}for(let R of y.roles??[]){let W={subject:y.id,subjectType:"user",targetType:"role",target:R.value,metadata:R.display||R.type?{display:R.display,type:R.type,primary:R.primary}:void 0};k.set(Gt(W),W)}for(let R of y.entitlements??[]){let W={subject:y.id,subjectType:"user",targetType:"permission",target:R.value,metadata:R.display||R.type?{display:R.display,type:R.type,primary:R.primary}:void 0};k.set(Gt(W),W)}return k}class cn extends Error{constructor(y){super(y);this.name="AmbiguousMemberSubjectTypeError",Object.setPrototypeOf(this,cn.prototype)}}function Ns(y,k,R){if(y.type==="Group")return;if(y.type==="Workload")return"workload";if(y.type==="User")return"user";if(y.type==="Customer")return"customer";let W=k??[];if(W.length===1)return W[0];throw new cn(`SCIM Group member "${y.value}" of entitlement "${R}" omits type, and the entitlement is assignable to more than one principal kind [${W.join(", ")||"none"}]. Set members[].type to User, Workload, or Customer.`)}function nn(y,k,R,W,V){let G=new Map,H=W&&W.length>0?W:void 0;for(let Y of y??[]){let Q=Ns(Y,V,R);if(!Q)continue;let X={subject:Y.value,subjectType:Q,targetType:k,target:R,resources:H,metadata:Y.display||Y.type?{display:Y.display,type:Y.type}:void 0};G.set(Gt(X),X)}return G}function Vn(y){let k=y[e]?.resources;return k&&k.length>0?k:void 0}function Ws(y,k){let R=(V,G)=>[...V??[]].sort().join(",")===[...G??[]].sort().join(","),W=y[e];if(W?.type!==void 0&&W.type!==k.kind)return!0;if(W?.requestable!==void 0&&W.requestable!==k.entity.requestable)return!0;if(W?.resources!==void 0&&!R(W.resources,Jn(k.entity)))return!0;if(W?.assignableSubjectTypes!==void 0&&!R(W.assignableSubjectTypes,k.entity.assignableSubjectTypes))return!0;if(W?.recommendedSubjectTypes!==void 0&&!R(W.recommendedSubjectTypes,k.entity.recommendedSubjectTypes))return!0;return!1}function Vs(y,k){let R=(G,H)=>[...G??[]].sort().join(",")===[...H??[]].sort().join(","),W=y[e],V=k[e];if(W?.type!==void 0&&W.type!==V?.type)return!0;if(W?.requestable!==void 0&&W.requestable!==V?.requestable)return!0;if(W?.resources!==void 0&&!R(W.resources,V?.resources))return!0;if(W?.assignableSubjectTypes!==void 0&&!R(W.assignableSubjectTypes,V?.assignableSubjectTypes))return!0;if(W?.recommendedSubjectTypes!==void 0&&!R(W.recommendedSubjectTypes,V?.recommendedSubjectTypes))return!0;return!1}function qs(y){let k=new Map;for(let R of y)k.set(Gt(R),R);return k}async function Pt(y,k,R,W,V,G){let H=[],Y=new Set,Q=(Pe,xe)=>`${xe}\x00${Pe}`,X=G?G.get(`${R}:${W}`)??[]:k?(await k.listByTarget(R,W)).items:[];for(let Pe of X){let xe=n(Pe.subject),je=Pe.metadata,De=Pe.subjectType==="workload"?"Workload":Pe.subjectType==="customer"?"Customer":je?.type??"User",We=Q(xe,De);if(Y.has(We))continue;Y.add(We),H.push({value:xe,...je?.display?{display:je.display}:{},type:De})}for(let Pe of V??[]){if(Pe.targetType!==R||n(Pe.target)!==W)continue;let xe=n(Pe.subject),je=Q(xe,"Workload");if(Y.has(je))continue;Y.add(je),H.push({value:xe,type:"Workload"})}if(R==="group"){let Pe=await y.groups.get(W);for(let xe of Pe?.groups??[]){let je=n(xe),De=Q(je,"Group");if(!je||Y.has(De))continue;Y.add(De),H.push({value:je,type:"Group"})}}return H.length>0?H:void 0}function on(y,k){let R=[];for(let[W,V]of k)if(!y.has(W))R.push({action:"grant",change:V});for(let[W,V]of y)if(!k.has(W))R.push({action:"revoke",change:V});return R}async function qn(y,k){if(y.oaa.isReady())await y.oaa.pushUser(k)}async function Sr(y,k,R){if(k?.externalId&&k.externalId!==R.externalId)await y?.onUserDelete(k.externalId);await y?.onUserUpsert(R)}async function jt(y,k,R,W){let V={metadataApplied:!1,access:[]},G={status:"skipped"},H=[],Y=new _(y.catalogStore,y.resources,y.codeCatalog);try{try{await k(),V.metadataApplied=!0}catch(Q){for(let X of R)V.access.push({change:X.change,status:"rolled_back"});throw V.metadataApplied=!1,new Ot(`SCIM metadata write failed: ${dt(Q)}`,V,!1)}if(W?.oaa)await Ct(y,"authz.oaa.metadata","OAA metadata projection failed after SCIM write; full sync will reconcile",W.oaa);if(W?.delta&&y.iamDelta?.isReady())G=await Ct(y,"iam.delta.egress","IAM delta metadata projection failed after SCIM write; full aggregation will reconcile",W.delta);for(let Q=0;Q<R.length;Q++){let X=R[Q];try{if(X.action==="grant")await js(y,X.change,H,Y);else await Ks(y,X.change,H);V.access.push({change:X.change,status:"applied"})}catch(Pe){V.access.push({change:X.change,status:"failed",error:Pe});for(let je=Q+1;je<R.length;je++)V.access.push({change:R[je].change,status:"rolled_back"});let xe=Pe instanceof an||Pe instanceof Ht;if(!xe)await Bs(y,X.change,Y);throw new Ot(xe?dt(Pe):`SCIM access mutation failed: ${dt(Pe)}`,V,xe)}}return V}finally{await zs(y),V.egress=await sn(y,H),V.egress.delta=$s(G,V.egress.delta),Gs(y,V)}}function $s(y,k){if(y.status==="degraded")return y;if(k.status==="degraded")return k;return y.status==="ok"||k.status==="ok"?{status:"ok"}:{status:"skipped"}}function dt(y){return y instanceof Error?y.message:String(y)}async function zs(y){try{await y.settleAuthz?.()}catch{}}async function Bs(y,k,R){if(!y.accessIndex||!y.catalogStore&&!y.codeCatalog||!y.accessStore)return;let W=n(k.subject);if(!W)return;let V=k.subjectType;try{await z(W,V,{accessStore:y.accessStore,accessIndex:y.accessIndex,catalogStore:y.catalogStore,code:y.codeCatalog,resources:y.resources},R)}catch(G){y.log?.warn("Per-subject reconcile after failed SCIM access mutation failed",{"ion.operation":"authz.reconcile.subject.repair","ion.outcome":"degraded",subject:W,subjectType:V,error:dt(G)})}}function Gs(y,k){if(!y.onAccessMutation)return;try{y.onAccessMutation(k)}catch{}}async function Ks(y,k,R){if(y.accessStore){let W=k.id??c(k);if(!await y.accessStore.get(W)){if((y.accessIndex?await y.accessIndex.has(k.subject,k.targetType,k.target,k.resources?.[0],k.subjectType):{allow:!1}).allow)throw new an(`Cannot revoke ${k.targetType} "${n(k.target)}" for "${n(k.subject)}": it is not a directly granted root (it is derived from group/role membership). Remove the granting group/role instead.`);await Bt(y,k,R);return}}await Bt(y,k,R)}function _t(y){let k=y[e]?.type??"group";if(k==="group"||k==="role"||k==="permission")return k;throw Error(`Unsupported ionite SCIM Group authz type "${String(k)}"`)}async function $n(y,k,R){if(!y.oaa.isReady())return;if(R==="role"){await y.oaa.pushRole(k);return}if(R==="permission"){await y.oaa.pushPermission(k);return}await y.oaa.pushGroup(k)}function Jn(y){let k=y.resources;if(!k||k.length===0)return;let R=k.map((W)=>typeof W==="string"?W:W.id).filter(Boolean);return R.length>0?R:void 0}function xt(y,k,R){return _n(y,k,R)}function Js(y,k){let R=y[e],V={...r(R?.attributes??{},o),id:k,name:y.displayName,displayName:y.displayName,description:R?.description??y.displayName,requestable:R?.requestable,riskLevel:R?.riskLevel??u,providerId:R?.providerId??y.externalId,requestUrl:R?.requestUrl,assignableSubjectTypes:["user"]};if(R?.resources!==void 0)V.resources=R.resources;return V}function Hs(y){if(!y)return;let k=y.trim().match(/^requestable\s+eq\s+(true|false)$/i);if(!k)return;return{requestable:k[1]?.toLowerCase()==="true"}}function kr(y){if(!y)return;let k=y.trim().match(/^externalId\s+eq\s+"([^"]*)"$/i);return k?k[1]:void 0}function Fs(y){if(!y)return;let k=y.trim(),R=k.match(/^userName\s+eq\s+"([^"]*)"$/i);if(R)return{userName:R[1]};let W=k.match(/^externalId\s+eq\s+"([^"]*)"$/i);if(W)return{externalId:W[1]};let V=k.match(/^meta\.lastModified\s+gt\s+"([^"]*)"$/i);if(V)return{updatedAfter:V[1]};return}function Ys(y,k,R){let W=new Set(["id","schemas"]),V={...y};if(k){let G=new Set(k.split(",").map((H)=>H.trim()).filter(Boolean));for(let H of Object.keys(V))if(!W.has(H)&&!G.has(H))delete V[H]}if(R){for(let G of R.split(",").map((H)=>H.trim()).filter(Boolean))if(!W.has(G))delete V[G]}return V}function wr(y,k){let R=async(G,H,Y)=>{let Q=await y.toScim(G),X=G.id;return{...Q,id:X,meta:{...Q.meta??{},resourceType:y.resourceType,location:X?He(H,`${Y}/${encodeURIComponent(X)}`):void 0}}},W=(G,H)=>{let Y=H.op.toLowerCase();if(!H.path){if(Y!=="remove"&&H.value&&typeof H.value==="object"&&!Array.isArray(H.value))Object.assign(G,H.value);return}if(Y==="remove"){delete G[H.path];return}G[H.path]=H.value};return{handler:async(G,H)=>{if(!await k.validateAuth(G))return Re(401,"Authorization required");let Y=new URL(G.url),Q=H?.basePath??`/${y.resourceType}s`,X=Y.pathname;if(X.startsWith(Q))X=X.substring(Q.length);let Pe=X.match(/^\/([^/]+)$/),xe=Pe?.[1]?decodeURIComponent(Pe[1]):void 0,je=Y.searchParams.get("attributes"),De=Y.searchParams.get("excludedAttributes"),We=(ke)=>Ys(ke,je,De);try{if(xe){if(G.method==="GET"){let ke=await y.store.get(xe);if(!ke)return Re(404,`${y.resourceType} not found`);return Xe(We(await R(ke,G,Q)))}if(G.method==="PUT"||G.method==="PATCH"){let ke=await y.store.get(xe);if(!ke)return Re(404,`${y.resourceType} not found`);let Le=await G.json(),ye=Le;if(G.method==="PATCH"){let Ge=Le.Operations;if(!Array.isArray(Ge))return Re(400,"PATCH requires Operations","invalidSyntax");let Je=await y.toScim(ke);for(let nt of Ge)W(Je,nt);ye=Je}let _e=await bt(y.validator,ye);if(_e.issues)return Re(400,_e.issues.map((Ge)=>Ge.message).join("; "),"invalidValue");let Ne=G.method==="PATCH"?"patch":"replace",$e=await y.store.upsert({...await y.fromScim(_e.value,{existing:ke,mode:Ne}),id:ke.id??xe});if(ke.active!==$e.active)await k.accessIndex?.setSubjectDisabled?.($e.id,y.subjectType,$e.active===!1);let tt=$e.id?He(G,`${Q}/${encodeURIComponent($e.id)}`):void 0;for(let Ge of y.projections??[])await Ct(k,`${Ge.channel}.${y.subjectType}.upsert`,`${y.resourceType} projection degraded after SCIM upsert; aggregation will reconcile`,()=>Ge.upsert($e,ke));return Xe(We(await R($e,G,Q)),200,tt)}if(G.method==="DELETE"){let ke=await y.store.get(xe);if(!ke)return Re(404,`${y.resourceType} not found`);if(k.revokeSubjectAccess)await k.revokeSubjectAccess(xe,y.subjectType);await y.store.delete(xe),await k.accessIndex?.setSubjectDisabled?.(xe,y.subjectType,!1);for(let Le of y.projections??[])await Ct(k,`${Le.channel}.${y.subjectType}.delete`,`${y.resourceType} projection degraded after SCIM delete; aggregation will reconcile`,()=>Le.delete(ke));return new Response(null,{status:204})}return Re(405,"Method not allowed")}if(G.method==="GET"){let ke=parseInt(Y.searchParams.get("startIndex")??"",10),Le=parseInt(Y.searchParams.get("count")??"",10),ye=ke!=null&&!Number.isNaN(ke)?Math.max(0,ke-1):0,_e=Le!=null&&!Number.isNaN(Le)?Le:void 0,Ne=Fs(Y.searchParams.get("filter"));if(Ne?.externalId!==void 0){let Ge=y.store.getByExternalId?await y.store.getByExternalId(Ne.externalId):await y.store.lookup({externalId:Ne.externalId}),Je=Ge?[We(await R(Ge,G,Q))]:[];return ft(Je,{totalResults:Je.length,startIndex:1,itemsPerPage:Je.length})}let $e=await y.store.list({start:ye,limit:_e,filter:Ne}),tt=await Promise.all($e.items.map(async(Ge)=>We(await R(Ge,G,Q))));return ft(tt,{totalResults:$e.total,startIndex:ye+1,itemsPerPage:$e.count})}if(G.method==="POST"){let ke=await G.json(),Le=await bt(y.validator,ke);if(Le.issues)return Re(400,Le.issues.map((Ne)=>Ne.message).join("; "),"invalidValue");let ye=await y.store.upsert(await y.fromScim(Le.value,{mode:"create"}));if(ye.active===!1)await k.accessIndex?.setSubjectDisabled?.(ye.id,y.subjectType,!0);for(let Ne of y.projections??[])await Ct(k,`${Ne.channel}.${y.subjectType}.upsert`,`${y.resourceType} projection degraded after SCIM create; aggregation will reconcile`,()=>Ne.upsert(ye,void 0));let _e=ye.id?He(G,`${Q}/${encodeURIComponent(ye.id)}`):void 0;return Xe(We(await R(ye,G,Q)),201,_e)}return Re(405,"Method not allowed")}catch(ke){if(T(ke))return Re(409,ke.message,"uniqueness");return Re(500,ke instanceof Error?ke.message:"Internal error")}}}}async function Xs(y,k,R,W){let V=[],G=[["group",y.groups],["role",y.roles],["permission",y.permissions]];for(let[Y,Q]of G)for await(let X of i((Pe,xe)=>Q.list({start:Pe,limit:xe,filter:{requestable:!0}})))if(X.providerId===R)V.push({entity:X,type:Y});if(V.length>1)throw new m(`Ambiguous providerId "${R}": ${V.length} entitlements share it (${V.map((Y)=>`${Y.type}:${Y.entity.id}`).join(", ")})`,"unique_violation","providerId");let H=V[0];if(H?.entity.requestable!==!0)return;return xt(H.entity,H.type,await Pt(y,k,H.type,H.entity.id,W))}async function Zs(y,k,R,W){let V=Math.max(0,R.start),G=R.limit!=null?V+R.limit:void 0,H={start:0,limit:G,filter:R.filter},[Y,Q,X]=await Promise.all([y.groups.list(H),y.roles.list(H),y.permissions.list(H)]),Pe=[...Y.items.map((ke)=>({entity:ke,type:"group"})),...Q.items.map((ke)=>({entity:ke,type:"role"})),...X.items.map((ke)=>({entity:ke,type:"permission"}))],xe=Y.total+Q.total+X.total,je=Pe.slice(V,G),De=k?.listByTargets?await k.listByTargets(je.map(({entity:ke,type:Le})=>({targetType:Le,target:ke.id}))):void 0,We=await Promise.all(je.map(async({entity:ke,type:Le})=>xt(ke,Le,await Pt(y,k,Le,ke.id,W,De))));return{resources:We,total:xe,count:We.length}}async function zt(y,k,R,W){let[V,G,H]=await Promise.all([y.groups.get(R),y.roles.get(R),y.permissions.get(R)]);if(V)return xt(V,"group",await Pt(y,k,"group",R,W));if(G)return xt(G,"role",await Pt(y,k,"role",R,W));if(H)return xt(H,"permission",await Pt(y,k,"permission",R,W));return}async function zn(y,k,R,W){let V=_t(k),G=V==="role"?await y.roles.get(R):V==="permission"?await y.permissions.get(R):await y.groups.get(R),H=Js(k,R),Y=G?.assignableSubjectTypes&&G.assignableSubjectTypes.length>0?G.assignableSubjectTypes:["user"],Q={...G??{},...H,source:G?.source??"scim",assignableSubjectTypes:Y},X=W?W.displayName??W.name:G?.name;if(H.displayName===X)delete Q.displayName;if(H.riskLevel===(W?.riskLevel??u))delete Q.riskLevel;let Pe=r(H,o),xe=W?r(W,o):void 0;if(k[e]?.attributes!==void 0){for(let De of Object.keys(r(G??{},o)??{}))if(!(De in(Pe??{})))delete Q[De]}for(let[De,We]of Object.entries(Pe??{}))if(p(We,xe?.[De]))delete Q[De];if(W)Q.name=W.name;let je=V==="role"?y.roles.set(Q):V==="permission"?y.permissions.set(Q):y.groups.set(Q);return await je.ready(),je}async function Qs(y,k){await Promise.all([y.groups.delete(k),y.roles.delete(k),y.permissions.delete(k)])}function rn(){return crypto.randomUUID()}function bt(y,k){let R=y;if(typeof R.validate==="function")return R.validate(k);return Promise.resolve(y["~standard"].validate(k))}function ei(y){if(!y)return;try{return new URL(y).pathname}catch{return y.startsWith("/")?y:`/${y}`}}function ut(y){let k=ei(y);return k?C(k):void 0}function br(...y){for(let k of y){let R=ut(k);if(!R)continue;for(let W of["/Users","/Groups","/Workloads","/Customers"])if(R.endsWith(W))return R.slice(0,-W.length)}return}function He(y,k){return new URL(k,y.url).toString()}function ie(y,k,R,W){let{multiValued:V=!1,...G}=W??{};return{name:y,type:k,description:R,multiValued:V,...G}}function ti(y,k){return{schemas:[xs],documentationUri:k?.documentationUri,patch:{supported:!0},bulk:{supported:!1},filter:{supported:!0,maxResults:1000},changePassword:{supported:!1},sort:{supported:!1},etag:{supported:!1},authenticationSchemes:[{type:"oauthbearertoken",name:"OAuth Bearer Token",description:"Use an ionite workload bearer token for IAM discovery and provisioning requests.",primary:!0}],meta:{resourceType:"ServiceProviderConfig",location:He(y.request,`${y.basePath}/ServiceProviderConfig`)}}}function ni(y){let k=[];if(y.supportsUsers)k.push({schemas:[tn],id:"User",name:"User",description:"User Account",endpoint:y.usersUrl,schema:Gn,schemaExtensions:[{schema:Jt,required:!1},{schema:s,required:!1}],meta:{resourceType:"ResourceType",location:He(y.request,`${y.basePath}/ResourceTypes/User`)}});if(y.supportsGroups)k.push({schemas:[tn],id:"Group",name:"Group",description:"Group",endpoint:y.groupsUrl,schema:Kn,schemaExtensions:[{schema:e,required:!1}],meta:{resourceType:"ResourceType",location:He(y.request,`${y.basePath}/ResourceTypes/Group`)}});if(y.supportsWorkloads)k.push({schemas:[tn],id:"Workload",name:"Workload",description:"Workload (machine) principal",endpoint:y.workloadsUrl,schema:f,meta:{resourceType:"ResourceType",location:He(y.request,`${y.basePath}/ResourceTypes/Workload`)}});if(y.supportsCustomers)k.push({schemas:[tn],id:"Customer",name:"Customer",description:"Customer (CIAM) principal",endpoint:y.customersUrl,schema:g,meta:{resourceType:"ResourceType",location:He(y.request,`${y.basePath}/ResourceTypes/Customer`)}});return k}function ri(y){let k=[];if(y.supportsUsers)k.push({schemas:[Tt],id:Gn,name:"User",description:"User Account",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(Gn)}`)},attributes:[ie("id","string","Unique identifier for the User.",{multiValued:!1,required:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),ie("externalId","string","External identifier from the provisioning client.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",uniqueness:"none"}),ie("userName","string","Unique identifier typically used for login.",{multiValued:!1,required:!0,caseExact:!1,mutability:"readWrite",returned:"default",uniqueness:"server"}),ie("name","complex","The components of the user name.",{multiValued:!1,required:!1,mutability:"readWrite",returned:"default",subAttributes:[ie("formatted","string","The full name, including titles and suffixes.",{multiValued:!1}),ie("familyName","string","The family name of the User.",{multiValued:!1}),ie("givenName","string","The given name of the User.",{multiValued:!1}),ie("middleName","string","The middle name(s) of the User.",{multiValued:!1}),ie("honorificPrefix","string","The honorific prefix(es) of the User.",{multiValued:!1}),ie("honorificSuffix","string","The honorific suffix(es) of the User.",{multiValued:!1})]}),ie("displayName","string","The name of the User, suitable for display.",{multiValued:!1}),ie("nickName","string","The casual way to address the user.",{multiValued:!1}),ie("profileUrl","reference","A URL pointing to the User profile.",{multiValued:!1,referenceTypes:["external"]}),ie("title","string","The user title, such as Vice President.",{multiValued:!1}),ie("userType","string","The relationship between the organization and the User.",{multiValued:!1}),ie("preferredLanguage","string","Preferred written or spoken language.",{multiValued:!1}),ie("locale","string","Default location for localizing values.",{multiValued:!1}),ie("timezone","string","The User time zone.",{multiValued:!1}),ie("active","boolean","The User administrative status.",{multiValued:!1}),ie("emails","complex","Email addresses for the User.",{multiValued:!0,subAttributes:[ie("value","string","Email address value.",{multiValued:!1,required:!0}),ie("display","string","Display label for the email.",{multiValued:!1}),ie("type","string","Email type such as work or home.",{multiValued:!1}),ie("primary","boolean","Primary email indicator.",{multiValued:!1})]}),ie("phoneNumbers","complex","Phone numbers for the User.",{multiValued:!0,subAttributes:[ie("value","string","Phone number value.",{multiValued:!1,required:!0}),ie("display","string","Display label for the phone number.",{multiValued:!1}),ie("type","string","Phone number type.",{multiValued:!1}),ie("primary","boolean","Primary phone number indicator.",{multiValued:!1})]}),ie("photos","complex","Photo URLs for the User.",{multiValued:!0,subAttributes:[ie("value","reference","Photo URL.",{multiValued:!1,required:!0,referenceTypes:["external"]}),ie("display","string","Display label for the photo.",{multiValued:!1}),ie("type","string","Photo type.",{multiValued:!1}),ie("primary","boolean","Primary photo indicator.",{multiValued:!1})]}),ie("addresses","complex","Physical mailing addresses for the User.",{multiValued:!0,subAttributes:[ie("formatted","string","Formatted mailing address.",{multiValued:!1}),ie("streetAddress","string","Full street address component.",{multiValued:!1}),ie("locality","string","City or locality.",{multiValued:!1}),ie("region","string","State or region.",{multiValued:!1}),ie("postalCode","string","Postal code.",{multiValued:!1}),ie("country","string","Country.",{multiValued:!1}),ie("type","string","Address type.",{multiValued:!1}),ie("primary","boolean","Primary address indicator.",{multiValued:!1})]}),ie("groups","complex","Groups to which the User belongs.",{multiValued:!0,mutability:"readOnly",subAttributes:[ie("value","string","Group identifier.",{multiValued:!1,required:!0}),ie("$ref","reference","Reference to the Group resource.",{multiValued:!1,referenceTypes:["Group"]}),ie("display","string","Display name of the group.",{multiValued:!1}),ie("type","string","Relationship type.",{multiValued:!1})]}),ie("entitlements","complex","Entitlements for the User.",{multiValued:!0,subAttributes:[ie("value","string","Entitlement value.",{multiValued:!1,required:!0}),ie("display","string","Display value.",{multiValued:!1}),ie("type","string","Entitlement type.",{multiValued:!1}),ie("primary","boolean","Primary entitlement indicator.",{multiValued:!1})]}),ie("roles","complex","Roles for the User.",{multiValued:!0,subAttributes:[ie("value","string","Role value.",{multiValued:!1,required:!0}),ie("display","string","Display value.",{multiValued:!1}),ie("type","string","Role type.",{multiValued:!1}),ie("primary","boolean","Primary role indicator.",{multiValued:!1})]}),ie("x509Certificates","complex","Certificates issued to the User.",{multiValued:!0,subAttributes:[ie("value","string","Certificate value.",{multiValued:!1,required:!0}),ie("display","string","Display value.",{multiValued:!1}),ie("type","string","Certificate type.",{multiValued:!1}),ie("primary","boolean","Primary certificate indicator.",{multiValued:!1})]})]}),k.push({schemas:[Tt],id:Jt,name:"EnterpriseUser",description:"Enterprise User extension",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(Jt)}`)},attributes:[ie("employeeNumber","string","Numeric or alphanumeric identifier assigned to a person.",{multiValued:!1}),ie("costCenter","string","Name of a cost center.",{multiValued:!1}),ie("organization","string","Name of an organization.",{multiValued:!1}),ie("division","string","Name of a division.",{multiValued:!1}),ie("department","string","Name of a department.",{multiValued:!1}),ie("manager","complex","The User manager.",{multiValued:!1,subAttributes:[ie("value","string","Identifier of the manager User resource.",{multiValued:!1}),ie("$ref","reference","Reference to the manager User resource.",{multiValued:!1,referenceTypes:["User"]}),ie("displayName","string","Display name of the manager.",{multiValued:!1})]})]}),k.push({schemas:[Tt],id:s,name:"IoniteUser",description:"ionite User extension carrying ECID, account purpose, and AppDev custom attributes. See https://ionite.com/docs/llms-ecid.txt.",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(s)}`)},attributes:[ie("ecid","string","Enterprise Controlled ID formatted as 'ecid:<realm>:<opaque>' (realm = the minting authority's id). Correlates multiple accounts to one identity.",{multiValued:!1,caseExact:!0}),ie("accountClass","string","Account purpose (distinct from userType persona). Open value set: 'daily', 'privileged', 'break_glass', 'service'.",{multiValued:!1}),ie("attributes","complex","AppDev custom attributes. IAM may override seeded values.",{multiValued:!1,required:!1,mutability:"readWrite"})]});if(y.supportsGroups)k.push({schemas:[Tt],id:e,name:"IoniteAuthzGroup",description:"ionite authorization metadata for SCIM Group resources.",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(e)}`)},attributes:[ie("type","string","Authorization entity kind: group, role, or permission.",{multiValued:!1,required:!1}),ie("requestable","boolean","Whether this catalog entry is exposed as assignable access to IAM tooling. Only true entries are served.",{multiValued:!1,required:!1}),ie("riskLevel","string",`Advisory access-risk classification. Unset values project as ${u}; canonical values are suggestions, not a closed enum.`,{multiValued:!1,required:!1,mutability:"readWrite",canonicalValues:[...U]}),ie("providerId","string","IAM service-provider id captured when this entitlement is materialized at the destination.",{multiValued:!1,required:!1,mutability:"readWrite"}),ie("requestUrl","reference","IAM-owned deep link where a principal can request this entitlement.",{multiValued:!1,required:!1,mutability:"readWrite",referenceTypes:["external"]}),ie("source","string","Provenance of the catalog row.",{multiValued:!1,required:!1,mutability:"readOnly",canonicalValues:["code","app","scim"]}),ie("deprecated","boolean","Whether this retired entitlement may be deleted.",{multiValued:!1,required:!1,mutability:"readOnly"}),ie("description","string","Human-readable authorization entity description.",{multiValued:!1,required:!1}),ie("resources","string","Resource ids this entitlement is scoped to.",{multiValued:!0,required:!1}),ie("assignableSubjectTypes","string","AppDev-owned required audience of principal kinds (user, workload, customer) that may hold this entitlement. Read-only to IAM tooling.",{multiValued:!0,required:!1,mutability:"readOnly",canonicalValues:["user","customer","workload"]}),ie("recommendedSubjectTypes","string","AppDev advisory default principal kinds (subset of assignableSubjectTypes). Read-only to IAM tooling.",{multiValued:!0,required:!1,mutability:"readOnly",canonicalValues:["user","customer","workload"]}),ie("attributes","complex","AppDev custom attributes. IAM may override seeded values.",{multiValued:!1,required:!1,mutability:"readWrite"})]});if(y.supportsGroups)k.push({schemas:[Tt],id:Kn,name:"Group",description:"Group",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(Kn)}`)},attributes:[ie("id","string","Unique identifier for the Group.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),ie("externalId","string","External identifier from the provisioning client.",{multiValued:!1,uniqueness:"none"}),ie("displayName","string","Human-readable name for the Group.",{multiValued:!1,required:!0,uniqueness:"none"}),ie("members","complex","Members of the Group.",{multiValued:!0,subAttributes:[ie("value","string","Identifier of the member resource.",{multiValued:!1,required:!0}),ie("$ref","reference","Reference to the member resource.",{multiValued:!1,referenceTypes:["User","Group","Workload","Customer"]}),ie("display","string","Display name of the member.",{multiValued:!1}),ie("type","string","Member type.",{multiValued:!1})]})]});if(y.supportsWorkloads)k.push({schemas:[Tt],id:f,name:"Workload",description:"Workload (machine) principal",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(f)}`)},attributes:[ie("id","string","Unique identifier for the Workload.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),ie("externalId","string","External identifier from the provisioning client.",{multiValued:!1}),ie("userName","string","Login identifier, typically the OAuth clientId.",{multiValued:!1}),ie("displayName","string","Human-readable name for the Workload.",{multiValued:!1}),ie("description","string","Free-form description of the Workload.",{multiValued:!1}),ie("active","boolean","Administrative status of the Workload.",{multiValued:!1}),ie("attributes","complex","AppDev custom attributes.",{multiValued:!1,required:!1,mutability:"readWrite"})]});if(y.supportsCustomers)k.push({schemas:[Tt],id:g,name:"Customer",description:"Customer (CIAM) principal",meta:{resourceType:"Schema",location:He(y.request,`${y.basePath}/Schemas/${encodeURIComponent(g)}`)},attributes:[ie("id","string","Unique identifier for the Customer.",{multiValued:!1,mutability:"readOnly",returned:"always",uniqueness:"global"}),ie("externalId","string","External identifier from the provisioning client.",{multiValued:!1}),ie("userName","string","Unique identifier typically used for login.",{multiValued:!1}),ie("displayName","string","Human-readable name for the Customer.",{multiValued:!1}),ie("active","boolean","Administrative status of the Customer.",{multiValued:!1}),ie("emails","complex","Email addresses for the Customer.",{multiValued:!0,subAttributes:[ie("value","string","Email address.",{multiValued:!1,required:!0}),ie("primary","boolean","Whether this is the primary email.",{multiValued:!1})]}),ie("attributes","complex","AppDev custom attributes.",{multiValued:!1,required:!1,mutability:"readWrite"})]});return k}function si(y,k,R,W,V,G,H,Y,Q,X,Pe,xe,je,De,We){let ke={authz:W,settleAuthz:We,accessStore:V,accessIndex:G,catalogStore:H,codeCatalog:Y,resources:Q,log:k,iamDelta:xe,onAccessMutation:je};if(!X&&!Pe)return;let ye={...X,...Pe},_e=ye.users?.enabled!==!1,Ne=ye.groups?.enabled!==!1,$e=ye.workloads?.enabled!==!1,tt=ye.customers?.enabled!==!1;if(Boolean(ye.url||ye.userStore||H||Y)&&!R)k.error("IAM requires workload identity for SCIM push/pull operations",{"ion.operation":"workload.require","ion.outcome":"failure"});function Je(){if(!R)throw k.error("IAM requires workload identity for SCIM push/pull operations",{"ion.operation":"workload.require","ion.outcome":"failure"}),Error("IAM requires workload identity for SCIM push/pull operations");return R}async function nt(Se){let ve=Je(),M=Se.headers.get("Authorization");if(!M?.startsWith("Bearer "))return!1;try{let B=M.substring(7);return(await ve.validateToken(B)).valid}catch{return!1}}async function Ut(){let Se=Je(),ve=typeof Se.getServerToken==="function"?await Se.getServerToken():await Se.getToken();return new Headers({"Content-Type":Kt,Accept:Kt,Authorization:`Bearer ${ve}`})}async function Rt(Se,ve,M,B){if(!ye.url)throw Error("IAM URL not configured for outgoing requests");let J=`${ye.url}${ve}`;try{let F=await Ut(),ne=await fetch(J,{method:Se,headers:F,body:M?JSON.stringify(M):void 0}),pe=await ne.json();if(!ne.ok)return{success:!1,error:pe,status:ne.status};let de=await B["~standard"].validate(pe);if(de.issues)return k.error("SCIM response validation failed",{"ion.operation":"scim.response.validate","ion.outcome":"failure",validationIssues:de.issues}),{success:!1,error:{schemas:[Bn],status:"400",scimType:"invalidValue",detail:`Response validation failed: ${de.issues.map((re)=>re.message).join("; ")}`},status:400};return{success:!0,data:de.value,status:ne.status}}catch(F){return{success:!1,error:{schemas:[Bn],status:"500",detail:F instanceof Error?F.message:"Unknown error occurred"},status:500}}}function Et(){return ye.url}function Dt(Se,ve){let M=ut(ve?.usersUrl??ye.usersUrl??"/api/iam/Users")??"/api/iam/Users",B=ut(ve?.groupsUrl??ye.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",J=ut(ve?.workloadsUrl??ye.workloadsUrl??"/api/iam/Workloads")??"/api/iam/Workloads",F=ut(ve?.customersUrl??ye.customersUrl??"/api/iam/Customers")??"/api/iam/Customers",ne=ut(ve?.discovery?.basePath??ye.discovery?.basePath)??br(M,B,J,F);if(!ne)return;return{request:Se,basePath:ne,usersUrl:M,groupsUrl:B,workloadsUrl:J,customersUrl:F,supportsUsers:_e&&Boolean(ye.userStore),supportsGroups:Ne&&Boolean(H||Y),supportsWorkloads:$e&&Boolean(ye.workloadIdentityStore),supportsCustomers:tt&&Boolean(ye.customerStore)}}async function Lt(Se){let ve=ti(Se,ye.discovery);return await ye.discovery?.buildServiceProviderConfig?.(Se,ve)??ve}async function ot(Se){let ve=ni(Se);return await ye.discovery?.buildResourceTypes?.(Se,ve)??ve}async function vt(Se){let ve=ri(Se);return await ye.discovery?.buildSchemas?.(Se,ve)??ve}async function gt(Se,ve){let M=Dt(Se,ve);if(!M)return;let B=C(new URL(Se.url).pathname),{basePath:J}=M;if(B!==J&&!B.startsWith(`${J}/`))return;let F=C(B.slice(J.length)||"/");if(!(F==="/ServiceProviderConfig"||F==="/ResourceTypes"||F.startsWith("/ResourceTypes/")||F==="/Schemas"||F.startsWith("/Schemas/")))return;if(Se.method!=="GET")return Re(405,"Method not allowed");if(!await nt(Se))return Re(401,"Authorization required");if(F==="/ServiceProviderConfig")return Xe(await Lt(M));if(F==="/ResourceTypes")return ft(await ot(M));if(F.startsWith("/ResourceTypes/")){let de=decodeURIComponent(F.slice(15)),re=(await ot(M)).find((se)=>se.id===de||se.name===de);return re?Xe(re):Re(404,"Resource not found")}if(F==="/Schemas")return ft(await vt(M));if(F.startsWith("/Schemas/")){let de=decodeURIComponent(F.slice(9)),re=(await vt(M)).find((se)=>se.id===de);return re?Xe(re):Re(404,"Resource not found")}return}let at,It;if(ye.url)It=async(ve,M)=>{let B={...ve,schemas:ve.schemas??["urn:ietf:params:scim:schemas:core:2.0:User","urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"]};return Rt("POST","/Users",B,y.user)},at={createGroup:async(ve,M)=>{let B={schemas:["urn:ietf:params:scim:schemas:core:2.0:Group"],displayName:ve,externalId:M?.id,members:M?.members};return Rt("POST","/Groups",B,y.group)}};let lt;if(H||Y){let Se=x(Y,H),ve=(ae,ee,oe)=>{let ue=ae[e]??{},ce=_t(ae),he=ae.id,we=he?He(ee,`${oe}/${encodeURIComponent(he)}`):void 0,ge={id:he??ae.externalId??ae.displayName,name:ae.displayName,displayName:ae.displayName,description:ue.description??ae.displayName,requestable:ue.requestable,providerId:ue.providerId??ae.externalId,requestUrl:ue.requestUrl,source:ue.source,deprecated:ue.deprecated,riskLevel:ue.riskLevel,assignableSubjectTypes:ue.assignableSubjectTypes,recommendedSubjectTypes:ue.recommendedSubjectTypes},Ce=ue.requestUrl??ye.entitlementRequestUrl?.(ge,ce,{request:ee});return{...ae,meta:{...ae.meta,resourceType:"Group",location:we},[e]:{...ue,requestUrl:Ce}}},M=(ae)=>A(Y,ae),B=async(ae,ee)=>{if(!H){if(ee)throw Error(`Cannot persist access for code entitlement "${ae.entity.id}": no AccessCatalogStore is wired.`);return ae.entity}try{return await v(ae.kind,ae.entity,I(H,ae.kind))}catch(oe){if(ee)throw oe;return k.warn("Code entitlement discovery materialization failed; serving the code template",{"ion.operation":"iam.catalog.materialize","ion.outcome":"degraded",entitlementId:ae.entity.id,entitlementType:ae.kind,error:dt(oe)}),ae.entity}},J=async(ae)=>{if(!H)return;try{await j(Y,H,ae)}catch(ee){k.warn("Retired code entitlement deprecation failed; serving the last durable row",{"ion.operation":"iam.catalog.deprecate","ion.outcome":"degraded",entitlementId:ae,error:dt(ee)})}},F=(ae,ee)=>Re(403,`Entitlement "${ae}" is declared in application code; its structural definition cannot be ${ee} through SCIM. IAM may change presentation and receipts, while code continues to own structure.`,"mutability"),ne=(ae)=>ae.path==="members"||Boolean(ae.path?.startsWith("members[")),pe=(ae)=>ne(ae)||ae.path==="displayName"||ae.path===`${e}.description`||ae.path===`${e}.riskLevel`||ae.path===`${e}.providerId`||ae.path===`${e}.requestUrl`||ae.path===`${e}.attributes`||Boolean(ae.path?.startsWith(`${e}.attributes.`)),de=(ae)=>ae?.[e]?.requestable===!0,re=(ae)=>Re(404,`Requestable Group ${ae} not found`,"invalidValue"),se=async(ae,ee)=>{if(!await nt(ae))return Re(401,"Authorization required");let ue=new URL(ae.url),ce=ee?.basePath??"/Groups",he=ue.pathname;if(he.startsWith(ce))he=he.substring(ce.length);let ge=he.match(/^\/([^/]+)$/)?.[1],Ce=ae.method;try{if(ge)switch(Ce){case"GET":return await be(ae,ce,ge);case"PUT":return await Ie(ae,ce,ge);case"PATCH":return await Oe(ae,ce,ge);case"DELETE":return await Ee(ge);default:return Re(405,"Method not allowed")}else if(he===""||he==="/")switch(Ce){case"GET":return await fe(ae,ce);case"POST":return await me(ae,ce);default:return Re(405,"Method not allowed")}return Re(404,"Resource not found")}catch(Ae){if(Ae instanceof Ot)return yr(Ae);if(Ae instanceof cn)return Re(400,Ae.message,"invalidValue");if(T(Ae))return Re(409,Ae.message,"uniqueness");return k.error("Groups inbound handler error",{"ion.operation":"scim.groups.handler","ion.outcome":"failure"},Ae),Re(500,Ae instanceof Error?Ae.message:"Internal server error")}},fe=async(ae,ee)=>{let oe=new URL(ae.url),ue=oe.searchParams.get("startIndex"),ce=oe.searchParams.get("count"),he=ue!=null?parseInt(ue,10):void 0,we=ce!=null?parseInt(ce,10):void 0,ge=he!=null&&!Number.isNaN(he)?Math.max(0,he-1):0,Ce=we!=null&&!Number.isNaN(we)?we:void 0,Ae=oe.searchParams.get("filter"),Me=kr(Ae);if(Me!==void 0){await J();let Te=await Xs(Se,V,Me,De),Ke=Te?[ve(Te,ae,ee)]:[];return ft(Ke,{totalResults:Ke.length,startIndex:1,itemsPerPage:Ke.length})}if(Hs(Ae)?.requestable===!1)return ft([],{totalResults:0,startIndex:1,itemsPerPage:0});let Qe={requestable:!0};if(Y)await Promise.all([...Y.groups.list().filter((Te)=>Te.requestable===!0).map((Te)=>({entity:Te,kind:"group"})),...Y.roles.list().filter((Te)=>Te.requestable===!0).map((Te)=>({entity:Te,kind:"role"})),...Y.permissions.list().filter((Te)=>Te.requestable===!0).map((Te)=>({entity:Te,kind:"permission"}))].map((Te)=>B(Te,!1)));await J();let Ve=await Zs(Se,V,{start:ge,limit:Ce,filter:Qe},De);return ft(Ve.resources.map((Te)=>ve(Te,ae,ee)),{totalResults:Ve.total,startIndex:ge+1,itemsPerPage:Ve.count})},be=async(ae,ee,oe)=>{let ue=M(oe);if(ue&&ue.entity.requestable!==!0)return re(oe);if(ue)await B(ue,!1);await J(oe);let ce=await zt(Se,V,oe,De);if(!de(ce))return re(oe);return Xe(ve(ce,ae,ee))},me=async(ae,ee)=>{let oe=await ae.json(),ue=await bt(y.group,oe);if(ue.issues)return k.error("Group creation validation failed",{"ion.operation":"scim.group.create","ion.outcome":"failure",validationIssues:ue.issues}),Re(400,`Request validation failed: ${ue.issues.map((Ve)=>Ve.message).join("; ")}`,"invalidValue");let ce=ue.value;if(!ce.displayName)return Re(400,"displayName is required","invalidValue");if(ce[e]?.requestable===!1)return Re(400,"SCIM may create only requestable entitlements; non-requestable definitions are App-owned.","invalidValue");if(ce[e]={...ce[e],requestable:!0},!H)return Re(501,"Group creation is not supported: this application declares its catalog in code (authz.catalog) and wires no AccessCatalogStore for SCIM-authored definitions.","invalidValue");let we=_t(ce),ge=rn();if(M(ge))throw new m(`id "${ge}" is reserved by the code catalog`,"unique_violation","id");let Ce=Vn(ce),Ae=on(new Map,nn(ce.members,we,ge,Ce,ce[e]?.assignableSubjectTypes)),Me;await jt(ke,async()=>{Me=await zn(Se,ce,ge)},Ae,{oaa:()=>$n(W,Me,we)});let ze=await Pt(Se,V,we,ge),Qe=ve(xt(Me,we,ze),ae,ee);return Xe(Qe,201,Qe.meta?.location)},Ie=async(ae,ee,oe)=>{let ue=await ae.json(),ce=await bt(y.group,ue);if(ce.issues)return k.error("Group replacement validation failed",{"ion.operation":"scim.group.replace","ion.outcome":"failure",validationIssues:ce.issues}),Re(400,`Request validation failed: ${ce.issues.map((Ke)=>Ke.message).join("; ")}`,"invalidValue");let he=ce.value,we=_t(he),ge=M(oe);if(ge&&ge.entity.requestable!==!0)return re(oe);if(ge){if(await B(ge,!0),Ws(he,ge))return F(oe,"replaced")}let Ce=await zt(Se,V,oe);if(!de(Ce))return re(oe);if(!ge&&Ce[e]?.source==="code"&&Vs(he,Ce))return F(oe,"replaced");let Ae=ge?.kind??we,Me=ge?Jn(ge.entity):Vn(he),ze=V?(await V.listByTarget(Ae,oe)).items:[],Qe=on(qs(ze),nn(he.members,Ae,oe,Me,ge?.entity.assignableSubjectTypes??Ce[e]?.assignableSubjectTypes??he[e]?.assignableSubjectTypes)),Ve;await jt(ke,async()=>{Ve=await zn(Se,he,oe,ge?.entity)},Qe,{oaa:()=>$n(W,Ve,Ae)});let Te=await Pt(Se,V,Ae,oe);return Xe(ve(xt(Ve,Ae,Te),ae,ee))},Oe=async(ae,ee,oe)=>{let ue=M(oe);if(ue&&ue.entity.requestable!==!0)return re(oe);if(ue)await B(ue,!0);let ce=await zt(Se,V,oe);if(!de(ce))return re(oe);let he=await ae.json();if((ue!==void 0||ce[e]?.source==="code")&&(he.Operations??[]).some((Ue)=>!pe(Ue)))return F(oe,"patched");let ge={...ce};for(let Ue of he.Operations??[])if(Ue.op==="replace"&&Ue.path&&Ue.value!==void 0){if(Ue.path==="displayName")ge.displayName=Ue.value;else if(Ue.path===`${e}.requestable`)ge[e]={...ge[e],requestable:Boolean(Ue.value)};else if(Ue.path===`${e}.description`)ge[e]={...ge[e],description:String(Ue.value)};else if(Ue.path===`${e}.riskLevel`)ge[e]={...ge[e],riskLevel:String(Ue.value)};else if(Ue.path===`${e}.providerId`)ge[e]={...ge[e],providerId:String(Ue.value)};else if(Ue.path===`${e}.requestUrl`)ge[e]={...ge[e],requestUrl:String(Ue.value)};else if(Ue.path===`${e}.attributes`&&typeof Ue.value==="object"&&Ue.value!==null&&!Array.isArray(Ue.value))ge[e]={...ge[e],attributes:Ue.value};else if(Ue.path.startsWith(`${e}.attributes.`)){let qe=Ue.path.slice(`${e}.attributes.`.length);ge[e]={...ge[e],attributes:{...ge[e]?.attributes,[qe]:Ue.value}}}}else if(Ue.op==="add"&&Ue.path==="members"&&Ue.value!==void 0){let qe=Ue.value;ge.members=[...ge.members??[],...qe]}else if(Ue.op==="remove"&&Ue.path?.startsWith("members[")){let qe=Ue.path.match(/members\[value eq "([^"]+)"\]/);if(qe)ge.members=(ge.members??[]).filter((St)=>St.value!==qe[1])}else if(Ue.op==="remove"&&Ue.path?.startsWith(`${e}.attributes.`)){let qe=Ue.path.slice(`${e}.attributes.`.length),St={...ge[e]?.attributes};delete St[qe],ge[e]={...ge[e],attributes:St}}let Ce=await bt(y.group,ge);if(Ce.issues)return k.error("Group patch validation failed",{"ion.operation":"scim.group.patch","ion.outcome":"failure",validationIssues:Ce.issues}),Re(400,`Request validation failed: ${Ce.issues.map((Ue)=>Ue.message).join("; ")}`,"invalidValue");let Ae=ue?.kind??_t(ge),Me=ue?Jn(ue.entity):Vn(ge),ze=ue?.entity.assignableSubjectTypes??ce[e]?.assignableSubjectTypes??ge[e]?.assignableSubjectTypes,Qe=on(nn(ce.members,Ae,oe,Me,ze),nn(ge.members,Ae,oe,Me,ze)),Ve,Te=!ue||(he.Operations??[]).some((Ue)=>!ne(Ue));await jt(ke,async()=>{if(Te)Ve=await zn(Se,ge,oe,ue?.entity)},Qe,Te?{oaa:()=>$n(W,Ve,Ae)}:void 0);let Ke=await zt(Se,V,oe);return Xe(ve(Ke,ae,ee))},Ee=async(ae)=>{let ee=M(ae);if(ee&&ee.entity.requestable!==!0)return re(ae);if(ee)await B(ee,!0);let oe=await zt(Se,V,ae);if(!de(oe))return re(ae);let ue=oe[e];if((ee||ue?.source==="code")&&ue?.deprecated!==!0)return Re(403,`Code-owned entitlement "${ae}" can be deleted only after it is marked deprecated.`,"mutability");let ce=_t(oe);if(V){let he=await V.listByTarget(ce,ae),we=[];for(let ge of he.items)await Bt(ke,ge,we);await sn(ke,we)}return await Qs(Se,ae),new Response(null,{status:204})};lt={handler:se}}let Ze,yt,ct;if(ye.userStore){let{userStore:Se,inboundUsers:ve}=ye,M=(ee)=>ee?.find((oe)=>oe.primary)?.value||ee?.[0]?.value,B=async(ee)=>{if(ve?.mapBaseUserToScim)return await ve.mapBaseUserToScim(ee);return On(ee)},J=async(ee,oe,ue)=>{let ce=await B(ee),he=ce.id??ee.id;return{...ce,id:he,meta:{...ce.meta,resourceType:"User",location:he?He(oe,`${ue}/${encodeURIComponent(he)}`):void 0}}},F=async(ee,oe)=>{if(ve?.mapValidatedScimToBaseUser)return await ve.mapValidatedScimToBaseUser(ee,oe);let ue=new Date,ce=M(ee.emails),he=ee.name?.formatted||[ee.name?.givenName,ee.name?.middleName,ee.name?.familyName].filter(Boolean).join(" ").trim()||ee.displayName,we=ee.id||oe.existing?.id||rn(),ge=ee.userName||ce||oe.existing?.userName||we,Ce=he||ee.displayName||oe.existing?.name||ge,Ae=Object.fromEntries(Object.entries(ee).filter(([Ke,Ue])=>Ke.startsWith("urn:")&&Ke!==Jt&&Ke!==s&&Ue!==void 0)),Me=ee[s],ze=r(Me?.attributes??{},h),Qe=Me?.ecid!==void 0&&Me.ecid!==null?w(Me.ecid):oe.existing?.ecid,Ve=Me?.accountClass??oe.existing?.accountClass,Te=oe.existing?.sso;return{...oe.existing??{},id:we,userName:ge,name:Ce,email:ce||oe.existing?.email||ge,avatar:ee.profileUrl,sso:{...Te??{},profile:{...Te?.profile??{},sub:we,iss:Te?.profile.iss??"iam-provisioned",aud:Te?.profile.aud??"iam-provisioned",exp:Te?.profile.exp??Math.floor(Date.now()/1000)+3600,iat:Te?.profile.iat??Math.floor(Date.now()/1000),email:ce||oe.existing?.email||ge,email_verified:!0,name:Ce,preferred_username:ge},tenant:Te?.tenant??{id:"iam-provisioned",name:"IAM Provisioned"},scope:Te?.scope??"openid profile email",tokenType:Te?.tokenType??"Bearer",expires:Te?.expires??new Date(Date.now()+3600000)},externalId:ee.externalId,ecid:Qe,accountClass:Ve,displayName:ee.displayName,scimName:ee.name,emails:ee.emails,nickName:ee.nickName,title:ee.title,preferredLanguage:ee.preferredLanguage,locale:ee.locale,timezone:ee.timezone,active:ee.active,phoneNumbers:ee.phoneNumbers,ims:ee.ims,photos:ee.photos,addresses:ee.addresses,groups:ee.groups,entitlements:ee.entitlements,roles:ee.roles,x509Certificates:ee.x509Certificates,scimEnterprise:ee[Jt],scimSchemaExtensions:Object.keys(Ae).length>0?Ae:void 0,createdAt:oe.existing?.createdAt??(ee.meta?.created?new Date(ee.meta.created):ue),updatedAt:ee.meta?.lastModified?new Date(ee.meta.lastModified):ue,userType:ee.userType,...ze}},ne=(ee,oe,ue)=>{ee[oe]=ue},pe=(ee,oe,ue)=>{let ce=ee[oe];if(Array.isArray(ce)){ee[oe]=[...ce,...Array.isArray(ue)?ue:[ue]];return}if(ce&&typeof ce==="object"&&!Array.isArray(ce)&&ue&&typeof ue==="object"&&!Array.isArray(ue)){ee[oe]={...ce,...ue};return}ee[oe]=ue},de=(ee,oe,ue)=>{let ce=oe.match(/^(urn:.*:(?:User|Group))(?::(.+))?$/),he=ce?[ce[1],...ce[2]?.split(":")??[]]:oe.split("."),we=ee;for(let Ce of he.slice(0,-1)){let Ae=we[Ce];if(Ae===void 0){if(!ue)return null;we[Ce]={}}else if(Ae===null||typeof Ae!=="object"||Array.isArray(Ae)){if(!ue)return null;we[Ce]={}}we=we[Ce]}let ge=he.at(-1);if(!ge)return null;return{parent:we,key:ge}},re=(ee,oe)=>{let ue=oe.op.toLowerCase();if(!oe.path){if(ue!=="remove"&&oe.value&&typeof oe.value==="object"&&!Array.isArray(oe.value))Object.assign(ee,oe.value);return}let ce=oe.path.match(/^([A-Za-z0-9]+)\[value eq "([^"]+)"\]$/);if(ce&&ue==="remove"){let[,we,ge]=ce,Ce=ee[we];if(Array.isArray(Ce))ee[we]=Ce.filter((Ae)=>!(Ae&&typeof Ae==="object"&&("value"in Ae)&&Ae.value===ge));return}let he=de(ee,oe.path,ue!=="remove");if(!he)return;if(ue==="remove"){delete he.parent[he.key];return}if(ue==="add"){pe(he.parent,he.key,oe.value);return}ne(he.parent,he.key,oe.value)},se=async(ee,oe)=>{if(!await nt(ee))return Re(401,"Authorization required");let ce=new URL(ee.url),he=oe?.basePath??"/Users",we=ce.pathname;if(we.startsWith(he))we=we.substring(he.length);let Ce=we.match(/^\/([^/]+)$/)?.[1],Ae=ee.method;try{if(Ce)switch(Ae){case"GET":return await be(ee,he,Ce);case"PUT":return await Oe(ee,he,Ce);case"PATCH":return await Ee(ee,he,Ce);case"DELETE":return await ae(Ce);default:return Re(405,"Method not allowed")}else if(we===""||we==="/")switch(Ae){case"GET":return await fe(ee,he);case"POST":return await Ie(ee,he);default:return Re(405,"Method not allowed")}return Re(404,"Resource not found")}catch(Me){if(Me instanceof Ot)return yr(Me);if(T(Me))return Re(409,Me.message,"uniqueness");return k.error("Users inbound handler error",{"ion.operation":"scim.users.handler","ion.outcome":"failure"},Me),Re(500,Me instanceof Error?Me.message:"Internal server error")}},fe=async(ee,oe)=>{let ue=new URL(ee.url),ce=ue.searchParams.get("startIndex"),he=ue.searchParams.get("count"),we=ce!=null?parseInt(ce,10):void 0,ge=he!=null?parseInt(he,10):void 0,Ce=we!=null&&!Number.isNaN(we)?Math.max(0,we-1):0,Ae=ge!=null&&!Number.isNaN(ge)?ge:void 0,Me=kr(ue.searchParams.get("filter"));if(Me!==void 0){let Ve=await Se.lookup({externalId:Me}),Te=Ve?[await J(Ve,ee,oe)]:[];return ft(Te,{totalResults:Te.length,startIndex:1,itemsPerPage:Te.length})}let ze=await Se.list({start:Ce,limit:Ae}),Qe=await Promise.all(ze.items.map((Ve)=>J(Ve,ee,oe)));return ft(Qe,{totalResults:ze.total,startIndex:Ce+1,itemsPerPage:ze.count})},be=async(ee,oe,ue)=>{let ce=await Se.get(ue);if(!ce)return Re(404,`User ${ue} not found`,"invalidValue");return Xe(await J(ce,ee,oe))},me=async(ee,oe)=>{let ue=ke.accessIndex;if(!ue?.setSubjectDisabled||!oe.id)return;let ce=ee?ee.active??!0:!0,he=oe.active??!0;if(ee&&ce===he)return;if(!ee&&he)return;await ue.setSubjectDisabled(oe.id,"user",!he)},Ie=async(ee,oe)=>{let ue=await ee.json(),ce=await bt(y.user,ue);if(ce.issues)return k.error("User creation validation failed",{"ion.operation":"scim.user.create","ion.outcome":"failure",validationIssues:ce.issues}),Re(400,`Request validation failed: ${ce.issues.map((Ce)=>Ce.message).join("; ")}`,"invalidValue");let he=ce.value;if(!he.userName&&!he.emails?.[0]?.value)return Re(400,"userName or email is required","invalidValue");let we=await F(he,{mode:"create"});await jt(ke,async()=>{await Se.upsert(we),await me(void 0,we)},Wn(void 0,we),{oaa:async()=>{await qn(W,we)},delta:async()=>{await ke.iamDelta?.onUserUpsert(we)}});let ge=await J(we,ee,oe);return Xe(ge,201,ge.meta?.location)},Oe=async(ee,oe,ue)=>{let ce=await Se.get(ue);if(!ce)return Re(404,`User ${ue} not found`,"invalidValue");let he=await ee.json(),we=await bt(y.user,he);if(we.issues)return k.error("User replacement validation failed",{"ion.operation":"scim.user.replace","ion.outcome":"failure",validationIssues:we.issues}),Re(400,`Request validation failed: ${we.issues.map((Ae)=>Ae.message).join("; ")}`,"invalidValue");let ge=we.value,Ce=await F({...ge,id:ue},{existing:ce,mode:"replace"});return Ce.createdAt=ce.createdAt,Ce.updatedAt=new Date,await jt(ke,async()=>{await Se.upsert(Ce),await me(ce,Ce)},Wn(ce,Ce),{oaa:async()=>{await qn(W,Ce)},delta:async()=>{await Sr(ke.iamDelta,ce,Ce)}}),Xe(await J(Ce,ee,oe))},Ee=async(ee,oe,ue)=>{let ce=await Se.get(ue);if(!ce)return Re(404,`User ${ue} not found`,"invalidValue");let we=(await ee.json()).Operations??[],Ce={...await B(ce)};for(let ze of we)re(Ce,ze);let Ae=await bt(y.user,Ce);if(Ae.issues)return k.error("User patch validation failed",{"ion.operation":"scim.user.patch","ion.outcome":"failure",validationIssues:Ae.issues}),Re(400,`Request validation failed: ${Ae.issues.map((ze)=>ze.message).join("; ")}`,"invalidValue");let Me=await F(Ae.value,{existing:ce,mode:"patch"});return Me.updatedAt=new Date,await jt(ke,async()=>{await Se.upsert(Me),await me(ce,Me)},Wn(ce,Me),{oaa:async()=>{await qn(W,Me)},delta:async()=>{await Sr(ke.iamDelta,ce,Me)}}),Xe(await J(Me,ee,oe))},ae=async(ee)=>{let oe=await Se.get(ee);if(!oe)return Re(404,`User ${ee} not found`,"invalidValue");if(V){let ue=[];for await(let ce of i((he,we)=>V.listBySubject(ee,"user",{start:he,limit:we})))await Bt(ke,ce,ue);await sn(ke,ue)}if(await Se.delete(ee),await ke.accessIndex?.setSubjectDisabled?.(ee,"user",!1),oe.externalId&&ke.iamDelta?.isReady())await Ct(ke,"iam.delta.egress","IAM delta user delete failed after SCIM write; full aggregation will reconcile",()=>ke.iamDelta?.onUserDelete(oe.externalId)??Promise.resolve(),{id:ee,kind:"user"});else if(ke.iamDelta?.isReady())ke.log?.warn("IAM delta: deleted User has no externalId; destination delete skipped",{"ion.operation":"iam.delta.delete","ion.outcome":"skipped",id:ee,kind:"user"});if(ke.authz.oaa.isReady())await Ct(ke,"authz.oaa.delete","OAA incremental user delete failed; full sync will reconcile",()=>ke.authz.oaa.deleteUser(ee),{id:ee,kind:"user"});return new Response(null,{status:204})};Ze={handler:se}}let rt=async(Se,ve)=>{if(!V)return;let M=[];for await(let B of i((J,F)=>V.listBySubject(Se,ve,{start:J,limit:F})))await Bt(ke,B,M);await sn(ke,M)};if(ye.workloadIdentityStore){let{workloadIdentityStore:Se,inboundWorkloads:ve}=ye;yt=wr({resourceType:"Workload",subjectType:"workload",store:Se,validator:y.workload??q,toScim:async(M)=>await(ve?.mapBaseWorkloadToScim?.(M)??Dn(M)),fromScim:async(M,B)=>{if(ve?.mapValidatedScimToBaseWorkload)return ve.mapValidatedScimToBaseWorkload(M,B);let J=B.existing,F=M,ne=F.id?.trim()||J?.id||rn(),pe=r(F.attributes??{},b);return{...J??{},id:ne,externalId:F.externalId??J?.externalId,clientId:F.userName??J?.clientId??ne,displayName:F.displayName??J?.displayName,description:F.description??J?.description,active:F.active??J?.active??!0,providerId:J?.providerId,requestUrl:J?.requestUrl,...pe}},projections:[{channel:"oaa",upsert:async(M)=>{if(W.oaa.isReady())await W.oaa.pushWorkload(M)},delete:async(M)=>{if(W.oaa.isReady())await W.oaa.deleteWorkload(M.id)}},{channel:"delta",upsert:async(M,B)=>{let J=B?.externalId??B?.id,F=M.externalId??M.id;if(J&&J!==F)await xe?.onWorkloadDelete(J);await xe?.onWorkloadUpsert(M)},delete:async(M)=>{await xe?.onWorkloadDelete(M.externalId??M.id)}}]},{validateAuth:nt,accessStore:V,accessIndex:G,revokeSubjectAccess:rt,log:k})}if(ye.customerStore){let{customerStore:Se,inboundCustomers:ve}=ye;ct=wr({resourceType:"Customer",subjectType:"customer",store:Se,validator:y.customer??K,toScim:async(M)=>await(ve?.mapBaseCustomerToScim?.(M)??Ln(M)),fromScim:async(M,B)=>{if(ve?.mapValidatedScimToBaseCustomer)return ve.mapValidatedScimToBaseCustomer(M,B);let J=B.existing,F=M,ne=F.id?.trim()||J?.id||rn(),pe=r(F.attributes??{},S),de=F.emails?.find((re)=>re.primary)?.value??F.emails?.[0]?.value;return{...J??{},id:ne,externalId:F.externalId??J?.externalId??ne,userName:F.userName??J?.userName??ne,name:F.displayName??J?.name??F.userName??ne,email:de??J?.email??"",displayName:F.displayName??J?.displayName,emails:F.emails??J?.emails,active:F.active??J?.active??!0,providerId:J?.providerId,requestUrl:J?.requestUrl,...pe}},projections:[{channel:"oaa",upsert:async(M)=>{if(W.oaa.isReady())await W.oaa.pushCustomer(M)},delete:async(M)=>{if(W.oaa.isReady()&&M.id)await W.oaa.deleteCustomer(M.id)}},{channel:"delta",upsert:async(M,B)=>{let J=B?.externalId??B?.id,F=M.externalId??M.id;if(J&&J!==F)await xe?.onCustomerDelete(J);await xe?.onCustomerUpsert(M)},delete:async(M)=>{let B=M.externalId??M.id;if(B)await xe?.onCustomerDelete(B)}}]},{validateAuth:nt,accessStore:V,accessIndex:G,revokeSubjectAccess:rt,log:k})}async function ht(Se,ve){Je();let M=new URL(Se.url).pathname,B=ut(ve?.usersUrl??ye.usersUrl??"/api/iam/Users")??"/api/iam/Users",J=ut(ve?.groupsUrl??ye.groupsUrl??"/api/iam/Groups")??"/api/iam/Groups",F=ut(ve?.workloadsUrl??ye.workloadsUrl??"/api/iam/Workloads")??"/api/iam/Workloads",ne=ut(ve?.customersUrl??ye.customersUrl??"/api/iam/Customers")??"/api/iam/Customers",pe=`${br(B,J,F,ne)??"/api/iam"}/AccessRequests`,de=await gt(Se,ve);if(de)return de;let re=(se)=>M===se||M.startsWith(`${se}/`);if(re(B)){if(!_e)return Re(404,"SCIM Users endpoint is disabled by RemoteConfig");if(!Ze)return Re(501,"SCIM Users endpoint is enabled by RemoteConfig but no user store capability is wired by the application.");return Ze.handler(Se,{basePath:B})}if(re(J)){if(!Ne)return Re(404,"SCIM Groups endpoint is disabled by RemoteConfig");if(!lt)return Re(501,"SCIM Groups endpoint is enabled by RemoteConfig but no AccessCatalogStore capability is wired by the application.");return lt.handler(Se,{basePath:J})}if(re(F)){if(!$e)return Re(404,"SCIM Workloads endpoint is disabled by RemoteConfig");if(!yt)return Re(501,"SCIM Workloads endpoint is enabled by RemoteConfig but no workload identity store capability is wired by the application.");return yt.handler(Se,{basePath:F})}if(re(ne)){if(!tt)return Re(404,"SCIM Customers endpoint is disabled by RemoteConfig");if(!ct)return Re(501,"SCIM Customers endpoint is enabled by RemoteConfig but no customer store capability is wired by the application.");return ct.handler(Se,{basePath:ne})}if(re(pe)){if(!ye.accessRequests)return Re(404,"AccessRequests endpoint is not configured");if(Se.method!=="POST")return Re(405,"Method not allowed");if(!await nt(Se))return Re(401,"Authorization required");let se;try{se=await Se.json()}catch{return Re(400,"Request body must be valid JSON","invalidSyntax")}if(typeof se.subject!=="string"||!se.subject||typeof se.target!=="string"||!se.target||se.subjectType!=="user"&&se.subjectType!=="workload"&&se.subjectType!=="customer"||se.targetType!=="group"&&se.targetType!=="role"&&se.targetType!=="permission"||se.operation!=="grant"&&se.operation!=="revoke")return Re(400,"subject, subjectType, targetType, target, and operation are required","invalidValue");let fe=await ye.accessRequests.create({subject:se.subject,subjectType:se.subjectType,targetType:se.targetType,target:se.target,operation:se.operation,justification:typeof se.justification==="string"?se.justification:void 0});return Xe(fe.request,fe.created?201:200,fe.request.trackingUrl)}return Re(404,"Resource not found")}return{...ye,users:Nn(ye.users),workloads:Nn(ye.workloads),customers:Nn(ye.customers),groups:{enabled:Ne},createUser:It,getBaseUrl:Et,groups_outbound:at,groups_inbound:lt,users_inbound:Ze,workloads_inbound:yt,customers_inbound:ct,handler:ht,delta:xe}}function Hn(y,k){let R=new TextEncoder().encode(y),W=typeof k==="string"?new TextEncoder().encode(k):k,V=new Uint8Array(R.length+1+W.length);return V.set(R,0),V[R.length]=46,V.set(W,R.length+1),V}function ii(y){let k=y.replace(/-/g,"+").replace(/_/g,"/"),R=k.length%4===0?"":"=".repeat(4-k.length%4),W=atob(k+R),V=new Uint8Array(W.length);for(let G=0;G<W.length;G++)V[G]=W.charCodeAt(G);return V}function oi(y){let k="";for(let R of y)k+=String.fromCharCode(R);return btoa(k).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function Rr(y){let k=JSON.parse(y);if(!k||typeof k!=="object"||!Array.isArray(k.keys))throw Error("Invalid JWKS: expected { keys: [...] }");return k}function ai(y){return JSON.stringify(y)}async function ci(y){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:y.x},{name:"Ed25519"},!0,["verify"])}async function ui(y){return crypto.subtle.importKey("jwk",{kty:"OKP",crv:"Ed25519",x:y.x,d:y.d},{name:"Ed25519"},!0,["sign"])}async function di(y){let R=(typeof y.jwks==="string"?Rr(y.jwks):y.jwks).keys.find((W)=>W.kid===y.kid&&W.kty==="OKP"&&W.crv==="Ed25519");if(!R?.x)return!1;try{let W=await ci(R),V=Hn(y.requestId,y.rawBody),G=ii(y.signatureB64Url);return crypto.subtle.verify({name:"Ed25519"},W,G,V)}catch{return!1}}async function li(y){let k=await ui(y.privateKeyJwk),R=Hn(y.requestId,y.rawBody),W=await crypto.subtle.sign({name:"Ed25519"},k,R);return oi(new Uint8Array(W))}async function pi(y){let k=await crypto.subtle.generateKey({name:"Ed25519"},!0,["sign","verify"]),R=await crypto.subtle.exportKey("jwk",k.privateKey),V=(await crypto.subtle.exportKey("jwk",k.publicKey)).x,G=R.d;if(!V||!G)throw Error("Failed to export Ed25519 key material (missing x/d)");return{privateJwk:{kty:"OKP",crv:"Ed25519",x:V,d:G,kid:y,alg:"EdDSA",use:"sig"},publicJwks:{keys:[{kty:"OKP",crv:"Ed25519",x:V,kid:y,alg:"EdDSA",use:"sig"}]}}}var Ft={jwksTtlSeconds:{min:60,max:86400,default:600},jwksMaxEntries:{min:16,max:4096,default:256},sessionReadTtlSeconds:{min:1,max:300,default:30},sessionReadMaxEntries:{min:16,max:65536,default:1024}};function un(y,k){if(typeof y!=="number"||!Number.isFinite(y))return k.default;let R=Math.floor(y);if(R<k.min)return k.min;if(R>k.max)return k.max;return R}function vr(y){return{ttlMs:un(y?.ttlSeconds,Ft.jwksTtlSeconds)*1000,maxEntries:un(y?.maxEntries,Ft.jwksMaxEntries)}}function Ir(y){let k=y?.read;return{read:{enabled:k?.enabled===!0,ttlMs:un(k?.ttlSeconds,Ft.sessionReadTtlSeconds)*1000,maxEntries:un(k?.maxEntries,Ft.sessionReadMaxEntries)}}}function mi(y){return{jwks:vr(y?.jwks),session:Ir(y?.session)}}function fi(y){let k={};if(!y)return k;let R=y.split(";");for(let W of R){let V=W.trim();if(!V)continue;let G=V.indexOf("=");if(G===-1)continue;k[V.slice(0,G).trim()]=V.slice(G+1).trim()}return k}function Ar(y){if(!y.expiresAt)return!1;let k=y.expiresAt instanceof Date?y.expiresAt:new Date(y.expiresAt);return!Number.isNaN(k.getTime())&&Date.now()>k.getTime()}function gi(y){if(!y||typeof y!=="object"||Array.isArray(y))return;let{access_token:k,id_token:R,refresh_token:W,tokens:V,...G}=y;return G}function it(y,k){let R=y[k];return typeof R==="string"?R:""}function yi(y,k){let R=y.exp;if(typeof R==="number")return new Date(R*1000);if(typeof R==="string"&&R.trim()){let W=Number(R);if(!Number.isNaN(W))return new Date(W*1000)}if(k instanceof Date)return k;if(k){let W=new Date(k);if(!Number.isNaN(W.getTime()))return W}return new Date}function hi(y){let k=y.claims;if(!k?.sub||typeof k.sub!=="string")return;let R=yi(k,y.expiresAt);if(y.authType==="sso")return{id:k.sub,userName:it(k,"preferred_username"),name:it(k,"name"),email:it(k,"email"),avatar:it(k,"picture")||void 0,sso:{profile:k,tenant:{id:it(k,"idp")||it(k,"iss"),name:it(k,"iss")},tokenType:"Bearer",expires:R}};return{id:k.sub,userName:it(k,"preferred_username"),name:it(k,"name"),email:it(k,"email"),avatar:it(k,"picture")||void 0,userType:"customer",ciam:{profile:k,scope:"openid profile email",tokenType:"Bearer",expires:R}}}function Si(y){if(y.authType!=="sso"&&y.authType!=="ciam")return;if(Ar(y))return;return{sid:y.sid,authType:y.authType,tenantId:typeof y.tenantId==="string"?y.tenantId:void 0,sub:y.sub,expiresAt:y.expiresAt,createdAt:y.createdAt,claims:gi(y.claims)}}function ki(y,k){if(!y.endsWith(".session"))return!1;if(!k||k.length===0)return!0;return k.some((R)=>y===`${R}.session`)}function wi(y){if(y===void 0)return;let k=(Array.isArray(y)?y:[y]).map((R)=>R.trim()).filter((R)=>R.length>0);return k.length>0?k:void 0}async function Tr(y,k,R){return(await Pr(y,k,R)).map(Si).filter((V)=>Boolean(V))}async function Pr(y,k,R){let W=fi(y.headers.get("cookie")),V=wi(R?.cookiesPrefix),G=[],H=new Set;for(let[Y,Q]of Object.entries(W)){if(!ki(Y,V)||!Q)continue;if(H.has(Q))continue;H.add(Q);let X=await k.get(Q);if(!X)continue;if(X.authType!=="sso"&&X.authType!=="ciam")continue;if(Ar(X))continue;G.push(X)}return G}async function bi(y,k,R){return(await Tr(y,k,R)).map(hi).filter((V)=>Boolean(V))}var Ci="@ionite/core",Ri=a(l(Ci));async function vi(y,k){let R=await kt({idToken:y,jwksUri:k.jwksUri,issuer:k.issuer,audience:k.audience}),W=await Ri.validate(R);if(W.issues)throw Error(`ID token claims validation failed: ${W.issues.map((H)=>H.message).join("; ")}`);let V=W.value;if(V===void 0)throw Error("ID token claims missing");return P(V)}function Ye(y){return Date.now()-y}function Fn(y){if(y instanceof Error)return{"error.name":y.name,"error.message":y.message};return{"error.name":typeof y,"error.message":String(y)}}function dn(y,k){if(!y)return{};try{let R=new URL(y);return{[`${k}.origin`]:R.origin,[`${k}.path`]:R.pathname}}catch{return{[`${k}.path`]:y.startsWith("/")?y:`/${y}`}}}function ln(y,k=5){if(!Array.isArray(y))return[String(y)];return y.slice(0,k).map((R)=>{if(!R||typeof R!=="object")return String(R);let W=R,V=Array.isArray(W.path)?W.path.join("."):String(W.path??""),G=typeof W.message==="string"?W.message:String(W.message??"validation failed");return V?`${V}: ${G}`:G})}function Ii(y){if(!y||typeof y!=="object")return{};let k=y;return{oidc_error:typeof k.error==="string"?k.error:void 0,oidc_error_description:typeof k.error_description==="string"?k.error_description:void 0,oidc_error_uri:typeof k.error_uri==="string"?k.error_uri:void 0}}function Ai(y,k={}){let R=typeof y==="string"?y:y?.headers.get("cookie")??void 0;if(!R)return[];let V=`${k.cookiePrefix??"ion.sso"}.`,G=new Set;for(let H of Object.keys(Pi(R))){if(!H.startsWith(V))continue;let Y=H.slice(V.length),Q=Y.lastIndexOf(".");if(Q<=0)continue;let X=Y.slice(0,Q).trim();if(X)G.add(X)}return Array.from(G)}function Ti(y,k,R,W,V){if(!R&&!W)return;let G=new WeakMap,H=new Map,Y={...R,...W},Q=!!(Y.authority&&Y.tokenUrl&&Y.authorizationUrl&&Y.clientId&&Y.redirectUri&&Y.scope),X={...Y,authority:Q?t(Y.authority,"Missing 'authority' from SSO Config"):Y.authority,tokenUrl:Q?t(Y.tokenUrl,"Missing 'tokenUrl' from SSO Config"):Y.tokenUrl,authorizationUrl:Q?t(Y.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"):Y.authorizationUrl,clientId:Q?t(Y.clientId,"Missing 'clientId' from SSO Config"):Y.clientId,redirectUri:Q?t(Y.redirectUri,"Missing 'redirectUri' from SSO Config"):Y.redirectUri,scope:Q?t(Y.scope,"Missing 'scope' from SSO Config"):Y.scope,responseType:Y.responseType??"code",cookiesSecure:Y.cookiesSecure!==void 0?Y.cookiesSecure:!0,cookiesSameSite:Y.cookiesSameSite!==void 0?Y.cookiesSameSite:"Strict",cookiesPrefix:Y.cookiesPrefix??(Y.clientId?`ion.sso.${Y.clientId}`:"ion.sso"),cookiesPath:Y.cookiesPath??"/"},Pe=Math.min(600,Math.max(0,Math.floor(Number(X.rotationGraceSeconds??60))||0))*1000,xe=Math.floor(Number(X.sessionWindowSeconds??86400)),je=Number.isFinite(xe)&&xe>=1?xe:86400;function De(){let M=[];if(!X.authority)M.push("authority");if(!X.tokenUrl)M.push("tokenUrl");if(!X.authorizationUrl)M.push("authorizationUrl");if(!X.clientId)M.push("clientId");if(!X.redirectUri)M.push("redirectUri");if(!X.scope)M.push("scope");if(M.length>0)throw Error(`Missing OIDC configuration fields: ${M.join(", ")}. OIDC configuration is required for SSO operations. Please provide these fields either in your vault configuration or in the SSO config when initializing ionite.`)}async function We(M){if(!X)throw Error("ionite SSO Manager not initialized");let B=G.get(M);if(B)return B;let J=ke(M);return G.set(M,J),J}async function ke(M){try{let{tokens:B,session:J,refreshedUser:F}=await Ze(M);if(!B)return{status:"unauthenticated"};if(F)return{status:"authenticated",value:F};if(J?.claims)return{status:"authenticated",value:Je(J.claims,B,gt(J.expiresAt))};return{status:"unauthenticated"}}catch(B){if(xr(B))return{status:"unauthenticated"};return k.error("Error parsing user from cookies",{"ion.operation":"cookie.parse","ion.outcome":"degraded"},B),{status:"degraded",error:B instanceof Error?B:void 0}}}async function Le(M){let B=await We(M);return B.status==="authenticated"?B.value:void 0}async function ye(M){if(!X)throw Error("ionite SSO Manager not initialized");De();let B=t(X.redirectUri,"Missing 'redirectUri' from SSO Config"),J=t(X.authorizationUrl,"Missing 'authorizationUrl' from SSO Config"),F=t(X.clientId,"Missing 'clientId' from SSO Config"),ne=t(X.scope,"Missing 'scope' from SSO Config"),pe=X.cookiesSecure?M.url.replace(/^http:\/\//,"https://"):M.url,de=st(),re=st(64),se=st(),fe=B;try{new URL(fe)}catch{if(pe)try{let Ee=new URL(pe),ae=fe.startsWith("//")?fe.slice(1):fe.startsWith("/")?fe:`/${fe}`;fe=new URL(ae,Ee.origin).toString()}catch{try{let Ee=new URL(J),ae=fe.startsWith("//")?fe.slice(1):fe.startsWith("/")?fe:`/${fe}`;fe=new URL(ae,Ee.origin).toString()}catch{throw Error(`Invalid redirectUri: "${B}". It must be a valid absolute URL.`)}}}let be=new URL(J);be.searchParams.append("client_id",F),be.searchParams.append("redirect_uri",fe),be.searchParams.append("response_type","code"),be.searchParams.append("scope",ne),be.searchParams.append("state",de),be.searchParams.append("nonce",se);let me=await $t(re);be.searchParams.append("code_challenge",me),be.searchParams.append("code_challenge_method","S256");let Ie=await X.beforeLogin?.({request:M}),Oe=Ie===void 0?{state:de,codeVerifier:re,nonce:se}:{state:de,codeVerifier:re,nonce:se,context:Ie};return new Response("Redirecting to SSO Provider",{status:302,headers:{Location:be.toString(),"Set-Cookie":ct(Se(de),Oe,X.loginStateTtl??600,"Lax")}})}async function _e(M){if(!X)throw Error("ionite SSO Manager not initialized");let B;try{B=await Le(M)}catch{B=void 0}let J=await X.beforeLogout?.({request:M,user:B}),F=ht("session",M),ne;try{ne=await Ze(M);let me=ne.tokens?.refresh_token??ht("refresh",M);if(me)await Et(me)}catch(me){k.warn("Failed to revoke token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},me)}if(X.sessionStore)try{let me=ne?.sid??F;if(me)await X.sessionStore.delete(me)}catch(me){k.warn("Failed to delete session",{"ion.operation":"session.delete","ion.outcome":"degraded"},me)}let pe=[["Set-Cookie",rt("session")]],de=await X.afterLogout?.({request:M,context:J}),re=wt(de,"/",M.url);if(re.response){let me=new Headers(re.response.headers);for(let[,Ie]of pe)me.append("Set-Cookie",Ie);return new Response(re.response.body,{status:re.response.status,statusText:re.response.statusText,headers:me})}let se=re.location??"/",fe=M.headers.get("accept");if(fe?.includes("application/json")||fe?.includes("text/javascript"))return new Response(JSON.stringify({success:!0,message:"Logged out",redirect:se}),{status:200,headers:[["Content-Type","application/json"],...pe]});return new Response("Logged out",{status:302,headers:[["Location",se],...pe]})}async function Ne(M){if(!X)throw Error("ionite SSO Manager not initialized");if(!X.sessionStore)throw Error("Back-Channel Logout requires sessionStore configuration");try{if(!M.headers.get("content-type")?.includes("application/x-www-form-urlencoded"))return new Response("Invalid Content-Type, expected application/x-www-form-urlencoded",{status:400});let J=await M.text(),ne=new URLSearchParams(J).get("logout_token");if(!ne)return new Response("Missing logout_token parameter",{status:400});let pe=t(X.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify logout tokens."),de=t(X.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify logout tokens."),re=X.jwksUri||`${pe}/protocol/openid-connect/certs`,se=await Pn({logoutToken:ne,jwksUri:re,issuer:pe,audience:de,log:k}),fe=typeof se.sid==="string"?se.sid:void 0;if(!fe)return k.warn("Back-Channel Logout: logout_token missing sid claim",{"ion.operation":"backchannel_logout","ion.outcome":"failure"}),new Response("Invalid logout_token: missing sid claim",{status:400});return await X.sessionStore.delete(fe),k.info("Back-Channel Logout: successfully deleted session",{"ion.module":"sso",sid:fe}),new Response("OK",{status:200})}catch(B){return k.error("Error during back-channel logout",{"ion.operation":"backchannel_logout","ion.outcome":"failure"},B),new Response("Internal Server Error",{status:500})}}async function $e(M){if(!X)throw Error("ionite SSO Manager not initialized");let B=Date.now(),J=new URL(M.url),F=new URLSearchParams(J.search);k.debug("SSO callback received",{"ion.event":"ion.sso.callback.received","ion.module":"sso","ion.operation":"sign_in.callback","http.method":M.method,"url.path":J.pathname,hasCode:F.has("code"),hasState:F.has("state"),hasError:F.has("error"),...dn(F.get("iss")??void 0,"oidc.issuer")});let ne=Object.fromEntries(F.entries()),pe=await y.callbackParams.validate(ne);if(pe.issues)return k.warn("SSO callback parameter validation failed",{"ion.event":"ion.sso.callback.validation_failed","ion.operation":"sign_in.callback","ion.outcome":"failure","validation.issues":ln(pe.issues)}),D(pe.issues,"OIDC callback parameters validation failed");let{code:de,state:re}=pe.value,se;try{let fe=t(re,'OIDC "state" was not present in the callback parameters'),be=ht(Se(fe),M,!0),{codeVerifier:me,state:Ie,nonce:Oe,context:Ee}=be??{};se=Ee,k.debug("SSO callback state cookie read",{"ion.event":"ion.sso.callback.state_cookie_read","ion.module":"sso","ion.operation":"sign_in.callback",hasStateCookie:Boolean(be),hasCodeVerifier:Boolean(me),hasStateVerifier:Boolean(Ie),hasNonce:Boolean(Oe),hasContext:Ee!==void 0});let ae=t(me,'OIDC "codeVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');t(Ie,'OIDC "stateVerifier" was not present in cookies, ensure that the SSO login was initiated correctly');let ee=t(Oe,'OIDC "nonce" was not present in cookies, ensure that the SSO login was initiated correctly'),oe=t(de,'OIDC "code" was not present in the callback parameters');if(re!==Ie)throw k.warn("SSO callback state verification failed",{"ion.event":"ion.sso.callback.state_verification_failed","ion.operation":"sign_in.callback","ion.outcome":"failure"}),Error('SSO State Verifier failed, the "state" request parameter does not equal the "state" in the SSO cookie');k.debug("SSO callback state verified",{"ion.event":"ion.sso.callback.state_verified","ion.module":"sso","ion.operation":"sign_in.callback"});let ue=X.cookiesSecure?M.url.replace(/^http:\/\//,"https://"):M.url,ce=await Ut(oe,ae,ue),{tokenExpiresAt:he,sessionExpiresAt:we}=tt(ce);ce.expires=he.toISOString();let ge=Date.now();k.debug("SSO ID token parsing started",{"ion.event":"ion.sso.id_token.parse_started","ion.module":"sso","ion.operation":"id_token.parse"});let Ce=await Ge(ce,ee,we);k.debug("SSO ID token parsing completed",{"ion.event":"ion.sso.id_token.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":Ye(ge),"user.id":Ce.id});let Ae,Me;{let Te=ot("SSO requires sessionStore configuration for opaque session cookies."),Ke=typeof Ce.sso.profile.sid==="string"?Ce.sso.profile.sid:void 0,Ue=Ke||st(32),qe=Ce.id;if(k.debug("SSO session creation evaluated",{"ion.event":"ion.sso.session.create_evaluated","ion.module":"sso","ion.operation":"session.create",hasSid:Boolean(Ue),hasIdpSid:Boolean(Ke),hasSub:Boolean(qe),"user.id":qe}),!qe)throw Error("Session creation failed: missing sub in ID token claims");let St=Date.now(),Yt={sid:Ue,sub:qe,idpSid:Ke,authType:"sso",tenantId:X.tenantId,tokens:ce,claims:Ce.sso.profile,expiresAt:we,createdAt:new Date};await vt(Te,Yt),Me=Yt,Ae=["Set-Cookie",ct("session",Ue,we)],k.info("SSO session created",{"ion.event":"ion.sso.session.created","ion.operation":"session.create","ion.outcome":"success","duration.ms":Ye(St),"user.id":qe})}if(X.userStore)try{let Te=Ce.id;if(Te){let Ke=new Date,Ue=Date.now();k.debug("SSO user store lookup started",{"ion.event":"ion.sso.user.lookup_started","ion.module":"sso","ion.operation":"user.lookup","user.id":Te});let qe=await X.userStore.get(Te);if(k.debug("SSO user store lookup completed",{"ion.event":"ion.sso.user.lookup_completed","ion.module":"sso","ion.operation":"user.lookup","duration.ms":Ye(Ue),"user.id":Te,found:Boolean(qe)}),qe||X.enableJitUserProvisioning){let St=Date.now(),Yt={...qe??{},...Ce,id:Te,tenantId:qe?.tenantId,createdAt:qe?.createdAt??Ke,updatedAt:Ke};await X.userStore.upsert(Yt),k.info("SSO user stored",{"ion.event":"ion.sso.user.stored","ion.operation":"user.store","ion.outcome":"success","duration.ms":Ye(St),"user.id":Te,existing:Boolean(qe),jitProvisioning:Boolean(X.enableJitUserProvisioning)})}else k.warn("JIT user provisioning disabled: user not found in store and will not be created",{"ion.event":"ion.sso.user.skipped","ion.operation":"user.store","ion.outcome":"skipped","user.id":Te})}else k.warn("User storage skipped: missing sub in ID token claims",{"ion.event":"ion.sso.user.skipped","ion.operation":"user.store","ion.outcome":"skipped"})}catch(Te){k.warn("Failed to store user",{"ion.event":"ion.sso.user.store_failed","ion.operation":"user.store","ion.outcome":"degraded",...Fn(Te)})}k.info("SSO sign-in succeeded",{"ion.event":"ion.sso.sign_in.succeeded","ion.operation":"sign_in.callback","ion.outcome":"success","duration.ms":Ye(B),"user.id":Ce.id});let ze=[["Set-Cookie",rt(Se(fe))],...Ae?[Ae]:[]],Qe=await X.afterLogin?.({ok:!0,request:M,user:Ce,session:Me,context:se}),Ve=wt(Qe,"/",M.url);if(Ve.response)return At(Ve.response,ze.map(([,Te])=>Te));return new Response("Authentication successful, redirecting",{status:302,headers:[["Location",Ve.location],...ze]})}catch(fe){k.error("Error during sign-in callback",{"ion.event":"ion.sso.sign_in.callback_failed","ion.operation":"sign_in.callback","ion.outcome":"failure","duration.ms":Ye(B),...Fn(fe)});let be=re?[["Set-Cookie",rt(Se(re))]]:[],me=await X.afterLogin?.({ok:!1,request:M,error:fe,context:se}),Ie=wt(me,"/",M.url);if(Ie.response)return At(Ie.response,be.map(([,Oe])=>Oe));return new Response("Authentication failed, redirecting",{status:302,headers:[["Location",Ie.location],...be]})}}function tt(M){let B=Date.now(),J=Number(M.expires_in??3600)||3600,F=new Date(B+J*1000),ne;if(M.refresh_expires_in!=null&&Number.isFinite(Number(M.refresh_expires_in)))ne=Number(M.refresh_expires_in);else if(M.refresh_token)ne=je;else ne=J;return{tokenExpiresAt:F,sessionExpiresAt:new Date(B+ne*1000)}}async function Ge(M,B,J){if(!X)throw Error("ionite SSO Manager not initialized");let F=Date.now(),ne=await Lt(M.id_token,B);return k.debug("SSO user parsed from ID token",{"ion.event":"ion.sso.user.parse_completed","ion.module":"sso","ion.operation":"id_token.parse","duration.ms":Ye(F),"user.id":ne.sub,hasEmail:Boolean(ne.email),hasName:Boolean(ne.name)}),Je(ne,M,J)}function Je(M,B,J){let F=J??tt(B).sessionExpiresAt,ne=M.ecid!==void 0&&M.ecid!==null?w(M.ecid):void 0;return{id:M.sub,userName:M.preferred_username||"",name:M.name||"",email:M.email||"",emails:[{value:M.email||"",primary:!0}],...ne?{ecid:ne}:{},avatar:M.picture,sso:{profile:{...M},tenant:{id:M.idp||M.iss||"",name:M.iss||""},scope:B.scope,tokenType:B.token_type,sessionState:B.session_state,expires:F}}}async function nt(M){if(!X.userStore)return M;let B=await X.userStore.lookup(M);if(!B)return M;return{...M,...B,id:M.id,sso:M.sso}}async function Ut(M,B,J){if(!X)throw Error("ionite SSO Manager not initialized");De();let F=t(X.tokenUrl,"Missing 'tokenUrl' from SSO Config"),ne=t(X.redirectUri,"Missing 'redirectUri' from SSO Config"),pe=t(X.clientId,"Missing 'clientId' from SSO Config"),de=ne;try{new URL(de)}catch{if(J)try{let se=new URL(J),fe=de.startsWith("//")?de.slice(1):de.startsWith("/")?de:`/${de}`;de=new URL(fe,se.origin).toString()}catch{try{let se=new URL(F),fe=de.startsWith("//")?de.slice(1):de.startsWith("/")?de:`/${de}`;de=new URL(fe,se.origin).toString()}catch{throw Error(`Invalid redirectUri: "${ne}". It must be a valid absolute URL.`)}}}let re=new URLSearchParams;if(re.append("grant_type","authorization_code"),re.append("code",M),re.append("redirect_uri",de),re.append("client_id",pe),X.clientSecret)re.append("client_secret",X.clientSecret);re.append("code_verifier",B);try{let se=Date.now();k.debug("SSO token exchange started",{"ion.event":"ion.sso.token.exchange_started","ion.module":"sso","ion.operation":"token.exchange",...dn(F,"oidc.token_url"),...dn(de,"oidc.redirect_uri"),hasClientSecret:Boolean(X.clientSecret)});let fe=await fetch(F,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:re.toString()});k.debug("SSO token exchange response received",{"ion.event":"ion.sso.token.response_received","ion.module":"sso","ion.operation":"token.exchange","http.status_code":fe.status,"duration.ms":Ye(se)}),k.debug("SSO token exchange response body read started",{"ion.event":"ion.sso.token.response_body_read_started","ion.module":"sso","ion.operation":"token.exchange"});let be=await fe.json();if(k.debug("SSO token exchange response body read completed",{"ion.event":"ion.sso.token.response_body_read_completed","ion.module":"sso","ion.operation":"token.exchange","duration.ms":Ye(se)}),!fe.ok){k.error("Token exchange error",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure","http.status_code":fe.status,"duration.ms":Ye(se),...Ii(be)});let Ie=be;throw Error(`Token exchange failed: ${Ie.error||fe.statusText} - ${Ie.error_description||""}`.trim())}let me=await y.tokenResponse.validate(be);if(me.issues)throw k.error("Token response validation failed",{"ion.event":"ion.sso.token.response_validation_failed","ion.operation":"token.exchange","ion.outcome":"failure","duration.ms":Ye(se),"validation.issues":ln(me.issues)}),Error(`Token response validation failed: ${me.issues}`);return k.debug("SSO token exchange completed",{"ion.event":"ion.sso.token.exchange_completed","ion.module":"sso","ion.operation":"token.exchange","ion.outcome":"success","duration.ms":Ye(se),tokenType:me.value.token_type,hasAccessToken:Boolean(me.value.access_token),hasIdToken:Boolean(me.value.id_token),hasRefreshToken:Boolean(me.value.refresh_token),expiresIn:me.value.expires_in}),me.value}catch(se){throw k.error("Error during token exchange",{"ion.event":"ion.sso.token.exchange_failed","ion.operation":"token.exchange","ion.outcome":"failure",...Fn(se)}),se}}async function Rt(M){return Cn(async()=>{if(!X)throw Error("ionite SSO Manager not initialized");De();let B=t(X.tokenUrl,"Missing 'tokenUrl' from SSO Config"),J=t(X.clientId,"Missing 'clientId' from SSO Config"),F=new URLSearchParams;if(F.append("grant_type","refresh_token"),F.append("refresh_token",M),F.append("client_id",J),X.clientSecret)F.append("client_secret",X.clientSecret);let ne=await fetch(B,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:F.toString()}),pe=await ne.json();if(!ne.ok){k.error("Token refresh error",{"ion.operation":"token.refresh","ion.outcome":"failure",response:pe});let re=pe;throw Error(`Token refresh failed: ${re.error||ne.statusText} - ${re.error_description||""}`.trim())}let de=await y.tokenResponse.validate(pe);if(de.issues)throw k.error("Token refresh response validation failed",{"ion.event":"ion.sso.token.refresh_validation_failed","ion.operation":"token.refresh","ion.outcome":"failure","validation.issues":ln(de.issues)}),Error(`Token refresh response validation failed: ${de.issues}`);return de.value},void 0,void 0,void 0,k)}async function Et(M){try{if(!X)throw Error("ionite SSO Manager not initialized");if(!X.revocationEndpoint)return;let B=t(X.clientId,"Missing 'clientId' from SSO Config"),J=new URLSearchParams;if(J.append("token",M),J.append("token_type_hint","refresh_token"),J.append("client_id",B),X.clientSecret)J.append("client_secret",X.clientSecret);let F=await fetch(X.revocationEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:J.toString()});if(!F.ok)k.warn("Token revocation failed",{"ion.operation":"token.revoke","ion.outcome":"degraded",status:F.status,statusText:F.statusText});else k.info("Token revoked successfully",{"ion.module":"sso"})}catch(B){k.warn("Error revoking token",{"ion.operation":"token.revoke","ion.outcome":"degraded"},B)}}async function Dt(){if(!X)throw Error("ionite SSO Manager not initialized");let M=X.authority;if(!X.jwksUri&&!M)throw Error("Missing 'jwksUri' or 'authority' from SSO Config. OIDC configuration is required for this operation.");let B=X.jwksUri||`${M}/protocol/openid-connect/certs`;return Wt(B,k)}async function Lt(M,B){let J=Date.now(),F=t(X.authority,"Missing 'authority' from SSO Config. OIDC configuration is required to verify ID tokens."),ne=t(X.clientId,"Missing 'clientId' from SSO Config. OIDC configuration is required to verify ID tokens."),pe=X.jwksUri||`${F}/protocol/openid-connect/certs`;k.debug("SSO ID token verification started",{"ion.event":"ion.sso.id_token.verify_started","ion.module":"sso","ion.operation":"id_token.verify",...dn(pe,"oidc.jwks_uri")});let de;try{de=await kt({idToken:M,jwksUri:pe,issuer:F,audience:ne,expectedNonce:B,log:k})}catch(se){throw k.error("SSO ID token verification failed",{"ion.event":"ion.sso.id_token.verify_failed","ion.module":"sso","ion.operation":"id_token.verify","ion.outcome":"failure","duration.ms":Ye(J)},se),se}k.debug("SSO ID token signature verified",{"ion.event":"ion.sso.id_token.signature_verified","ion.module":"sso","ion.operation":"id_token.verify","duration.ms":Ye(J)});let re=await y.idTokenClaims.validate(de);if(re.issues)throw k.error("ID token claims validation failed",{"ion.event":"ion.sso.id_token.validation_failed","ion.operation":"id_token.validate","ion.outcome":"failure","duration.ms":Ye(J),"validation.issues":ln(re.issues)}),Error(`ID token claims validation failed: ${re.issues}`);return k.debug("SSO ID token claims validated",{"ion.event":"ion.sso.id_token.claims_validated","ion.module":"sso","ion.operation":"id_token.validate","ion.outcome":"success","duration.ms":Ye(J),"user.id":re.value.sub,hasIssuer:Boolean(re.value.iss),hasAudience:Boolean(re.value.aud)}),re.value}function ot(M="SSO sessionStore is required for opaque session cookies."){if(!X.sessionStore)throw Error(M);return X.sessionStore}async function vt(M,B){try{await M.create(B)}catch(J){if(!await M.get(B.sid))throw J;await M.update(B.sid,B)}}function gt(M){if(!M)return;if(M instanceof Date)return M;let B=new Date(M);return Number.isNaN(B.getTime())?void 0:B}function at(M){let B=M.tokens;if(!B?.access_token||!B.id_token||!B.token_type)return;return B}async function It(M,B=!1){let J=ot(),F=ht("session",M);if(!F)return{tokens:void 0,refreshHeaders:[]};let ne=await J.get(F);if(ne&&X.tenantId&&ne.tenantId&&ne.tenantId!==X.tenantId)return{tokens:void 0,refreshHeaders:[["Set-Cookie",rt("session")]],sid:F};if(ne?.authType!=="sso")return{tokens:void 0,refreshHeaders:[["Set-Cookie",rt("session")]],sid:F};let pe=at(ne);if(!pe)return{tokens:void 0,refreshHeaders:[["Set-Cookie",rt("session")]],sid:F};let de=gt(ne.expiresAt);if(de?Date.now()>de.getTime():!1)return await J.delete(F),{tokens:void 0,sid:F,refreshHeaders:[["Set-Cookie",rt("session")]]};let se=gt(pe.expires),fe=se?Date.now()>se.getTime():!0;if((B||fe)&&pe.refresh_token)return lt(F,ne,pe);return{tokens:pe,sid:F,session:ne,refreshHeaders:[]}}function lt(M,B,J){let F=H.get(M);if(F)return F;let ne=ot(),pe=(async()=>{let de=await Rt(J.refresh_token),{tokenExpiresAt:re,sessionExpiresAt:se}=tt(de);de.expires=re.toISOString();let fe=await Ge(de,void 0,se),be=fe.sso.profile,me=st(32),Ie={...B,sid:me,tokens:de,claims:be,expiresAt:se,createdAt:new Date};await vt(ne,Ie);try{if(Pe<=0)await ne.delete(M);else{let{refresh_token:Oe,...Ee}=J;await ne.update(M,{tokens:Ee,expiresAt:new Date(Date.now()+Pe)})}}catch(Oe){k.warn("Failed to retire rotated SSO session record",{"ion.operation":"session.rotate","ion.outcome":"degraded"},Oe)}return{tokens:de,sid:me,session:Ie,refreshedUser:fe,refreshHeaders:[["Set-Cookie",ct("session",me,se)]]}})();return H.set(M,pe),pe.finally(()=>{H.delete(M)})}async function Ze(M,B=!1){return It(M,B)}async function yt(M){let{tokens:B}=await Ze(M);if(!B)return;return B.access_token}function ct(M,B,J,F=X.cookiesSameSite??"Strict"){if(!X)throw Error("ionite SSO Manager not initialized");if(M=`${X.cookiesPrefix}.${M}`,typeof B!=="string")B=btoa(JSON.stringify(B));let ne;if(J instanceof Date)ne=`Expires=${J.toUTCString()}`;else if(typeof J==="number")ne=`Max-Age=${J}`;else throw Error("Invalid expires type",J);if(B.length>4000)throw Error(`Error setting cookie: ${M}. Cookie length is: ${B.length}`);return`${M}=${B}; ${ne}; Path=${X.cookiesPath}; HttpOnly;${X.cookiesSecure?" Secure;":""} SameSite=${F};`}function rt(M){if(!X)throw Error("ionite SSO Manager not initialized");return`${X.cookiesPrefix}.${M}=; Max-Age=0; Path=${X.cookiesPath}; HttpOnly;${X.cookiesSecure?" Secure;":""} SameSite=${X.cookiesSameSite};`}function ht(M,B,J=!1){if(!X)throw Error("ionite SSO Manager not initialized");let F=B.headers.get("cookie");if(!F)return null;let ne=`${X.cookiesPrefix}.${M}`,pe=F.split(";").find((fe)=>fe.trim().startsWith(`${ne}=`));if(!pe)return null;let de=pe.indexOf("="),re=pe.slice(de+1).trim();if(!J)return re;let se=atob(re);return JSON.parse(se)}function Se(M){return`state_${M}`}async function ve(M,B){if(!X)throw Error("ionite SSO Manager not initialized");let{loginUrl:J,userUrl:F,tokenUrl:ne,refreshUrl:pe,logoutUrl:de,logoutBackChannelUrl:re,jwksUrl:se,redirectUri:fe}={...X,...B},be=new URL(M.url).pathname;if(fe){let me;try{me=new URL(fe).pathname}catch{try{let Ie=new URL(M.url),Oe=fe.startsWith("//")?fe.slice(1):fe;me=new URL(Oe,Ie.origin).pathname}catch{me=fe.startsWith("/")?fe:`/${fe}`}}if(me===be)return $e(M)}if(J===be)return ye(M);if(F===be)try{let{tokens:me,session:Ie,refreshedUser:Oe,refreshHeaders:Ee}=await Ze(M);if(!me)return new Response("User not logged in",{status:401,headers:Ee});let ae=Oe??(Ie?.claims?Je(Ie.claims,me,gt(Ie.expiresAt)):void 0);if(!ae)return new Response("User not logged in",{status:401,headers:Ee});let ee=await nt(ae);return new Response(JSON.stringify(ee),{headers:[["Content-Type","application/json"],...Ee]})}catch(me){if(xr(me))return new Response("User not logged in",{status:401});return k.error("Error resolving SSO user",{"ion.operation":"sso.user","ion.outcome":"degraded"},me),new Response(JSON.stringify({error:"auth_unavailable"}),{status:503,headers:{"Content-Type":"application/json"}})}if(ne===be){let{tokens:me,refreshHeaders:Ie}=await Ze(M);if(!me)return new Response("User not logged in",{status:401,headers:Ie});return new Response(JSON.stringify({token:me.access_token,expires:me.expires}),{headers:[["Content-Type","application/json"],...Ie]})}if(pe===be){let{tokens:me,refreshHeaders:Ie}=await Ze(M,!0);if(!me)return new Response("User not logged in",{status:401});return new Response("Refresh Complete",{status:200,headers:Ie})}if(de===be)return _e(M);if(re===be)return Ne(M);if(se===be){let me=await Dt();return new Response(JSON.stringify(me),{headers:[["Content-Type","application/json"]]})}return new Response("Not Found",{status:404})}return{...X,getUser:Le,resolveUser:We,getJwt:yt,initiateLogin:ye,logout:_e,logoutBackChannel:Ne,callbackHandler:$e,handler:ve}}function Pi(y){let k={},R=y.split(";");for(let W of R){let V=W.trim();if(!V)continue;let G=V.indexOf("=");if(G===-1)continue;let H=V.slice(0,G).trim(),Y=V.slice(G+1).trim();k[H]=Y}return k}function xr(y){if(!(y instanceof Error))return!1;return["Public key not found","Invalid JWT","Invalid JWT signature","ID token expired","ID token issuer mismatch","ID token audience mismatch","ID token nonce mismatch","ID token missing exp","invalid_grant"].some((k)=>y.message.includes(k))}function Ur(y){return y=y??"SSO Unavailable",new Response(JSON.stringify({error:y}),{status:503,statusText:y,headers:{"Content-Type":"application/json"}})}var pn="Ionite instance is required. Create one with ionite(source, config) and pass it to this function.";async function xi(y,k){return t(k,pn),k.sso?.getUser(y)}async function Ui(y,k){return t(k,pn),await k.sso?.resolveUser(y)??{status:"unauthenticated"}}async function Ei(y,k){t(k,pn);let R=k.sso;if(!R)return Ur();return R.initiateLogin(y)}async function Mi(y,k){t(k,pn);let R=k.sso;if(!R)return Ur();return R.callbackHandler(y)}export{Ft as CACHE_BOUNDS,Qn as CIAM_PROVIDER_PRESETS,_ as CatalogAdjacencyCache,Z as InMemoryTenantStore,fs as allowHosts,ms as allowOrigins,pr as allowRelativePaths,mr as allowSameOrigin,Cr as assertSubjectTypeAssignable,cr as assertTrustedIdTokenClaims,Ln as baseCustomerToScim,On as baseUserToScimUser,Dn as baseWorkloadToScim,lr as blockDangerousUrls,An as buildAuthorizationUrl,Hn as buildLfvSigningInput,Mi as callback,ys as captureRedirect,ws as ciam,cs as clearDiscoveryCache,Zr as clearJwksCache,te as collectReferencedDefinitions,Jr as configureJwksCache,gs as defaultRedirectPolicies,xn as discoverOidcEndpoints,Pr as discoverSessionRecords,Tr as discoverSessions,_n as entitlementToScimGroup,Tn as exchangeAuthorizationCode,O as expandRoot,Un as fetchUserInfo,En as generateAppleClientSecret,pi as generateLfvEd25519KeyPair,Rn as getCachedVerificationKey,bs as getCustomer,bi as getDiscoveredSessionUsers,Wt as getJwks,gn as getProviderPreset,ts as getPublicKeyForKid,es as getPublicKeyFromJwks,xi as getUser,vn as getVerificationKeyForKid,Nr as has,zr as hasAll,Kr as hasAllScope,$r as hasAny,Gr as hasAnyScope,qr as hasGroup,Wr as hasPermission,Vr as hasRole,Br as hasScope,si as iam,Ei as initiateLogin,fr as isRedirectAllowed,Ai as listSsoClientIdsFromCookies,qt as normalizeOidcIssuer,hn as orderedEnabledProviders,Rr as parseLfvJwks,$t as pkceChallengeFromVerifier,z as reconcileSubjectAccess,wt as resolveAfterRedirect,mi as resolveCacheConfig,hs as resolveCapturedRedirect,Zt as resolveCiamProvider,Cs as resolveCustomer,Qr as resolveJwkForKid,vr as resolveJwksCacheConfig,yn as resolveProviderBranding,jn as resolveRedirect,Ir as resolveSessionCacheConfig,Ui as resolveUser,Mn as sameOriginRedirectRules,le as sendTenantWebhook,as as setDiscoveryClock,Hr as setJwksClock,Fr as setJwksRetry,li as signLfvPayload,Ti as sso,ai as stringifyLfvJwks,kt as verifyIdToken,di as verifyLfvSignature,Pn as verifyLogoutToken,vi as verifyUser,At as withSetCookies};
|