@enterprisestandard/server 0.0.8 → 0.0.9-beta.20260301.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +82 -1
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -1 +1,82 @@
1
- import{createValidators as aL,defaultLogger as dS,tenant as eL}from"@enterprisestandard/core";import{ciam as oL,iam as S$,sso as L$}from"@enterprisestandard/core/server";function MS(S){throw Error("Not implemented")}function NS(S){throw Error("Not implemented")}function IS(S){return console.warn("ES_CONFIG_TYPE is not set. For LLM documentation, see https://enterprisestandard.com/llms.txt"),console.warn(`If this is a local development environment, visit https://ionite.com/dev?appId=${S.appId??""} to get started, or run: npx @enterprisestandard/cli`),{load:async()=>{return{}},subscribe(L){let $=()=>{};return()=>{}}}}function HS(S){throw Error("Not implemented")}var YS=new Map;function QL(S){if(!S)return"/";return S.startsWith("/")?S:`/${S}`}function zL(S){try{let L=new URL(S),$=L.pathname.replace(/\/+$/g,"");return`${L.origin}${$}`}catch{return S.replace(/\/+$/g,"")}}function nS(S){let L=zL(S.lfvServerUrl),$=QL(S.path);return`${L}|${$}`}function fS(S,L,$){let R=YS.get(S)??new Map;return R.set(L,$),YS.set(S,R),()=>{let U=YS.get(S);if(!U)return;if(U.delete(L),U.size===0)YS.delete(S)}}async function gS(S,L,$){let R=YS.get(S);if(!R)return 0;let U=0;for(let[D,X]of R){if($&&D===$)continue;if(!X.onDelivery)continue;U+=1,await X.onDelivery(L)}return U}async function sS(S,L,$){let R=YS.get(S);if(!R)return 0;let U=0;for(let[D,X]of R){if($&&D===$)continue;if(!X.onEvents)continue;U+=1,await X.onEvents(L)}return U}function lS(S){try{return new URL(S).pathname}catch{return S.startsWith("/")?S:`/${S}`}}var ML=1e4,NL=1e4;async function iS(S){await new Promise((L)=>setTimeout(L,S))}function SS(S){return{startedAt:Date.now(),timeout:typeof S?.timeout==="number"&&S.timeout>0?S.timeout:void 0}}function KS(S){if(S.timeout===void 0)return;let L=Date.now()-S.startedAt;return Math.max(0,S.timeout-L)}function XS(S,L,$){return Error(`LFV ${S} timed out after ${$.timeout??0}ms for ${L}`)}async function GS(S,L,$,R,U){let D=KS($);if(D!==void 0){if(D<=0)throw XS(R,U,$);let X=new AbortController,J=setTimeout(()=>X.abort(),D);try{return await fetch(S,{...L,signal:X.signal})}catch(M){if(M instanceof Error&&M.name==="AbortError")throw XS(R,U,$);throw M}finally{clearTimeout(J)}}return await fetch(S,L)}async function pS(S,L,$,R,U,D){let X=0,J=Date.now();for(;;){let M=KS(L);if(M!==void 0&&M<=0)throw XS(R,$,L);try{return await S()}catch(Z){if(X+=1,D>0&&Date.now()-J>=D){let K=Z instanceof Error?Z.message:String(Z);console.warn(`Error connecting to the LFV source. Retries: '${X}' Error: ${K}`),J=Date.now()}let z=M===void 0?U:Math.min(U,M);if(z<=0)throw XS(R,$,L);await iS(z)}}}function HL(S){return typeof S==="object"&&S!==null&&!Array.isArray(S)}function ES(S){let{lfvServerUrl:L,clientId:$,path:R}=S,U=S.signature??"sdk-placeholder-signature",D=typeof S.deliveryTimeout==="number"&&S.deliveryTimeout>0?S.deliveryTimeout:void 0,X=typeof S.retryInterval==="number"&&S.retryInterval>0?S.retryInterval:ML,J=typeof S.warnInterval==="number"&&S.warnInterval>=0?S.warnInterval:NL,M=lS(S.deliveryEndpoint),Z=lS(S.eventsEndpoint),z=nS({lfvServerUrl:L??"",path:R??""}),K=crypto.randomUUID(),P=new Map,y=new Map,n=new Map,E;function w(){let _=P.size>0,Y=n.size>0,F=_||Y;if(F&&!E){E=fS(z,K,{onDelivery:async(A)=>{j(A)},onEvents:async(A)=>{I(A)}});return}if(!F&&E)E(),E=void 0}function q(_){if(!L)throw Error(`LFV source requires "lfvServerUrl" for path ${_}`);if(!$)throw Error(`LFV source requires "clientId" for path ${_}`);return{lfvUrl:L,clientId:$}}async function V(_){return _.text().catch(()=>"")}async function k(_,Y,F,A){let O=q(_),d=F??crypto.randomUUID(),h=A??SS(),f={request_id:d,path:_,action:Y},c=await pS(async()=>{return await GS(`${O.lfvUrl.replace(/\/+$/g,"")}/clients/${O.clientId}/otp`,{method:"POST",headers:{"Content-Type":"application/json","X-LFV-Request-Id":d,"X-LFV-Signature":U},body:JSON.stringify(f)},h,"issueOtp",_)},h,_,"issueOtp",X,J);if(c.status!==200){let o=await V(c);throw Error(`LFV OTP request failed (${c.status}) for ${_}: ${o}`)}let _S=await c.json();if(!_S.otp)throw Error(`LFV OTP response missing otp for ${_}`);return _S.otp}async function g(_,Y,F,A,O,d){let h=q(Y),f=O??crypto.randomUUID(),c=d??SS(),_S=await k(Y,F,f,c),o=await pS(async()=>{return await GS(`${h.lfvUrl.replace(/\/+$/g,"")}${_}`,{method:"POST",headers:{"Content-Type":"application/json","X-LFV-Request-Id":f,"X-LFV-Signature":U},body:JSON.stringify({request_id:f,otp:_S,path:Y,...A??{}})},c,F,Y)},c,Y,F,X,J);if(o.status!==200&&o.status!==202){let QS=await V(o);throw Error(`LFV ${F} failed (${o.status}) for ${Y}: ${QS}`)}return{requestId:f}}async function t(_,Y,F){let A=y.get(_);if(A)return A;let O=F?.timeout??D,d={startedAt:Date.now(),timeout:typeof O==="number"&&O>0?O:void 0},h,f=new Promise((i)=>{h={resolve:i};let LS=n.get(_)??new Set;LS.add(h),n.set(_,LS),w()}),c=()=>{if(!h)return;let i=n.get(_);if(i?.delete(h),i&&i.size===0)n.delete(_);w()},_S=Y??crypto.randomUUID(),o=0,QS=Date.now();for(;;)try{await g("/secrets/request",_,"read_secret",void 0,_S,d);break}catch(i){let LS=KS(d);if(LS!==void 0&&LS<=0)throw c(),XS("read_secret",_,d);if(o+=1,J>0&&Date.now()-QS>=J){let GL=i instanceof Error?i.message:String(i);console.warn(`LFV read_secret retrying for ${_}. Retries: '${o}' Error: ${GL}`),QS=Date.now()}let zS=LS===void 0?X:Math.min(X,LS);if(zS<=0)throw c(),XS("read_secret",_,d);await iS(zS)}let WS=KS(d);if(WS!==void 0){if(WS<=0)throw c(),Error(`LFV delivery timed out while reading ${_}`);let i;try{return await Promise.race([f,new Promise((LS,zS)=>{i=setTimeout(()=>{c(),zS(Error(`LFV delivery timed out while reading ${_}`))},WS)})])}finally{if(i)clearTimeout(i)}}return await f}function s(_,Y){y.set(_,Y);let F=P.get(_);if(!F)return;for(let A of F)A(Y)}async function p(_,Y){return await t(_,void 0,Y)}async function DS(_,Y,F){if(!HL(Y))throw Error(`putSecret requires an object value for LFV source at path ${_}`);let A=SS(F);if(await x(_,F)){await g("/secrets/update",_,"update_secret",{data:Y},void 0,A);return}await g("/secrets/create",_,"create_secret",{data:Y},void 0,A)}async function T(_,Y){let F=SS(Y);await g("/secrets/delete",_,"delete_secret",void 0,void 0,F)}async function C(_,Y){let F=q(_),A=SS(Y),O=crypto.randomUUID(),d=await k(_,"list_paths",O,A),h=await GS(`${F.lfvUrl.replace(/\/+$/g,"")}/paths/list`,{method:"POST",headers:{"Content-Type":"application/json","X-LFV-Request-Id":O,"X-LFV-Signature":U},body:JSON.stringify({request_id:O,otp:d,path:_})},A,"listPaths",_);if(h.status!==200){let c=await V(h);throw Error(`LFV listPaths failed (${h.status}) for ${_}: ${c}`)}let f=await h.json();if(!Array.isArray(f.items))throw Error(`LFV listPaths returned invalid payload for ${_}`);return f.items.filter((c)=>typeof c==="string")}async function x(_,Y){let F=q(_),A=SS(Y),O=crypto.randomUUID(),d=await k(_,"read_metadata",O,A),h=await GS(`${F.lfvUrl.replace(/\/+$/g,"")}/paths/exists`,{method:"POST",headers:{"Content-Type":"application/json","X-LFV-Request-Id":O,"X-LFV-Signature":U},body:JSON.stringify({request_id:O,otp:d,path:_})},A,"exists",_);if(h.status!==200){let c=await V(h);throw Error(`LFV exists failed (${h.status}) for ${_}: ${c}`)}let f=await h.json();if(typeof f.exists!=="boolean")throw Error(`LFV exists returned invalid payload for ${_}`);return f.exists}async function v(_,Y,F){let A=SS(F);await g("/secrets/rotate/request",_,"request_rotate",{reason:Y?.reason,severity:Y?.severity,incident_ref:Y?.incidentRef},void 0,A)}async function b(_,Y,F){let A=SS(F);await g("/secrets/revoke/request",_,"request_revoke",{reason:Y?.reason,severity:Y?.severity,incident_ref:Y?.incidentRef},void 0,A)}async function u(_,Y){let F=q(_),A=SS(Y),O=crypto.randomUUID(),d=await k(_,"read_metadata",O,A),h=await GS(`${F.lfvUrl.replace(/\/+$/g,"")}/paths/metadata/read`,{method:"POST",headers:{"Content-Type":"application/json","X-LFV-Request-Id":O,"X-LFV-Signature":U},body:JSON.stringify({request_id:O,otp:d,path:_})},A,"getMetadata",_);if(h.status!==200){let c=await V(h);throw Error(`LFV getMetadata failed (${h.status}) for ${_}: ${c}`)}let f=await h.json();if(!f.metadata||typeof f.metadata!=="object")throw Error(`LFV getMetadata returned invalid payload for ${_}`);return f.metadata}function W(_,Y){let F=P.get(_)??new Set;F.add(Y),P.set(_,F);let A=y.get(_);if(A)Y(A);return w(),()=>{let O=P.get(_);if(!O)return;if(O.delete(Y),O.size===0)P.delete(_);w()}}function m(_){return _.method==="POST"&&new URL(_.url).pathname===M}function Q(_){return _.method==="POST"&&new URL(_.url).pathname===Z}function G(_){let Y=_.data?.metadata?.path;if(typeof Y==="string"&&Y)return Y;if(typeof _.path==="string"&&_.path)return _.path;return}function N(_,Y){let F=n.get(_);if(!F||F.size===0)return!1;n.delete(_),w();for(let A of F)A.resolve(Y);return!0}function j(_){let Y=G(_);if(!Y)return{handled:!1};let F=_.data?.metadata??{},A=typeof F.version==="number"?F.version:0,O={data:_.data?.data??{},metadata:{path:Y,version:A,created:new Date}};return s(Y,O),{handled:N(Y,O)}}async function B(_){let Y=await _.json(),F=j(Y),A=await gS(z,Y,K);if(!F.handled&&A===0)return new Response(JSON.stringify({status:"accepted",note:"unmapped_delivery"}),{status:200,headers:{"Content-Type":"application/json"}});return new Response(JSON.stringify({status:"accepted"}),{status:200,headers:{"Content-Type":"application/json"}})}function I(_){if(!_?.path||typeof _.path!=="string")return;if(_.event==="created"||_.event==="updated"||_.event==="rotated"||_.event==="revoked")t(_.path,_.request_id).catch(()=>{})}async function H(_){let Y=await _.json();if(!Y?.path||typeof Y.path!=="string")return new Response(JSON.stringify({error:"invalid_request",message:"path is required"}),{status:400,headers:{"Content-Type":"application/json"}});return I(Y),await sS(z,Y,K),new Response(JSON.stringify({status:"accepted"}),{status:200,headers:{"Content-Type":"application/json"}})}return{type:S.type,getFullSecret:p,getSecret:async(_,Y)=>{return(await p(_,Y)).data},putSecret:DS,deleteSecret:T,listPaths:C,exists:x,requestRotate:v,requestRevoke:b,getMetadata:u,subscribe:W,isDeliveryRequest:m,isEventsRequest:Q,handleDelivery:B,handleEvents:H}}function $S(S,L,$){if(typeof S!=="string"||S.trim()==="")throw Error(`"${L}" is required when using ${$}`);return S}var wS="__esLfvBootstrap";function xS(S){let L=$S(S.path,"path","lfvConfig"),$=$S(S.deliveryEndpoint,"deliveryEndpoint","lfvConfig"),R=$S(S.eventsEndpoint,"eventsEndpoint","lfvConfig"),U={type:"lfv",path:L,lfvServerUrl:S.lfvServerUrl,clientId:S.clientId,signature:S.signature,deliveryTimeout:S.deliveryTimeout,retryInterval:S.retryInterval,warnInterval:S.warnInterval,deliveryEndpoint:$,eventsEndpoint:R,verifyPublicKey:S.verifyPublicKey},D=S.vault??ES({type:"lfv",path:L,lfvServerUrl:$S(S.lfvServerUrl,"lfvServerUrl","lfvConfig"),clientId:$S(S.clientId,"clientId","lfvConfig"),signature:S.signature,deliveryTimeout:S.deliveryTimeout,retryInterval:S.retryInterval,warnInterval:S.warnInterval,deliveryEndpoint:$,eventsEndpoint:R,verifyPublicKey:S.verifyPublicKey}),X={load:async()=>{try{return(await D.getFullSecret(L)).data}catch(J){throw Error("Error retrieving remote config from LFV",{cause:J})}},subscribe:(J)=>{return D.subscribe(L,(M)=>{J(M.data)})}};return X[wS]=U,X}import{readFile as KL}from"node:fs";import{parseJsonc as EL}from"@enterprisestandard/core";function yS(S){let L=S.path??"es-config.jsonc",$=S.watch===!0;return{load:()=>{return new Promise((U,D)=>{KL(L,"utf-8",(X,J)=>{if(X){D(Error(`Failed to read config file "${L}": ${X.message}`));return}try{U(EL(J))}catch(M){let Z=M instanceof Error?M.message:String(M);D(Error(`Invalid JSON/JSONC in "${L}": ${Z}`))}})})},subscribe(U){throw Error("TODO: subscribe not implemented for local file config source")}}}function ZS(S){let{type:L="vault",url:$,token:R,ttl:U}=S;if(!$)throw Error("OpenBao/Hashicorp compatible vaults require a non-empty url");if(!R)console.log("OpenBao/Hashicorp compatible vaults usually require a token, but one was not provided. Vault requests may fail.");if(U&&U<600000)throw Error("OpenBao/Hashicorp compatible vaults require ttl to be set and greater than 600_000 milliseconds (10 minutes), as not to overload the vault with polling requests");let D={"Content-Type":"application/json"};if(R)D["X-Vault-Token"]=R;function X(E){return typeof E==="object"&&E!==null&&!Array.isArray(E)}async function J(E,w){let q=await fetch(`${$}/${E}`,{headers:{...D}});if(q.status!==200){let k=q.status===401||q.status===403?`Vault returned ${q.status} ${q.statusText} (auth error) from URL: ${$}/${E}`:`Vault returned invalid status, ${q.status}: '${q.statusText}' from URL: ${$}/${E}`;throw Error(k)}try{return(await q.json()).data}catch(V){throw Error("Error retrieving secret",{cause:V})}}async function M(E,w,q){if(!X(w))throw Error(`putSecret requires an object value for vault source at path ${E}`);let V=await fetch(`${$}/${E}`,{method:"POST",headers:D,body:JSON.stringify(w)});if(V.status!==200&&V.status!==201&&V.status!==204){let k=await V.text().catch(()=>"");throw Error(`Vault putSecret failed (${V.status}) for ${$}/${E}: ${k}`)}}async function Z(E,w){let q=await fetch(`${$}/${E}`,{method:"DELETE",headers:D});if(q.status!==200&&q.status!==202&&q.status!==204){let V=await q.text().catch(()=>"");throw Error(`Vault deleteSecret failed (${q.status}) for ${$}/${E}: ${V}`)}}async function z(E,w){let q=`${$}/${E}`,V=async(s)=>{if(s==="LIST")return fetch(q,{method:"LIST",headers:D});let p=q.includes("?")?"&":"?";return fetch(`${q}${p}list=true`,{method:"GET",headers:D})},k=await V("LIST");if(k.status===405||k.status===501)k=await V("GET");if(k.status!==200){let s=await k.text().catch(()=>"");throw Error(`Vault listPaths failed (${k.status}) for ${$}/${E}: ${s}`)}let g=await k.json().catch(()=>null),t;if(g&&typeof g==="object"){let s=g,p=s.data;if(p&&typeof p==="object")t=p.keys;else t=s.keys}if(!Array.isArray(t))throw Error(`Vault listPaths returned an unexpected response for ${$}/${E}`);return t.filter((s)=>typeof s==="string")}async function K(E,w){let q=await fetch(`${$}/${E}`,{headers:D});if(q.status===200)return!0;if(q.status===404)return!1;if(q.status===401||q.status===403)throw Error(`Vault exists failed (${q.status}) for ${$}/${E}: permission denied`);let V=await q.text().catch(()=>"");throw Error(`Vault exists failed (${q.status}) for ${$}/${E}: ${V}`)}async function P(E,w,q){throw Error(`Vault requestRotate is not implemented for source ${L} at path ${E}`)}async function y(E,w,q){throw Error(`Vault requestRevoke is not implemented for source ${L} at path ${E}`)}async function n(E,w){return(await J(E,w)).metadata}return{type:L,getFullSecret:J,getSecret:async(E,w)=>{return(await J(E,w)).data},putSecret:M,deleteSecret:Z,listPaths:z,exists:K,requestRotate:P,requestRevoke:y,getMetadata:n,subscribe:(E,w)=>{if(!U)return console.warn("OpenBao/Hashicorp compatible vaults require ttl to be set if you want to subscribe to changes"),()=>{};let q,V=setInterval(async()=>{try{let k=await J(E);if(q===void 0){q=k.metadata.version;return}if(k.metadata.version!==q)q=k.metadata.version,w(k)}catch(k){console.warn(`Error retrieving remote config from vault. Retrying in ${S.ttl} milliseconds`,k)}},U);return()=>clearInterval(V)}}}function tS(S){if(!S||typeof S!=="object"||Array.isArray(S))return{};let L=S;if(!(("tenantId"in L)||("sso"in L)||("iam"in L)||("workload"in L)||("secrets"in L)||("tenant"in L)||("ciam"in L))&&Object.keys(L).length===1&&"data"in L){let R=L.data;if(R&&typeof R==="object"&&!Array.isArray(R))return R}return L}function BS(S){let L=$S(S.path,"path","vaultConfig"),$=S.vault??ZS({type:"vault",url:S.url,token:S.token,ttl:S.ttl});return{load:async()=>{try{let R=await $.getFullSecret(L);return tS(R.data)}catch(R){if(!S?.retryInterval)throw Error("Error retrieving remote config from vault",{cause:R});else return console.warn(`Error retrieving remote config from vault. Retrying in ${S.ttl} seconds`,R),{}}},subscribe:(R)=>{return $.subscribe(L,(U)=>{R(tS(U.data))})}}}function kS(S){if(!S)return;let L=Number.parseInt(S,10);return Number.isFinite(L)?L:void 0}function vS(S){let L=S?.type??process.env.ES_CONFIG_TYPE;if(!L||L==="dev"){let $=S??{};return IS({appId:$?.appId??process.env.ES_APP_ID,path:process.env.ES_CONFIG_PATH??$?.path,ioniteUrl:process.env.ES_IONITE_URL??$?.ioniteUrl})}else if(L==="lfv"){let $=S??{};return xS({path:process.env.ES_LFV_PATH??$?.path,lfvServerUrl:process.env.ES_LFV_SERVER_URL??$?.lfvServerUrl,clientId:process.env.ES_LFV_CLIENT_ID??$?.clientId,signature:process.env.ES_LFV_SIGNATURE??$?.signature,deliveryEndpoint:process.env.ES_LFV_DELIVERY_ENDPOINT??$?.deliveryEndpoint,verifyPublicKey:process.env.ES_LFV_VERIFY_PUBLIC_KEY??$?.verifyPublicKey,eventsEndpoint:process.env.ES_LFV_EVENTS_ENDPOINT??$?.eventsEndpoint,deliveryTimeout:kS(process.env.ES_LFV_DELIVERY_TIMEOUT)??$?.deliveryTimeout,retryInterval:kS(process.env.ES_LFV_RETRY_INTERVAL)??$?.retryInterval,warnInterval:kS(process.env.ES_LFV_WARN_INTERVAL)??$?.warnInterval})}else if(L==="localFile"){let $=S??{};return yS({path:process.env.ES_FILE_PATH??$?.path,watch:process.env.ES_FILE_WATCH==="true"||$?.watch,ttl:process.env.ES_FILE_TTL?parseInt(process.env.ES_FILE_TTL,10):void 0})}else if(L==="vault"){let $=S??{};return $.vault?BS($):BS({url:process.env.ES_VAULT_URL??$?.url,token:process.env.ES_VAULT_TOKEN??$?.token,path:process.env.ES_VAULT_PATH??$?.path,ttl:process.env.ES_VAULT_TTL?parseInt(process.env.ES_VAULT_TTL,10):void 0})}else if(L==="azure"){let $=S??{};return $.vault?NS($):NS({apiVersion:process.env.ES_AZURE_API_VERSION??$?.apiVersion,scope:process.env.ES_AZURE_SCOPE??$?.scope,secretNamePrefix:process.env.ES_AZURE_SECRET_NAME_PREFIX??$?.secretNamePrefix,authMethod:process.env.ES_AZURE_AUTH_METHOD??$?.authMethod,tenantId:process.env.ES_AZURE_TENANT_ID??$?.tenantId,clientId:process.env.ES_AZURE_CLIENT_ID??$?.clientId,clientSecret:process.env.ES_AZURE_CLIENT_SECRET??$?.clientSecret,federatedTokenFile:process.env.ES_AZURE_FEDERATED_TOKEN_FILE??$?.federatedTokenFile,managedIdentityClientId:process.env.ES_AZURE_MANAGED_IDENTITY_CLIENT_ID??$?.managedIdentityClientId,imdsApiVersion:process.env.ES_AZURE_IMDS_API_VERSION??$?.imdsApiVersion,vaultUrl:process.env.ES_AZURE_VAULT_URL??$?.vaultUrl,vaultName:process.env.ES_AZURE_VAULT_NAME??$?.vaultName,ttl:process.env.ES_AZURE_TTL?parseInt(process.env.ES_AZURE_TTL,10):void 0})}else if(L==="aws"){let $=S??{};return $.vault?MS($):MS({webhookUrl:process.env.ES_AWS_WEBHOOK_URL??$?.webhookUrl,ttl:process.env.ES_AWS_TTL?parseInt(process.env.ES_AWS_TTL,10):void 0})}else if(L==="gcp"){let $=S??{};return $.vault?HS($):HS({ttl:process.env.ES_GCP_TTL?parseInt(process.env.ES_GCP_TTL,10):void 0})}throw Error(`ES_CONFIG_TYPE="${L}" is not a valid ConfigSourceType when using envConfig().`)}import{defaultLogger as jL}from"@enterprisestandard/core";import{list as BL}from"@enterprisestandard/core";class JS{groups=new Map;externalIdIndex=new Map;displayNameIndex=new Map;async get(S){return this.groups.get(S)??null}async getByExternalId(S){let L=this.externalIdIndex.get(S);if(!L)return null;return this.groups.get(L)??null}async getByDisplayName(S){let L=this.displayNameIndex.get(S.toLowerCase());if(!L)return null;return this.groups.get(L)??null}async list(S){let L=Array.from(this.groups.values()),$=Math.max(0,S?.start??0),R=S?.limit;if(S?.sort?.length)L=[...L].sort((J,M)=>{for(let{field:Z,direction:z}of S.sort){let K=J[Z],P=M[Z],y=JL(K,P);if(y!==0)return z==="desc"?-y:y}return 0});let U=L.length,D=R!=null?$+R:void 0,X=L.slice($,D);return BL(U,X,$,R)}async upsert(S){let L=this.groups.get(S.id);if(L){if(L.externalId&&L.externalId!==S.externalId)this.externalIdIndex.delete(L.externalId);if(L.displayName.toLowerCase()!==S.displayName.toLowerCase())this.displayNameIndex.delete(L.displayName.toLowerCase())}if(this.groups.set(S.id,S),S.externalId)this.externalIdIndex.set(S.externalId,S.id);this.displayNameIndex.set(S.displayName.toLowerCase(),S.id)}async delete(S){let L=this.groups.get(S);if(L){if(L.externalId)this.externalIdIndex.delete(L.externalId);this.displayNameIndex.delete(L.displayName.toLowerCase())}this.groups.delete(S)}async addMember(S,L){let $=this.groups.get(S);if(!$)throw Error(`Group ${S} not found`);let R=$.members??[];if(!R.some((U)=>U.value===L.value))R.push(L),$.members=R,$.updatedAt=new Date}async removeMember(S,L){let $=this.groups.get(S);if(!$)throw Error(`Group ${S} not found`);if($.members)$.members=$.members.filter((R)=>R.value!==L),$.updatedAt=new Date}}function JL(S,L){let $=S===void 0||S===null,R=L===void 0||L===null;if($&&R)return 0;if($)return 1;if(R)return-1;if(S instanceof Date&&L instanceof Date)return S.getTime()-L.getTime();let U=String(S),D=String(L);return U.localeCompare(D)}class FS{magicLinks=new Map;async create(S,L,$){if(this.magicLinks.has(S))throw Error(`Magic link with token ${S} already exists`);let R={token:S,user:L,createdAt:new Date,expiresAt:$};this.magicLinks.set(S,R)}async get(S){let L=this.magicLinks.get(S);if(!L)return null;if(Date.now()>L.expiresAt.getTime())return this.magicLinks.delete(S),null;return L}async delete(S){this.magicLinks.delete(S)}}class qS{sessions=new Map;async create(S){if(this.sessions.has(S.sid))throw Error(`Session with sid ${S.sid} already exists`);this.sessions.set(S.sid,S)}async get(S){return this.sessions.get(S)??null}async update(S,L){let $=this.sessions.get(S);if(!$)throw Error(`Session with sid ${S} not found`);let R={...$,...L};this.sessions.set(S,R)}async delete(S){this.sessions.delete(S)}}import{list as FL}from"@enterprisestandard/core";class jS{users=new Map;emailIndex=new Map;userNameIndex=new Map;async get(S){return this.users.get(S)??null}async getByEmail(S){let L=this.emailIndex.get(S.toLowerCase());if(!L)return null;return this.users.get(L)??null}async getByUserName(S){let L=this.userNameIndex.get(S.toLowerCase());if(!L)return null;return this.users.get(L)??null}async upsert(S){let L=this.users.get(S.id);if(L){if(L.email&&L.email.toLowerCase()!==S.email?.toLowerCase())this.emailIndex.delete(L.email.toLowerCase());if(L.userName&&L.userName.toLowerCase()!==S.userName?.toLowerCase())this.userNameIndex.delete(L.userName.toLowerCase())}if(this.users.set(S.id,S),S.email)this.emailIndex.set(S.email.toLowerCase(),S.id);if(S.userName)this.userNameIndex.set(S.userName.toLowerCase(),S.id)}async delete(S){let L=this.users.get(S);if(L){if(L.email)this.emailIndex.delete(L.email.toLowerCase());if(L.userName)this.userNameIndex.delete(L.userName.toLowerCase())}this.users.delete(S)}async list(S){let L=Array.from(this.users.values()),$=Math.max(0,S?.start??0),R=S?.limit;if(S?.sort?.length)L=[...L].sort((J,M)=>{for(let{field:Z,direction:z}of S.sort){let K=J[Z],P=M[Z],y=qL(K,P);if(y!==0)return z==="desc"?-y:y}return 0});let U=L.length,D=R!=null?$+R:void 0,X=L.slice($,D);return FL(U,X,$,R)}}function qL(S,L){let $=S===void 0||S===null,R=L===void 0||L===null;if($&&R)return 0;if($)return 1;if(R)return-1;if(S instanceof Date&&L instanceof Date)return S.getTime()-L.getTime();return String(S).localeCompare(String(L))}class RS{tokens=new Map;async set(S){this.tokens.set(S.workload_id,S)}async get(S){let L=this.tokens.get(S);if(!L)return null;if(Date.now()>L.expires_at.getTime())return this.tokens.delete(S),null;return L}async delete(S){this.tokens.delete(S)}async isValid(S){return await this.get(S)!==null}async cleanup(){let S=Date.now();for(let[L,$]of this.tokens.entries())if(S>$.expires_at.getTime())this.tokens.delete(L)}}var bS="__esDynamicConfig";function PS(S){if(!S)return;try{return new URL(S).pathname}catch{return S.startsWith("/")?S:`/${S}`}}function PL(S){let L=S.workload;if(!L||typeof L!=="object")return;if(typeof L.tokenUrl==="string")return PS(L.tokenUrl);let $=L.incoming;if($&&typeof $.tokenUrl==="string")return PS($.tokenUrl);let R=L.default;if(R&&typeof R.tokenUrl==="string")return PS(R.tokenUrl);return}function TL(S,L,$){let R={...L},U=$.basePath,D=$.stores;if($.validators&&!R.validators)R.validators=$.validators;if($.logger&&!R.logger)R.logger=$.logger;if(S.sso&&!R.sso)R.sso={redirectUri:PS(S.sso.redirectUri)??`${U}/auth/callback`,loginUrl:`${U}/auth/login`,userUrl:`${U}/auth/user`,logoutUrl:`${U}/auth/logout`,logoutBackChannelUrl:`${U}/auth/logout/backchannel`,sessionStore:D.sessionStore,userStore:D.userStore,enableJitUserProvisioning:!0};if(S.iam&&!R.iam)R.iam={usersUrl:`${U}/iam/Users`,groupsUrl:`${U}/iam/Groups`,userStore:D.userStore,groupStore:D.groupStore};if(S.workload&&!R.workload)R.workload={tokenUrl:PL(S)??`${U}/workload/token`,validateUrl:`${U}/workload/validate`,jwksUrl:`${U}/workload/jwks`,refreshUrl:`${U}/workload/refresh`,tokenStore:D.workloadTokenStore};if(S.ciam&&!R.ciam)R.ciam={magicLinkUrl:`${U}/magic-link`,magicLinkLoginUrl:`${U}/magic-link/login`,logoutUrl:`${U}/auth/logout`,logoutBackChannelUrl:`${U}/auth/logout/backchannel`,landingUrl:"/",sessionStore:D.sessionStore,userStore:D.userStore,magicLinkStore:D.magicLinkStore,enableJitUserProvisioning:!0};if(S.tenant&&!R.tenant)R.tenant={};return R}function AL(S,L){return($,R,U)=>{let D=TL($,R,L),X=S?.($,D,U);return{config:X?.config??$,frameworkConfig:X?.frameworkConfig??D}}}function VL(S={}){return{validators:S.validators,logger:S.logger,stores:{sessionStore:S.stores?.sessionStore??new qS,userStore:S.stores?.userStore??new jS,groupStore:S.stores?.groupStore??new JS,magicLinkStore:S.stores?.magicLinkStore??new FS,workloadTokenStore:S.stores?.workloadTokenStore??new RS},basePath:S.basePath??"/api/es"}}function TS(S={}){let L=VL(S);return{validators:L.validators,logger:L.logger,[bS]:L}}function OL(S={}){return TS(S)}function rS(S,L){let $=S??{},R=$[bS];if(!R)return{config:S??{},options:L};let U={...$};delete U[bS];let D={...L??{},beforeChange:AL(L?.beforeChange,R)};return(U.logger??jL).info?.("Dynamic framework configuration enabled",{basePath:R.basePath,adaptiveStores:!0}),{config:U,options:D}}import{logout as aS,logoutBackChannel as eS}from"@enterprisestandard/core/server";function oS(S){if(!S)return;try{return new URL(S).pathname}catch{return S.startsWith("/")?S:`/${S}`}}function SL(S){return S==="/"?S:S.replace(/\/+$/,"")}function WL(S){let L=SL(S);return{matchesPath:(U)=>{if(!U)return!1;let D=oS(U);if(!D)return!1;return SL(D)===L},startsWithPath:(U)=>{if(!U)return!1;let D=oS(U);if(!D)return!1;return S===D||S.startsWith(`${D}/`)}}}function IL(S,L){let $=new URL(S.url).pathname,{matchesPath:R,startsWithPath:U}=WL($);if(L.sso){let D=L.sso;if(R(L.sso.userUrl))return{module:"sso",kind:"sso.user",handler:async(X)=>{let J=await D.handler(X);if(J.status===401&&L.ciam){let M=await L.ciam.getUser(X);if(M)return new Response(JSON.stringify(M),{headers:{"Content-Type":"application/json"}})}return J}};if(R(L.sso.logoutUrl))return{module:"sso",kind:"sso.logout",handler:async(X)=>aS(X,L)};if(R(L.sso.logoutBackChannelUrl))return{module:"sso",kind:"sso.logout_backchannel",handler:async(X)=>eS(X,L)};if(R(L.sso.loginUrl)||R(L.sso.tokenUrl)||R(L.sso.refreshUrl)||R(L.sso.jwksUrl)||R(L.sso.redirectUri))return{module:"sso",kind:"sso.handler",handler:async(X)=>D.handler(X)}}if(L.ciam){if(R(L.ciam.logoutUrl))return{module:"ciam",kind:"ciam.logout",handler:async(D)=>aS(D,L)};if(R(L.ciam.logoutBackChannelUrl))return{module:"ciam",kind:"ciam.logout_backchannel",handler:async(D)=>eS(D,L)}}if(L.iam){let D=L.iam;if(U(L.iam.usersUrl)||U(L.iam.groupsUrl))return{module:"iam",kind:"iam.handler",handler:async(X)=>D.handler(X)}}if(L.workload){let D=L.workload,M=D._handlerTokenUrl??(D.tokenUrl?.startsWith("/")?D.tokenUrl:void 0)??(D.tokenUrl&&!D.tokenUrl.startsWith("http")?D.tokenUrl:void 0),Z="validateUrl"in D?D.validateUrl:void 0,z="jwksUrl"in D?D.jwksUrl:void 0,K="refreshUrl"in D?D.refreshUrl:void 0;if(R(M)||R(Z)||R(z)||R(K))return{module:"workload",kind:"workload.handler",handler:async(P)=>D.handler(P)}}if(L.secrets){let D=L.secrets;if(D.isLfvDeliveryRequest?.(S)&&D.handleLfvDelivery){let X=D.handleLfvDelivery;return{module:"secrets",kind:"secrets.lfv_delivery",handler:async(J)=>X(J)}}if(D.isLfvEventsRequest?.(S)&&D.handleLfvEvents){let X=D.handleLfvEvents;return{module:"secrets",kind:"secrets.lfv_events",handler:async(J)=>X(J)}}}if(L.ciam){let D=L.ciam,X=L.ciam.magicLinkUrl||"/magic-link",J=L.ciam.magicLinkLoginUrl||"/magic-link/login";if(R(X)&&S.method==="POST"||R(J)&&S.method==="GET")return{module:"ciam",kind:"ciam.handler",handler:async(M)=>D.handler(M)}}return}async function LL(S,L,$){if($?.filter){let X=await $.filter(S,L);if(X instanceof Response)return X;if(X==="not_handled")return new Response("Not Found",{status:404})}let R=()=>IL(S,L),U=await $?.resolve?.(S,L,R)??R();if(!U)return new Response("Not Found",{status:404});let D=async()=>U.handler(S);if($?.wrap)return await $.wrap(S,U,D,L);return await D()}import{readFile as wL,stat as xL}from"node:fs/promises";function AS(S,L){if(!S||S.trim().length===0)throw Error(`Missing required Azure config: ${L}`);return S}function yL(S){return S.replace(/^\/+|\/+$/g,"").replaceAll("/","--")}function mS(S,L){return`${S.replace(/\/+$/g,"")}/${L.replace(/^\/+/g,"")}`}function kL(S){try{let $=new URL(S).pathname.split("/").filter(Boolean),R=$.indexOf("secrets");if(R===-1)return;return $[R+2]||void 0}catch{return}}function vL(S){return typeof S==="object"&&S!==null&&!Array.isArray(S)}function $L(S){let L=S.apiVersion??"7.4",$=S.scope??"https://vault.azure.net/.default",R=S.secretNameTransform??yL,U=S.authMethod,D="/var/run/secrets/azure/tokens/azure-identity-token",X=S.federatedTokenFile??"/var/run/secrets/azure/tokens/azure-identity-token",J=S.vaultUrl??(S.vaultName?`https://${S.vaultName}.vault.azure.net`:void 0)??void 0,M=AS(J,"vaultUrl or vaultName (ES_AZURE_KEY_VAULT_URL / ES_AZURE_KEY_VAULT_NAME)");async function Z(T){try{return await xL(T),!0}catch{return!1}}let z,K;async function P(T){let{tenantId:C,clientId:x}=S;if(!C)throw Error("Workload identity requires tenantId");if(!x)throw Error("Workload identity requires clientId");if(!await Z(X))throw Error(`Federated token file not found at ${X}`);let v=(await wL(X,"utf8")).trim();if(!v)throw Error("Federated token file was empty");let b=`https://login.microsoftonline.com/${encodeURIComponent(C)}/oauth2/v2.0/token`,u=new URLSearchParams({client_id:x,grant_type:"client_credentials",scope:$,client_assertion_type:"urn:ietf:params:oauth:client-assertion-type:jwt-bearer",client_assertion:v}),W=await fetch(b,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:u});if(W.status!==200){let Q=await W.text().catch(()=>"");throw Error(`Azure workload identity token exchange returned ${W.status} ${W.statusText}. tenantId=${C}. Response: ${Q}`)}let m=await W.json();if(!m?.access_token)throw Error("Azure token response missing access_token");return z={accessToken:m.access_token,expiresAtMs:T+(m.expires_in??0)*1000},m.access_token}async function y(T){let C=S.imdsApiVersion??"2018-02-01",x="https://vault.azure.net",v=new URL("http://169.254.169.254/metadata/identity/oauth2/token");if(v.searchParams.set("api-version",C),v.searchParams.set("resource","https://vault.azure.net"),S.managedIdentityClientId)v.searchParams.set("client_id",S.managedIdentityClientId);let b=await fetch(v.toString(),{headers:{Metadata:"true",Accept:"application/json"}});if(b.status!==200){let m=await b.text().catch(()=>"");throw Error(`Azure IMDS token endpoint returned ${b.status} ${b.statusText}. Response: ${m}`)}let u=await b.json();if(!u?.access_token)throw Error("IMDS token response missing access_token");let W=T+60000;if(u.expires_on){let m=Number.parseInt(u.expires_on,10);if(Number.isFinite(m)&&m>0)W=m*1000;else{let Q=Date.parse(u.expires_on);if(Number.isFinite(Q))W=Q}}else if(u.expires_in){let m=Number.parseInt(u.expires_in,10);if(Number.isFinite(m)&&m>0)W=T+m*1000}return z={accessToken:u.access_token,expiresAtMs:W},u.access_token}async function n(T){let C=AS(S.tenantId,"tenantId (or ES_AZURE_TENANT_ID/AZURE_TENANT_ID)"),x=AS(S.clientId,"clientId (or ES_AZURE_CLIENT_ID/AZURE_CLIENT_ID)"),v=AS(S.clientSecret,"clientSecret (or ES_AZURE_CLIENT_SECRET)"),b=`https://login.microsoftonline.com/${encodeURIComponent(C)}/oauth2/v2.0/token`,u=new URLSearchParams({client_id:x,client_secret:v,grant_type:"client_credentials",scope:$}),W=await fetch(b,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:u});if(W.status!==200){let Q=await W.text().catch(()=>"");throw Error(`Azure token endpoint returned ${W.status} ${W.statusText}. tenantId=${C}. Response: ${Q}`)}let m=await W.json();if(!m?.access_token)throw Error("Azure token response missing access_token");return z={accessToken:m.access_token,expiresAtMs:T+(m.expires_in??0)*1000},m.access_token}async function E(){let T=Date.now();if(z&&z.expiresAtMs-60000>T)return z.accessToken;if(K)return K;K=(async()=>{if(U==="workload_identity")return await P(T);if(U==="managed_identity")return await y(T);if(U==="client_secret")return await n(T);if(await Z(X))try{return await P(T)}catch{}try{return await y(T)}catch{}return await n(T)})();try{return await K}finally{K=void 0}}async function w(T){let C=await E(),x=mS(M,`/secrets/${encodeURIComponent(T)}?api-version=${encodeURIComponent(L)}`),v=await fetch(x,{headers:{Authorization:`Bearer ${C}`,Accept:"application/json"}});if(v.status!==200){let b=await v.text().catch(()=>"");throw Error(`Key Vault returned ${v.status} ${v.statusText} for ${x}. Response: ${b}`)}return await v.json()}async function q(T,C){let x=R(T),v=S.secretNamePrefix?`${S.secretNamePrefix}${x}`:x,b=await w(v),u=b.value;try{u=JSON.parse(b.value)}catch{}let W=b.attributes?.created?b.attributes.created*1000:void 0,m=kL(b.id);return{data:u,metadata:{path:T,version:Number.parseInt(m??"",10)||0,created:W?new Date(W):new Date}}}async function V(T,C,x){if(!vL(C))throw Error(`putSecret requires an object value for azure source at path ${T}`);let v=R(T),b=S.secretNamePrefix?`${S.secretNamePrefix}${v}`:v,u=await E(),W=mS(M,`/secrets/${encodeURIComponent(b)}?api-version=${encodeURIComponent(L)}`),m=JSON.stringify({value:JSON.stringify(C)}),Q=await fetch(W,{method:"PUT",headers:{Authorization:`Bearer ${u}`,"Content-Type":"application/json",Accept:"application/json"},body:m});if(Q.status!==200&&Q.status!==201){let G=await Q.text().catch(()=>"");throw Error(`Key Vault putSecret returned ${Q.status} for ${W}: ${G}`)}}async function k(T,C){let x=R(T),v=S.secretNamePrefix?`${S.secretNamePrefix}${x}`:x,b=await E(),u=mS(M,`/secrets/${encodeURIComponent(v)}?api-version=${encodeURIComponent(L)}`),W=await fetch(u,{method:"DELETE",headers:{Authorization:`Bearer ${b}`,Accept:"application/json"}});if(W.status!==200&&W.status!==202&&W.status!==204){let m=await W.text().catch(()=>"");throw Error(`Key Vault deleteSecret returned ${W.status} for ${u}: ${m}`)}}async function g(T,C){throw Error(`listPaths is not implemented for Azure Key Vault source at path ${T}`)}async function t(T,C){try{return await q(T),!0}catch(x){if((x instanceof Error?x.message:String(x)).includes(" 404 "))return!1;throw x}}async function s(T,C,x){throw Error(`requestRotate is not implemented for Azure Key Vault source at path ${T}`)}async function p(T,C,x){throw Error(`requestRevoke is not implemented for Azure Key Vault source at path ${T}`)}async function DS(T,C){let x=R(T),v=S.secretNamePrefix?`${S.secretNamePrefix}${x}`:x,b=await w(v);return{id:b.id,...b.attributes??{}}}return{type:S.type,getFullSecret:q,getSecret:async(T,C)=>{return(await q(T,C)).data},putSecret:V,deleteSecret:k,listPaths:g,exists:t,requestRotate:s,requestRevoke:p,getMetadata:DS,subscribe:(T,C)=>{throw Error("TODO: subscribe not implemented for azure vault")}}}function RL(S){async function L(Z,z){throw Error("Error retrieving secret",{cause:Error("Not implemented")})}async function $(Z,z,K){throw Error("putSecret not implemented for dev vault")}async function R(Z,z){throw Error(`deleteSecret not implemented for dev vault at path ${Z}`)}async function U(Z,z){throw Error(`listPaths not implemented for dev vault at path ${Z}`)}async function D(Z,z){throw Error(`exists not implemented for dev vault at path ${Z}`)}async function X(Z,z,K){throw Error(`requestRotate not implemented for dev vault at path ${Z}`)}async function J(Z,z,K){throw Error(`requestRevoke not implemented for dev vault at path ${Z}`)}async function M(Z,z){throw Error(`getMetadata not implemented for dev vault at path ${Z}`)}return{type:S.type,getFullSecret:L,getSecret:async(Z,z)=>{return(await L(Z,z)).data},putSecret:$,deleteSecret:R,listPaths:U,exists:D,requestRotate:X,requestRevoke:J,getMetadata:M,subscribe:(Z,z)=>{throw Error("TODO: subscribe not implemented for dev vault")}}}function UL(S,L){let $=(R,U)=>{throw Error(`${R} is not implemented for source "${L}" (type: ${S}) at path ${U}`)};return{type:S,getFullSecret:(R,U)=>Promise.reject($("getFullSecret",R)),getSecret:(R,U)=>Promise.reject($("getSecret",R)),putSecret:(R,U,D)=>Promise.reject($("putSecret",R)),subscribe:(R,U)=>{return $("subscribe",R),()=>{}},deleteSecret:(R,U)=>Promise.reject($("deleteSecret",R)),listPaths:(R,U)=>Promise.reject($("listPaths",R)),exists:(R,U)=>Promise.reject($("exists",R)),requestRotate:(R,U,D)=>Promise.reject($("requestRotate",R)),requestRevoke:(R,U,D)=>Promise.reject($("requestRevoke",R)),getMetadata:(R,U)=>Promise.reject($("getMetadata",R))}}function bL(S,L){if(L.type==="vault")return ZS(L);if(L.type==="lfv")return ES(L);if(L.type==="azure")return $L(L);if(L.type==="dev")return RL(L);if(L.type==="aws")return UL(L.type,S);if(L.type==="gcp")return UL(L.type,S);throw Error(`Unsupported secrets source type for "${S}"`)}function mL(S){return S.type==="lfv"&&typeof S.isDeliveryRequest==="function"&&typeof S.isEventsRequest==="function"&&typeof S.handleDelivery==="function"&&typeof S.handleEvents==="function"}function CL(S,L){let $={},R=new Set([...Object.keys(S??{}),...Object.keys(L??{})]);for(let U of R){let D=S?.[U],X=L?.[U];$[U]={...D??{},...X??{}}}return $}function CS(S,L,$,R){if(!$&&!R)return;let U=CL($,R),D={};for(let[z,K]of Object.entries(U))S?.validateSourceConfig?.(z,K),D[z]=bL(z,K);let X=(z)=>{let K=D[z];if(!K)throw L.warn?.(`Secrets source "${z}" is not configured`),Error(`Secrets source "${z}" is not configured`);return K},J=()=>{return Object.values(D).filter(mL)},M=(z)=>{return J().find((K)=>K.isDeliveryRequest(z))},Z=(z)=>{return J().find((K)=>K.isEventsRequest(z))};return{config:D,listSecretsSources:()=>Object.keys(D),getSecretsSource:X,getSecret:(z,K,P)=>X(z).getSecret(K,P),getFullSecret:(z,K,P)=>X(z).getFullSecret(K,P),putSecret:(z,K,P,y)=>X(z).putSecret(K,P,y),deleteSecret:(z,K,P)=>X(z).deleteSecret(K,P),listPaths:(z,K,P)=>X(z).listPaths(K,P),exists:(z,K,P)=>X(z).exists(K,P),requestRotate:(z,K,P,y)=>X(z).requestRotate(K,P,y),requestRevoke:(z,K,P,y)=>X(z).requestRevoke(K,P,y),getMetadata:(z,K,P)=>X(z).getMetadata(K,P),subscribe:(z,K,P)=>X(z).subscribe(K,P),isLfvDeliveryRequest:(z)=>M(z)!==void 0,isLfvEventsRequest:(z)=>Z(z)!==void 0,handleLfvDelivery:async(z)=>{let K=M(z);if(!K)return new Response("Not Found",{status:404});return K.handleDelivery(z)},handleLfvEvents:async(z)=>{let K=Z(z);if(!K)return new Response("Not Found",{status:404});return K.handleEvents(z)}}}import{must as r}from"@enterprisestandard/core";var DL=new Map;function l(S){if(S===void 0||S===null)return!1;let L=S;return L.workloadId!==void 0&&L.workloadId!==null||L.privateKey!==void 0&&L.privateKey!==null}function e(S){if(S===void 0||S===null)return!1;let L=S,$=L.clientId!==void 0&&L.clientId!==null,R=L.clientSecret!==void 0&&L.clientSecret!==null,U=L.workloadId!==void 0&&L.workloadId!==null,D=L.privateKey!==void 0&&L.privateKey!==null;return($||R)&&!U&&!D}function uS(S){if(S===void 0||S===null)return!1;let L=S,$=L.jwksUri!==void 0&&L.jwksUri!==null,R=L.workloadId!==void 0&&L.workloadId!==null,U=L.clientId!==void 0&&L.clientId!==null,D=L.clientSecret!==void 0&&L.clientSecret!==null,X=L.privateKey!==void 0&&L.privateKey!==null;return $&&!R&&!X&&!U&&!D}function _L(S){if(S===null||typeof S!=="object"||Array.isArray(S))return!1;let L=S;return"clientId"in L||"jwksUri"in L||"workloadId"in L}function uL(S){if(S===null||typeof S!=="object"||Array.isArray(S))return!1;let L=S;if(_L(L))return!1;let $=Object.entries(L);if($.length===0)return!1;return $.every(([,R])=>_L(R))}function hL(S){if(S===null||typeof S!=="object"||Array.isArray(S))return!1;let L=S;if("incoming"in L||"outgoing"in L){if(L.incoming!==void 0&&(typeof L.incoming!=="object"||L.incoming===null))return!1;if(L.outgoing!==void 0&&(typeof L.outgoing!=="object"||L.outgoing===null||Array.isArray(L.outgoing)))return!1;return!0}return!1}function US(S,L,$,R){if(!$&&!R)return;if($&&hL($)){let Q=$.incoming,G=Q?{...Q,...R,jwksUri:Q.jwksUri,issuer:Q.issuer}:R;if(!G||!G.tokenUrl&&!G.jwksUri)L.warn("Workload vault config has incoming/outgoing but no server config (incoming or framework) with tokenUrl/jwksUri; workload module handler will be unavailable.");let N=G&&(G.tokenUrl||G.jwksUri)?US(S,L,Q??void 0,R):void 0,j=Object.entries($.outgoing??{}),B={};for(let[H,_]of j){let Y=US(S,L,_,void 0);if(Y)B[H]=Y}if(!N&&Object.keys(B).length===0)return;return{...N?.config??{},getToken:async(H,_)=>{if(_?.client){let F=B[_.client];if(!F)throw Error(`Unknown workload client: ${_.client}`);return F.getToken(H)}if(N)return N.getToken(H);let Y=Object.keys(B);if(Y.length>1)throw Error(`Multiple named clients are configured, but no client was specified. Available clients: ${Y.join(", ")}`);if(Y.length===1)return B[Y[0]].getToken(H);throw Error("No workload config available; specify options.client")},refreshToken:async(H)=>{if(!N)throw Error("No default workload config");return N.refreshToken(H)},generateJWTAssertion:async(H)=>{if(!N)throw Error("No default workload config");return N.generateJWTAssertion(H)},revokeToken:async(H)=>{if(!N)throw Error("No default workload config");return N.revokeToken(H)},validateToken:async(H)=>{if(!N)throw Error("No default workload config");return N.validateToken(H)},getWorkloadIdentity:async(H)=>{if(!N)return;return N.getWorkloadIdentity(H)},parseJWT:async(H)=>{if(!N)throw Error("No default workload config");return N.parseJWT(H)},handler:async(H)=>{if(!N)return new Response("Not Found",{status:404});return N.handler(H)}}}if($&&uL($)){let Q=$.default,G=Q?{...Q,...R,jwksUri:Q.jwksUri,issuer:Q.issuer}:R;if(!G||!G.tokenUrl&&!G.jwksUri)L.warn('Workload vault config is a clients map but no server config (workload["default"] or framework workload) with tokenUrl/jwksUri; workload module handler will be unavailable.');let N=G&&(G.tokenUrl||G.jwksUri)?US(S,L,Q??void 0,R):void 0,j=Object.entries($).filter(([H])=>H!=="default"),B={};for(let[H,_]of j){let Y=US(S,L,_,void 0);if(Y)B[H]=Y}if(!N&&Object.keys(B).length===0)return;return{...N?.config??{},getToken:async(H,_)=>{if(_?.client){let F=B[_.client];if(!F)throw Error(`Unknown workload client: ${_.client}`);return F.getToken(H)}if(N)return N.getToken(H);let Y=Object.keys(B);if(Y.length>1)throw Error(`Multiple named clients are configured, but no client was specified. Available clients: ${Y.join(", ")}`);if(Y.length===1)return B[Y[0]].getToken(H);throw Error("No workload config available; specify options.client")},refreshToken:async(H)=>{if(!N)throw Error("No default workload config");return N.refreshToken(H)},generateJWTAssertion:async(H)=>{if(!N)throw Error("No default workload config");return N.generateJWTAssertion(H)},revokeToken:async(H)=>{if(!N)throw Error("No default workload config");return N.revokeToken(H)},validateToken:async(H)=>{if(!N)throw Error("No default workload config");return N.validateToken(H)},getWorkloadIdentity:async(H)=>{if(!N)return;return N.getWorkloadIdentity(H)},parseJWT:async(H)=>{if(!N)throw Error("No default workload config");return N.parseJWT(H)},handler:async(H)=>{if(!N)return new Response("Not Found",{status:404});return N.handler(H)}}}let U=$,D=R?.tokenUrl,X=D?.startsWith("/")?D:void 0,J=U?.idpTokenUrl??R?.idpTokenUrl??(U?.tokenUrl&&(U.tokenUrl.startsWith("http://")||U.tokenUrl.startsWith("https://"))?U.tokenUrl:void 0),M={...U,...R,tokenUrl:X??R?.tokenUrl??U?.tokenUrl,idpTokenUrl:J,jwksUri:U?.jwksUri,issuer:U?.issuer};M._handlerTokenUrl=X;let Z,z=M,K=l(M),P=e(M),y=uS(M);if(!K&&!P&&!y){if(!U||Object.keys(U).length===0)return;throw L.error("WorkloadConfig validation failed. Config:",{keys:Object.keys(M),clientId:z.clientId,clientSecret:z.clientSecret?"[REDACTED]":void 0,workloadId:z.workloadId,privateKey:z.privateKey?"[REDACTED]":void 0,jwksUri:z.jwksUri,tokenUrl:z.tokenUrl,idpTokenUrl:z.idpTokenUrl,fromVaultKeys:U?Object.keys(U):[],fromCodeKeys:R?Object.keys(R):[]}),Error("Invalid WorkloadConfig: must provide the correct config for one of the following modes: JWT Bearer Grant, OAuth2 Client Credentials, or Server-Only")}if(K)Z={...M,tokenUrl:M.tokenUrl,idpTokenUrl:r(M.idpTokenUrl,"Missing 'idpTokenUrl' from Workload Config"),workloadId:r(M.workloadId,"Missing 'workloadId' from Workload Config"),privateKey:r(M.privateKey,"Missing 'privateKey' from Workload Config"),audience:r(M.audience,"Missing 'audience' from Workload Config"),scope:M.scope??"",algorithm:M.algorithm??"RS256",tokenLifetime:M.tokenLifetime??300,refreshThreshold:M.refreshThreshold??60,autoRefresh:M.autoRefresh!==void 0?M.autoRefresh:!0,tokenStore:M.tokenStore??new RS};else if(e(M))Z={...M,tokenUrl:M.tokenUrl,idpTokenUrl:r(M.idpTokenUrl,"Missing 'idpTokenUrl' from Workload Config"),clientId:r(M.clientId,"Missing 'clientId' from Workload Config"),clientSecret:r(M.clientSecret,"Missing 'clientSecret' from Workload Config"),scope:M.scope??"",tokenLifetime:M.tokenLifetime??300,refreshThreshold:M.refreshThreshold??60,autoRefresh:M.autoRefresh!==void 0?M.autoRefresh:!0,tokenStore:M.tokenStore??new RS};else if(uS(M))Z=M;function n(){let Q=new Uint8Array(16);return crypto.getRandomValues(Q),Array.from(Q,(G)=>G.toString(16).padStart(2,"0")).join("")}function E(Q){let G;if(typeof Q==="string")G=btoa(Q);else G=btoa(String.fromCharCode(...Q));return G.replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function w(Q){let G=Q.replace(/-/g,"+").replace(/_/g,"/");while(G.length%4)G+="=";return atob(G)}function q(Q){if(Q.startsWith("RS"))return{name:"RSASSA-PKCS1-v1_5",hash:Q==="RS256"?"SHA-256":Q==="RS384"?"SHA-384":"SHA-512"};else if(Q.startsWith("ES"))return{name:"ECDSA",namedCurve:Q==="ES256"?"P-256":Q==="ES384"?"P-384":"P-521",hash:Q==="ES256"?"SHA-256":Q==="ES384"?"SHA-384":"SHA-512"};throw Error(`Unsupported algorithm: ${Q}`)}async function V(Q,G){let N=Q.replace(/-----BEGIN PRIVATE KEY-----/,"").replace(/-----END PRIVATE KEY-----/,"").replace(/\s/g,""),j=Uint8Array.from(atob(N),(I)=>I.charCodeAt(0)),B=q(G);return crypto.subtle.importKey("pkcs8",j,B,!1,["sign"])}async function k(Q,G,N){let j=await V(G,N),I=new TextEncoder().encode(Q),H=q(N),_=await crypto.subtle.sign(H,j,I);return E(new Uint8Array(_))}async function g(Q,G=3,N=1000,j=30000){let B=Error("Placeholder Error");for(let I=0;I<=G;I++)try{return await Q()}catch(H){if(B=H instanceof Error?H:Error(String(H)),B.message.includes("400")||B.message.includes("401")||B.message.includes("403")||B.message.includes("404"))throw B;if(I<G){let _=Math.min(N*2**I,j),Y=Math.random()*_*0.1;await new Promise((F)=>setTimeout(F,_+Y))}}throw B}async function t(Q){if(!l(Z))throw Error("generateJWTAssertion is only available in JWT Bearer Grant mode");let G=Z,N=Math.floor(Date.now()/1000),j={iss:G.workloadId,sub:G.workloadId,aud:G.audience??"",exp:N+G.tokenLifetime,iat:N,jti:n(),scope:Q??G.scope},B={alg:G.algorithm,typ:"JWT",kid:G.keyId},I=E(JSON.stringify(B)),H=E(JSON.stringify(j)),_=`${I}.${H}`,Y=await k(_,G.privateKey,G.algorithm);return`${_}.${Y}`}async function s(Q){if(!l(Z))throw Error("generateJWTAssertion is only available in JWT Bearer Grant mode");let G=Z;return g(async()=>{let N=G.idpTokenUrl,j=await t(Q),B=new URLSearchParams;if(B.append("grant_type","urn:ietf:params:oauth:grant-type:jwt-bearer"),B.append("assertion",j),Q)B.append("scope",Q);let I=await fetch(N,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:B.toString()}),H=await I.json();if(!I.ok)throw L.error("Token acquisition error:",H),Error(`Token acquisition failed: ${H.error||I.statusText} - ${H.error_description||""}`.trim());let _=await S.tokenResponse["~standard"].validate(H);if(_.issues)throw L.error("Token response validation failed:",_.issues),Error(`Token response validation failed: ${_.issues.map((Y)=>Y.message).join("; ")}`);if(G.tokenStore){let Y=new Date(Date.now()+(_.value.expires_in??300)*1000),F={workload_id:G.workloadId,access_token:_.value.access_token,token_type:_.value.token_type,scope:_.value.scope,expires_at:Y,created_at:new Date,refresh_token:_.value.refresh_token};await G.tokenStore.set(F)}return _.value})}async function p(Q){if(!e(Z))throw Error("acquireTokenClientCredentials is only available in OAuth2 Client Credentials mode");let G=Z;return g(async()=>{let N=G.idpTokenUrl,j=new URLSearchParams;if(j.append("grant_type","client_credentials"),j.append("client_id",G.clientId),j.append("client_secret",G.clientSecret),Q)j.append("scope",Q);let B=await fetch(N,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:j.toString()}),I=await B.json();if(!B.ok)throw L.error("Token acquisition error:",I),Error(`Token acquisition failed: ${I.error||B.statusText} - ${I.error_description||""}`.trim());let H=await S.tokenResponse["~standard"].validate(I);if(H.issues)throw L.error("Token response validation failed:",H.issues),Error(`Token response validation failed: ${H.issues.map((_)=>_.message).join("; ")}`);if(G.tokenStore){let _=new Date(Date.now()+(H.value.expires_in??300)*1000),Y={workload_id:G.clientId,access_token:H.value.access_token,token_type:H.value.token_type,scope:H.value.scope,expires_at:_,created_at:new Date,refresh_token:H.value.refresh_token};await G.tokenStore.set(Y)}return H.value})}async function DS(Q){if(!l(Z)&&!e(Z)){let B=Z;throw Error(`Acquiring tokens is only available in JWT Bearer Grant or OAuth2 Client Credentials mode. Current config: hasClientId=${!!B.clientId}, hasClientSecret=${!!B.clientSecret}, hasWorkloadId=${!!B.workloadId}, hasPrivateKey=${!!B.privateKey}, hasJwksUri=${!!B.jwksUri}`)}let G=Z;Q=Q??G.scope;let N=l(Z)?Z.workloadId:Z.clientId;if(G.tokenStore){let B=await G.tokenStore.get(N);if(B){let I=Date.now(),H=B.expires_at.getTime(),_=G.refreshThreshold*1000;if(I+_<H)return B.access_token;if(G.autoRefresh)try{return(l(Z)?await s(Q):await p(Q)).access_token}catch(Y){if(I<H)return L.warn("Token refresh failed, using cached token:",Y),B.access_token;throw Y}}}return(l(Z)?await s(Q):await p(Q)).access_token}async function T(Q){if(!l(Z)&&!e(Z))throw Error("Refreshing tokens is only available in JWT Bearer Grant or OAuth2 Client Credentials mode");let G=Z;return Q=Q??G.scope,l(G)?await s(Q):await p(Q)}async function C(Q){if(!l(Z)&&!e(Z))throw Error("Revoking tokens is only available in JWT Bearer Grant or OAuth2 Client Credentials mode");let G=Z;try{if(!Z.revocationEndpoint)return;let N=new URLSearchParams;if(N.append("token",Q),N.append("token_type_hint","access_token"),l(Z)){let B=Z;N.append("client_id",B.workloadId)}else if(e(Z)){let B=Z;N.append("client_id",B.clientId),N.append("client_secret",B.clientSecret)}let j=await fetch(Z.revocationEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:N.toString()});if(!j.ok)L.warn("Token revocation failed:",j.status,j.statusText);else L.info("Token revoked successfully");if(Z.tokenStore){let B;if(l(Z))B=Z.workloadId;else if(e(Z))B=Z.clientId;else return;await Z.tokenStore.delete(B)}}catch(N){L.warn("Error revoking token:",N)}}async function x(){if(!Z?.jwksUri)throw Error("No JWKS URI configured in Workload Config");let Q=Z.jwksUri,G=DL.get(Q);if(G)return G;return g(async()=>{let N=await fetch(Q);if(!N.ok)throw Error("Failed to fetch JWKS");let j=await N.json();return DL.set(Q,j),j})}async function v(Q){let N=(await x()).keys.find((I)=>I.kid===Q);if(!N)throw Error("Public key not found");let j=l(Z)?Z.algorithm:"RS256",B=q(N.alg||j);return crypto.subtle.importKey("jwk",N,B,!1,["verify"])}async function b(Q){try{let G=Q.split(".");if(G.length!==3)throw Error("Invalid JWT");let N=JSON.parse(w(G[0])),j=JSON.parse(w(G[1])),B=await v(N.kid),I=G[2],_=new TextEncoder().encode(`${G[0]}.${G[1]}`),Y=Uint8Array.from(w(I),(d)=>d.charCodeAt(0)),F=q(N.alg);if(!await crypto.subtle.verify(F,B,Y,_))throw Error("Invalid JWT signature");let O=await S.jwtAssertionClaims["~standard"].validate(j);if(O.issues)throw L.error("JWT claims validation failed:",O.issues),Error(`JWT claims validation failed: ${O.issues.map((d)=>d.message).join("; ")}`);return O.value}catch(G){throw L.error("Error verifying JWT:",G),G}}async function u(Q){if(!l(Z)&&!e(Z)&&!uS(Z))throw Error("Validating tokens is only available in JWT Bearer Grant, OAuth2 Client Credentials, or Server-Only mode");try{let G=await b(Q),N=Math.floor(Date.now()/1000);if(G.exp&&G.exp<N)return{valid:!1,error:"Token expired"};if(l(Z)){if(Z.audience&&G.aud!==Z.audience)return{valid:!1,error:"Invalid audience"}}else if(e(Z)){if(Z.issuer&&G.iss!==Z.issuer)return{valid:!1,error:"Invalid issuer"};if(Z.audience&&G.aud!==Z.audience)return{valid:!1,error:"Invalid audience"}}else{let j=Z;if(j.issuer&&G.iss!==j.issuer)return{valid:!1,error:"Invalid issuer"}}return{valid:!0,claims:G,expiresAt:G.exp?new Date(G.exp*1000):void 0}}catch(G){return{valid:!1,error:G instanceof Error?G.message:String(G)}}}async function W(Q){let G=Q.headers.get("Authorization");if(!G||!G.startsWith("Bearer "))return;let N=G.substring(7),j=await u(N);if(!j.valid||!j.claims)return;return{workloadId:j.claims.sub,clientId:typeof j.claims.client_id==="string"?j.claims.client_id:void 0,scope:j.claims.scope,claims:j.claims}}async function m(Q){if(!Z)throw Error("Enterprise Standard Workload Manager not initialized");let G=new URL(Q.url).pathname,N=(Y)=>{if(!Y)return;try{return new URL(Y).pathname}catch{return Y.startsWith("/")?Y:`/${Y}`}},j=Z._handlerTokenUrl;if(N(j||Z.tokenUrl)===G&&Q.method==="GET")try{let F=new URL(Q.url).searchParams.get("scope")||void 0,A=await DS(F);return new Response(JSON.stringify({access_token:A,token_type:"Bearer"}),{headers:[["Content-Type","application/json"]]})}catch(Y){return L.error("Error in token endpoint:",Y),new Response(JSON.stringify({error:Y instanceof Error?Y.message:"Internal server error"}),{status:500,headers:[["Content-Type","application/json"]]})}if(N(Z.validateUrl)===G&&Q.method==="POST"){let Y=Q.headers.get("Authorization");if(!Y||!Y.startsWith("Bearer "))return new Response(JSON.stringify({valid:!1,error:"Missing Authorization header"}),{status:401,headers:[["Content-Type","application/json"]]});let F=Y.substring(7),A=await u(F);return new Response(JSON.stringify(A),{status:A.valid?200:401,headers:[["Content-Type","application/json"]]})}if(N(Z.jwksUrl)===G&&Q.method==="GET"){let Y=await x();return new Response(JSON.stringify(Y),{headers:[["Content-Type","application/json"]]})}if(N(Z.refreshUrl)===G&&Q.method==="POST")try{let Y=await T();return new Response(JSON.stringify(Y),{headers:[["Content-Type","application/json"]]})}catch(Y){return L.error("Error in refresh endpoint:",Y),new Response(JSON.stringify({error:Y instanceof Error?Y.message:"Internal server error"}),{status:500,headers:[["Content-Type","application/json"]]})}return new Response("Not Found",{status:404})}return{...Z,getToken:DS,refreshToken:T,generateJWTAssertion:t,revokeToken:C,validateToken:u,getWorkloadIdentity:W,parseJWT:b,handler:m}}function hS(S){return S=S??"Workload authentication unavailable",new Response(JSON.stringify({error:S}),{status:503,statusText:S,headers:{"Content-Type":"application/json"}})}var VS="EnterpriseStandard instance is required. Create one with enterpriseStandard(source, config) and pass it to this function.",dL="EnterpriseStandard or Workload instance is required. Create an ES with enterpriseStandard(source, config) or pass a Workload instance.";async function cL(S,L){r(L,VS);let $=L.workload;if(!$)return;return $.getWorkloadIdentity(S)}async function nL(S,L,$){r(L,VS);let R=L.workload;if(!R)throw hS();return R.getToken($,{client:S})}async function fL(S,L){r(L,dL);let $="validateToken"in L&&typeof L.validateToken==="function"?L:L.workload;if(!$)return{valid:!1,error:"Workload authentication unavailable"};let R=S.headers.get("Authorization");if(!R||!R.startsWith("Bearer "))return{valid:!1,error:"Missing or invalid Authorization header"};let U=R.substring(7);return $.validateToken(U)}async function gL(S,L){r(L,VS);let $=L.workload;if(!$)throw hS();return $.revokeToken(S)}async function sL(S,L){r(L,VS);let $=L.workload;if(!$)throw hS();return $.handler(S)}export*from"@enterprisestandard/core";import{InMemoryTenantStore as TR,parseTenantRequest as AR,sendTenantWebhook as VR,TenantRequestError as OR,tenant as WR}from"@enterprisestandard/core";import{callback as wR,ciam as xR,getCIAMUser as yR,getRequiredSSOorCIAMUser as kR,getSSOorCIAMUser as vR,getSSOorCIAMUser as bR,getSSOUser as mR,iam as CR,initiateLogin as uR,logout as hR,logoutBackChannel as dR,sso as cR,verifyUser as nR}from"@enterprisestandard/core/server";import{setActiveSession as lL}from"@enterprisestandard/core";async function pL(S,L){let $=[];for(let[R,U]of L.entries()){if(!U.sso)continue;try{let D=await U.sso.getUser(S);if(!D)continue;$.push({clientId:R,user:D,valid:!0,expiresAt:D.sso?.expires})}catch{}}return $}async function iL(S,L,$,R={}){let U=$.get(L);if(!U?.sso)return new Response(JSON.stringify({error:"Unknown tenant session"}),{status:404,headers:{"Content-Type":"application/json"}});if(await U.sso.getUser(S)){let M=lL(L,{cookieName:R.activeSessionCookieName,path:R.cookiePath,secure:R.cookieSecure,sameSite:R.cookieSameSite,maxAge:R.cookieMaxAge});return new Response(JSON.stringify({success:!0}),{status:200,headers:{"Content-Type":"application/json","Set-Cookie":M}})}let X=R.loginUrl??U.sso.loginUrl;if(!X)return new Response(JSON.stringify({error:"Session expired"}),{status:401,headers:{"Content-Type":"application/json"}});let J=new URL(X,S.url);if(!J.searchParams.has("clientId"))J.searchParams.set("clientId",L);return new Response(null,{status:302,headers:{Location:J.toString()}})}async function tL(S,L,$){await S.putSecret(L,$)}function rL(S){let{type:L,...$}=S;return ZS({type:"vault",...$})}function a(S){if(!S)return;try{return new URL(S,"http://dummy").pathname}catch{return S.startsWith("/")?S:`/${S}`}}function $$(S,L){if(S?.sso?.redirectUri&&L.sso?.redirectUri){let $=a(S.sso.redirectUri),R=a(L.sso.redirectUri);if($!==R)throw Error(`redirectUri path in framework config must match ConfigSource redirectUri path. ConfigSource path: ${$}, framework path: ${R}`)}}function cS(S){let L={};if(!S)return L;for(let[$,R]of Object.entries(S))if(R.type==="lfv")L[$]=R;return L}function R$(S){return S[wS]}function U$(S,L){let $=cS(S.secrets),R=a(L.deliveryEndpoint),U=a(L.eventsEndpoint),D=a(L.path);for(let X of Object.values($)){if(a(X.deliveryEndpoint)!==R)continue;if(a(X.eventsEndpoint)!==U)continue;let J=X.path?a(X.path):void 0;if(D&&J&&D!==J)continue;return!0}return!1}function D$(S,L){let $=R$(L);if(!$)return S;if(U$(S,$))return S;let R={type:"lfv",path:$.path,lfvServerUrl:$.lfvServerUrl,clientId:$.clientId,signature:$.signature,deliveryTimeout:$.deliveryTimeout,retryInterval:$.retryInterval,warnInterval:$.warnInterval,deliveryEndpoint:$.deliveryEndpoint,eventsEndpoint:$.eventsEndpoint,verifyPublicKey:$.verifyPublicKey},U=S.secrets??{},D="LFV_BOOTSTRAP",X=1;while(D in U)X+=1,D=`LFV_BOOTSTRAP_${X}`;return{...S,secrets:{...U,[D]:R}}}function _$(S,L){let $=cS(S.secrets),R=cS(L.secrets);for(let[U,D]of Object.entries(R)){let X=$[U];if(!X)continue;let J=a(X.deliveryEndpoint),M=a(D.deliveryEndpoint);if(J&&M&&J!==M)throw Error(`LFV deliveryEndpoint path for secrets source "${U}" in framework config must match ConfigSource path. ConfigSource path: ${J}, framework path: ${M}`);let Z=a(X.eventsEndpoint),z=a(D.eventsEndpoint);if(Z&&z&&Z!==z)throw Error(`LFV eventsEndpoint path for secrets source "${U}" in framework config must match ConfigSource path. ConfigSource path: ${Z}, framework path: ${z}`)}}function YL(S,L){if(L===void 0)return!1;return JSON.stringify(S)===JSON.stringify(L)}function ZL(S,L,$,R,U){let D={logger:R,tenantId:S.tenantId,config:S,handler:async()=>new Response("Not Found",{status:404})};return D.workload=US($.workload,R,S?.workload,L.workload),D.secrets=CS($.secrets,R,S?.secrets,L?.secrets),D.sso=L$($.sso,R,S?.sso,L.sso),D.iam=S$($.iam,R,D.workload,S?.iam,L.iam),D.tenants=eL($.tenant,R,S?.tenant,L.tenant),D.ciam=oL($.ciam,R,S?.ciam,L.ciam,D.workload),D.handler=async(X)=>LL(X,D,U?.routing),D}function Y$(S,L,$,R,U,D){$$(L,$),_$(L,$);let X=ZL(L,$,R,U,D);S.tenantId=L.tenantId,S.config=L,S.logger=U,S.workload=X.workload,S.secrets=X.secrets,S.sso=X.sso,S.iam=X.iam,S.tenants=X.tenants,S.ciam=X.ciam,S.handler=X.handler}function X$(S,L,$,R){let U=S,D=L;if(R?.beforeChange){let X=R.beforeChange(S,L,$);if(X?.config!==void 0)U=X.config;if(X?.frameworkConfig!==void 0)D=X.frameworkConfig}return{effectiveRemoteConfig:U,effectiveFrameworkConfig:D}}function XL(S){return!!S&&typeof S==="object"&&typeof S.load==="function"}function OS(S){if(!S||typeof S!=="object")return!1;let L=S;return"beforeChange"in L||"afterChange"in L||"routing"in L}async function FR(S,L,$){let R,U,D,X=!1;if(XL(S))R=S,U=OS(L)?void 0:L,D=OS(L)?L:$;else X=!0,R=vS(),U=S,D=OS(L)?L:$;if(XL(S)&&OS(L)&&$)D=$;if(X&&!process.env.ES_CONFIG_TYPE)(U?.logger??dS).warn?.("enterpriseStandard() defaulted to envConfig() with no ES_CONFIG_TYPE set. Falling back to dev config source.");if(X&&!U)U=TS();let J=rS(U,D);U=J.config,D=J.options;let M=D$(U??{},R),Z=M.validators||aL(),z=M.logger||dS,K,P=M,y=ZL({},M,Z,z,D);function n(E){if(K!==void 0&&YL(E,K))return;let w=K,{effectiveRemoteConfig:q,effectiveFrameworkConfig:V}=X$(E,P,K,D);if(K!==void 0&&YL(q,K)&&V===P)return;let k=V.logger||dS;Y$(y,q,V,Z,k,D),K=q,P=V,M=V,Z=V.validators??Z,D?.afterChange?.(y,q,P,w)}if(y.reload=async()=>{let E=await R.load();n(E)},y.reconfigure=async(E)=>{if(E!=null)M={...M,...E},P=M,Z=M.validators??Z;let w=await R.load();n(w)},R.subscribe)R.subscribe((E)=>n(E));return R.load().then((E)=>n(E),(E)=>z.warn?.("ConfigSource initial load failed",E)),y}export{tL as writeEsaConfigToVault,sL as workloadHandler,US as workload,nR as verifyUser,BS as vaultConfig,fL as validateWorkloadToken,WR as tenantManagement,iL as switchSession,cR as sso,VR as sendTenantWebhook,CS as secrets,gL as revokeWorkloadToken,AR as parseTenantRequest,rL as openbaoVault,dR as logoutBackChannel,hR as logout,yS as localFileConfig,xS as lfvConfig,uR as initiateLogin,CR as iam,nL as getWorkloadToken,cL as getWorkload,bR as getUser,vR as getSSOorCIAMUser,mR as getSSOUser,kR as getRequiredSSOorCIAMUser,yR as getCIAMUser,HS as gcpConfig,vS as envConfig,FR as enterpriseStandard,TS as dynamicConfig,pL as discoverSessions,IS as devConfig,xR as ciam,wR as callback,NS as azureConfig,MS as awsConfig,OL as adaptiveFramework,OR as TenantRequestError,RS as InMemoryWorkloadTokenStore,jS as InMemoryUserStore,TR as InMemoryTenantStore,qS as InMemorySessionStore,FS as InMemoryMagicLinkStore,JS as InMemoryGroupStore};
1
+ import{createValidators as RL,defaultLogger as dS,tenant as UL}from"@enterprisestandard/core";import{ciam as DL,iam as _L,sso as YL}from"@enterprisestandard/core/server";function MS(S){throw Error("Not implemented")}function NS(S){throw Error("Not implemented")}function IS(S){return console.warn("ES_CONFIG_TYPE is not set. For LLM documentation, see https://enterprisestandard.com/llms.txt"),console.warn(`If this is a local development environment, visit https://ionite.com/dev?appId=${S.appId??""} to get started, or run: npx @enterprisestandard/cli`),{load:async()=>{return{}},subscribe($){let L=()=>{};return()=>{}}}}function HS(S){throw Error("Not implemented")}var YS=new Map;function M$(S){if(!S)return"/";return S.startsWith("/")?S:`/${S}`}function N$(S){try{let $=new URL(S),L=$.pathname.replace(/\/+$/g,"");return`${$.origin}${L}`}catch{return S.replace(/\/+$/g,"")}}function fS(S){let $=N$(S.lfvServerUrl),L=M$(S.path);return`${$}|${L}`}function nS(S,$,L){let R=YS.get(S)??new Map;return R.set($,L),YS.set(S,R),()=>{let U=YS.get(S);if(!U)return;if(U.delete($),U.size===0)YS.delete(S)}}async function gS(S,$,L){let R=YS.get(S);if(!R)return 0;let U=0;for(let[D,Y]of R){if(L&&D===L)continue;if(!Y.onDelivery)continue;U+=1,await Y.onDelivery($)}return U}async function sS(S,$,L){let R=YS.get(S);if(!R)return 0;let U=0;for(let[D,Y]of R){if(L&&D===L)continue;if(!Y.onEvents)continue;U+=1,await Y.onEvents($)}return U}function lS(S){try{return new URL(S).pathname}catch{return S.startsWith("/")?S:`/${S}`}}var H$=1e4,K$=1e4;async function iS(S){await new Promise(($)=>setTimeout($,S))}function SS(S){return{startedAt:Date.now(),timeout:typeof S?.timeout==="number"&&S.timeout>0?S.timeout:void 0}}function KS(S){if(S.timeout===void 0)return;let $=Date.now()-S.startedAt;return Math.max(0,S.timeout-$)}function ZS(S,$,L){return Error(`LFV ${S} timed out after ${L.timeout??0}ms for ${$}`)}async function GS(S,$,L,R,U){let D=KS(L);if(D!==void 0){if(D<=0)throw ZS(R,U,L);let Y=new AbortController,B=setTimeout(()=>Y.abort(),D);try{return await fetch(S,{...$,signal:Y.signal})}catch(M){if(M instanceof Error&&M.name==="AbortError")throw ZS(R,U,L);throw M}finally{clearTimeout(B)}}return await fetch(S,$)}async function pS(S,$,L,R,U,D){let Y=0,B=Date.now();for(;;){let M=KS($);if(M!==void 0&&M<=0)throw ZS(R,L,$);try{return await S()}catch(X){if(Y+=1,D>0&&Date.now()-B>=D){let H=X instanceof Error?X.message:String(X);console.warn(`Error connecting to the LFV source. Retries: '${Y}' Error: ${H}`),B=Date.now()}let Q=M===void 0?U:Math.min(U,M);if(Q<=0)throw ZS(R,L,$);await iS(Q)}}}function B$(S){return typeof S==="object"&&S!==null&&!Array.isArray(S)}function BS(S){let{lfvServerUrl:$,clientId:L,path:R}=S,U=S.signature??"sdk-placeholder-signature",D=typeof S.deliveryTimeout==="number"&&S.deliveryTimeout>0?S.deliveryTimeout:void 0,Y=typeof S.retryInterval==="number"&&S.retryInterval>0?S.retryInterval:H$,B=typeof S.warnInterval==="number"&&S.warnInterval>=0?S.warnInterval:K$,M=lS(S.deliveryEndpoint),X=lS(S.eventsEndpoint),Q=fS({lfvServerUrl:$??"",path:R??""}),H=crypto.randomUUID(),A=new Map,y=new Map,f=new Map,E;function w(){let _=A.size>0,Z=f.size>0,j=_||Z;if(j&&!E){E=nS(Q,H,{onDelivery:async(T)=>{F(T)},onEvents:async(T)=>{I(T)}});return}if(!j&&E)E(),E=void 0}function q(_){if(!$)throw Error(`LFV source requires "lfvServerUrl" for path ${_}`);if(!L)throw Error(`LFV source requires "clientId" for path ${_}`);return{lfvUrl:$,clientId:L}}async function V(_){return _.text().catch(()=>"")}async function k(_,Z,j,T){let O=q(_),d=j??crypto.randomUUID(),h=T??SS(),n={request_id:d,path:_,action:Z},c=await pS(async()=>{return await GS(`${O.lfvUrl.replace(/\/+$/g,"")}/clients/${O.clientId}/otp`,{method:"POST",headers:{"Content-Type":"application/json","X-LFV-Request-Id":d,"X-LFV-Signature":U},body:JSON.stringify(n)},h,"issueOtp",_)},h,_,"issueOtp",Y,B);if(c.status!==200){let o=await V(c);throw Error(`LFV OTP request failed (${c.status}) for ${_}: ${o}`)}let _S=await c.json();if(!_S.otp)throw Error(`LFV OTP response missing otp for ${_}`);return _S.otp}async function g(_,Z,j,T,O,d){let h=q(Z),n=O??crypto.randomUUID(),c=d??SS(),_S=await k(Z,j,n,c),o=await pS(async()=>{return await GS(`${h.lfvUrl.replace(/\/+$/g,"")}${_}`,{method:"POST",headers:{"Content-Type":"application/json","X-LFV-Request-Id":n,"X-LFV-Signature":U},body:JSON.stringify({request_id:n,otp:_S,path:Z,...T??{}})},c,j,Z)},c,Z,j,Y,B);if(o.status!==200&&o.status!==202){let QS=await V(o);throw Error(`LFV ${j} failed (${o.status}) for ${Z}: ${QS}`)}return{requestId:n}}async function t(_,Z,j){let T=y.get(_);if(T)return T;let O=j?.timeout??D,d={startedAt:Date.now(),timeout:typeof O==="number"&&O>0?O:void 0},h,n=new Promise((i)=>{h={resolve:i};let $S=f.get(_)??new Set;$S.add(h),f.set(_,$S),w()}),c=()=>{if(!h)return;let i=f.get(_);if(i?.delete(h),i&&i.size===0)f.delete(_);w()},_S=Z??crypto.randomUUID(),o=0,QS=Date.now();for(;;)try{await g("/secrets/request",_,"read_secret",void 0,_S,d);break}catch(i){let $S=KS(d);if($S!==void 0&&$S<=0)throw c(),ZS("read_secret",_,d);if(o+=1,B>0&&Date.now()-QS>=B){let z$=i instanceof Error?i.message:String(i);console.warn(`LFV read_secret retrying for ${_}. Retries: '${o}' Error: ${z$}`),QS=Date.now()}let zS=$S===void 0?Y:Math.min(Y,$S);if(zS<=0)throw c(),ZS("read_secret",_,d);await iS(zS)}let WS=KS(d);if(WS!==void 0){if(WS<=0)throw c(),Error(`LFV delivery timed out while reading ${_}`);let i;try{return await Promise.race([n,new Promise(($S,zS)=>{i=setTimeout(()=>{c(),zS(Error(`LFV delivery timed out while reading ${_}`))},WS)})])}finally{if(i)clearTimeout(i)}}return await n}function s(_,Z){y.set(_,Z);let j=A.get(_);if(!j)return;for(let T of j)T(Z)}async function p(_,Z){return await t(_,void 0,Z)}async function DS(_,Z,j){if(!B$(Z))throw Error(`putSecret requires an object value for LFV source at path ${_}`);let T=SS(j);if(await x(_,j)){await g("/secrets/update",_,"update_secret",{data:Z},void 0,T);return}await g("/secrets/create",_,"create_secret",{data:Z},void 0,T)}async function P(_,Z){let j=SS(Z);await g("/secrets/delete",_,"delete_secret",void 0,void 0,j)}async function C(_,Z){let j=q(_),T=SS(Z),O=crypto.randomUUID(),d=await k(_,"list_paths",O,T),h=await GS(`${j.lfvUrl.replace(/\/+$/g,"")}/paths/list`,{method:"POST",headers:{"Content-Type":"application/json","X-LFV-Request-Id":O,"X-LFV-Signature":U},body:JSON.stringify({request_id:O,otp:d,path:_})},T,"listPaths",_);if(h.status!==200){let c=await V(h);throw Error(`LFV listPaths failed (${h.status}) for ${_}: ${c}`)}let n=await h.json();if(!Array.isArray(n.items))throw Error(`LFV listPaths returned invalid payload for ${_}`);return n.items.filter((c)=>typeof c==="string")}async function x(_,Z){let j=q(_),T=SS(Z),O=crypto.randomUUID(),d=await k(_,"read_metadata",O,T),h=await GS(`${j.lfvUrl.replace(/\/+$/g,"")}/paths/exists`,{method:"POST",headers:{"Content-Type":"application/json","X-LFV-Request-Id":O,"X-LFV-Signature":U},body:JSON.stringify({request_id:O,otp:d,path:_})},T,"exists",_);if(h.status!==200){let c=await V(h);throw Error(`LFV exists failed (${h.status}) for ${_}: ${c}`)}let n=await h.json();if(typeof n.exists!=="boolean")throw Error(`LFV exists returned invalid payload for ${_}`);return n.exists}async function v(_,Z,j){let T=SS(j);await g("/secrets/rotate/request",_,"request_rotate",{reason:Z?.reason,severity:Z?.severity,incident_ref:Z?.incidentRef},void 0,T)}async function b(_,Z,j){let T=SS(j);await g("/secrets/revoke/request",_,"request_revoke",{reason:Z?.reason,severity:Z?.severity,incident_ref:Z?.incidentRef},void 0,T)}async function u(_,Z){let j=q(_),T=SS(Z),O=crypto.randomUUID(),d=await k(_,"read_metadata",O,T),h=await GS(`${j.lfvUrl.replace(/\/+$/g,"")}/paths/metadata/read`,{method:"POST",headers:{"Content-Type":"application/json","X-LFV-Request-Id":O,"X-LFV-Signature":U},body:JSON.stringify({request_id:O,otp:d,path:_})},T,"getMetadata",_);if(h.status!==200){let c=await V(h);throw Error(`LFV getMetadata failed (${h.status}) for ${_}: ${c}`)}let n=await h.json();if(!n.metadata||typeof n.metadata!=="object")throw Error(`LFV getMetadata returned invalid payload for ${_}`);return n.metadata}function W(_,Z){let j=A.get(_)??new Set;j.add(Z),A.set(_,j);let T=y.get(_);if(T)Z(T);return w(),()=>{let O=A.get(_);if(!O)return;if(O.delete(Z),O.size===0)A.delete(_);w()}}function m(_){return _.method==="POST"&&new URL(_.url).pathname===M}function z(_){return _.method==="POST"&&new URL(_.url).pathname===X}function G(_){let Z=_.data?.metadata?.path;if(typeof Z==="string"&&Z)return Z;if(typeof _.path==="string"&&_.path)return _.path;return}function N(_,Z){let j=f.get(_);if(!j||j.size===0)return!1;f.delete(_),w();for(let T of j)T.resolve(Z);return!0}function F(_){let Z=G(_);if(!Z)return{handled:!1};let j=_.data?.metadata??{},T=typeof j.version==="number"?j.version:0,O={data:_.data?.data??{},metadata:{path:Z,version:T,created:new Date}};return s(Z,O),{handled:N(Z,O)}}async function J(_){let Z=await _.json(),j=F(Z),T=await gS(Q,Z,H);if(!j.handled&&T===0)return new Response(JSON.stringify({status:"accepted",note:"unmapped_delivery"}),{status:200,headers:{"Content-Type":"application/json"}});return new Response(JSON.stringify({status:"accepted"}),{status:200,headers:{"Content-Type":"application/json"}})}function I(_){if(!_?.path||typeof _.path!=="string")return;if(_.event==="created"||_.event==="updated"||_.event==="rotated"||_.event==="revoked")t(_.path,_.request_id).catch(()=>{})}async function K(_){let Z=await _.json();if(!Z?.path||typeof Z.path!=="string")return new Response(JSON.stringify({error:"invalid_request",message:"path is required"}),{status:400,headers:{"Content-Type":"application/json"}});return I(Z),await sS(Q,Z,H),new Response(JSON.stringify({status:"accepted"}),{status:200,headers:{"Content-Type":"application/json"}})}return{type:S.type,getFullSecret:p,getSecret:async(_,Z)=>{return(await p(_,Z)).data},putSecret:DS,deleteSecret:P,listPaths:C,exists:x,requestRotate:v,requestRevoke:b,getMetadata:u,subscribe:W,isDeliveryRequest:m,isEventsRequest:z,handleDelivery:J,handleEvents:K}}function LS(S,$,L){if(typeof S!=="string"||S.trim()==="")throw Error(`"${$}" is required when using ${L}`);return S}var wS="__esLfvBootstrap";function xS(S){let $=LS(S.path,"path","lfvConfig"),L=LS(S.deliveryEndpoint,"deliveryEndpoint","lfvConfig"),R=LS(S.eventsEndpoint,"eventsEndpoint","lfvConfig"),U={type:"lfv",path:$,lfvServerUrl:S.lfvServerUrl,clientId:S.clientId,signature:S.signature,deliveryTimeout:S.deliveryTimeout,retryInterval:S.retryInterval,warnInterval:S.warnInterval,deliveryEndpoint:L,eventsEndpoint:R,verifyPublicKey:S.verifyPublicKey},D=S.vault??BS({type:"lfv",path:$,lfvServerUrl:LS(S.lfvServerUrl,"lfvServerUrl","lfvConfig"),clientId:LS(S.clientId,"clientId","lfvConfig"),signature:S.signature,deliveryTimeout:S.deliveryTimeout,retryInterval:S.retryInterval,warnInterval:S.warnInterval,deliveryEndpoint:L,eventsEndpoint:R,verifyPublicKey:S.verifyPublicKey}),Y={load:async()=>{try{return(await D.getFullSecret($)).data}catch(B){throw Error("Error retrieving remote config from LFV",{cause:B})}},subscribe:(B)=>{return D.subscribe($,(M)=>{B(M.data)})}};return Y[wS]=U,Y}import{watch as E$}from"node:fs";import{mkdir as J$,readFile as j$,writeFile as q$}from"node:fs/promises";import{dirname as F$,resolve as A$}from"node:path";import{parseJsonc as tS}from"@enterprisestandard/core";var rS=`// Example Enterprise Standard remote config (ConfigSource).
2
+ // Edit and save; local file watch reloads this automatically.
3
+ // See README.md Configuration section for which fields are ConfigSource-only vs FrameworkConfig (code).
4
+
5
+ {
6
+ // Optional app/tenant identifier for this ESA (e.g. from vault path or config).
7
+ // "tenantId": "my-tenant-123",
8
+
9
+ // --- SSO (OIDC) ---
10
+ // IdP endpoints and client credentials come from ConfigSource; handler paths (loginUrl, userUrl, etc.) are set in code.
11
+ "sso": {
12
+ "authority": "https://sso.example.com/realms/myrealm",
13
+ "tokenUrl": "https://sso.example.com/realms/myrealm/protocol/openid-connect/token",
14
+ "authorizationUrl": "https://sso.example.com/realms/myrealm/protocol/openid-connect/auth",
15
+ "clientId": "my-esa",
16
+ "clientSecret": "secret-from-idp",
17
+ "redirectUri": "https://myapp.example.com/api/es/sso/callback",
18
+ "scope": "openid profile email",
19
+ "jwksUri": "https://sso.example.com/realms/myrealm/protocol/openid-connect/certs",
20
+ "cookiesSecure": true,
21
+ "cookiesSameSite": "Lax"
22
+ },
23
+
24
+ // --- IAM (SCIM) ---
25
+ // Outbound: base URL of external SCIM endpoint. Inbound: userStore/groupStore and usersUrl/groupsUrl are set in code.
26
+ "iam": {
27
+ "url": "https://iam.example.com/scim/v2"
28
+ },
29
+
30
+ // --- Workload Identity ---
31
+ // Preferred: incoming (server-only: jwksUri, issuer) and outgoing (named clients). jwksUri/issuer are ConfigSource-only for server role.
32
+ "workload": {
33
+ "incoming": {
34
+ "jwksUri": "https://sso.example.com/realms/myrealm/protocol/openid-connect/certs",
35
+ "issuer": "https://sso.example.com/realms/myrealm"
36
+ },
37
+ "outgoing": {
38
+ "TNT_other-esa": {
39
+ "idpTokenUrl": "https://sso.example.com/realms/myrealm/protocol/openid-connect/token",
40
+ "clientId": "my-esa",
41
+ "clientSecret": "secret-from-idp",
42
+ "scope": "api:read"
43
+ }
44
+ }
45
+ },
46
+
47
+ // --- Secrets (named vault/LFV/cloud sources) ---
48
+ // Each key is a source name; framework config must use matching paths for LFV deliveryEndpoint/eventsEndpoint.
49
+ "secrets": {
50
+ "main": {
51
+ "type": "vault",
52
+ "url": "http://localhost:8200",
53
+ "token": "dev-token",
54
+ "ttl": 600000
55
+ }
56
+ // LFV example:
57
+ // "lfv": {
58
+ // "type": "lfv",
59
+ // "lfvServerUrl": "https://lfv.example.com",
60
+ // "clientId": "my-esa",
61
+ // "deliveryEndpoint": "/api/es/lfv/delivery",
62
+ // "eventsEndpoint": "/api/es/lfv/events"
63
+ // }
64
+ },
65
+
66
+ // --- Tenant Management ---
67
+ // Optional: signingKey (ConfigSource-only) for action_required request tokens; requestTokenTtl in seconds.
68
+ "tenant": {
69
+ "requestTokenTtl": 300
70
+ // "signingKey": "base64-or-hex-signing-key"
71
+ },
72
+
73
+ // --- CIAM (Magic Link) ---
74
+ // signingKey, magicLinkTtl, cookiesSecure, cookiesSameSite are ConfigSource-only; handler paths and stores are set in code.
75
+ "ciam": {
76
+ "signingKey": "replace-with-secure-key-from-vault",
77
+ "magicLinkTtl": 3600,
78
+ "cookiesSecure": true,
79
+ "cookiesSameSite": "Strict"
80
+ }
81
+ }
82
+ `;function yS(S){let $=S.path??"es-config.jsonc",L=S.watch!==!1,R=A$(process.cwd(),$),U=async()=>{try{let D=await j$(R,"utf-8");return tS(D)}catch(D){let Y=D;if(Y.code==="ENOENT")return await J$(F$(R),{recursive:!0}),await q$(R,rS,"utf-8"),console.warn(`Config file "${R}" was not found. Wrote an example config file for local development.`),tS(rS);if(Y instanceof SyntaxError){let M=Y.message;throw Error(`Invalid JSON/JSONC in "${R}": ${M}`)}let B=Y instanceof Error?Y.message:String(Y);throw Error(`Failed to read config file "${R}": ${B}`)}};return{load:U,subscribe(D){let Y,B,M=!1,X=async()=>{try{let Q=await U();if(!M)D(Q);if(L&&!Y&&!M)Y=E$(R,()=>{if(B)clearTimeout(B);B=setTimeout(()=>{B=void 0,X()},150)})}catch(Q){let H=Q instanceof Error?Q.message:String(Q);console.warn(`Failed to reload local config from "${R}": ${H}`)}};return X(),()=>{if(M=!0,B)clearTimeout(B),B=void 0;Y?.close()}}}}function XS(S){let{type:$="vault",url:L,token:R,ttl:U}=S;if(!L)throw Error("OpenBao/Hashicorp compatible vaults require a non-empty url");if(!R)console.log("OpenBao/Hashicorp compatible vaults usually require a token, but one was not provided. Vault requests may fail.");if(U&&U<600000)throw Error("OpenBao/Hashicorp compatible vaults require ttl to be set and greater than 600_000 milliseconds (10 minutes), as not to overload the vault with polling requests");let D={"Content-Type":"application/json"};if(R)D["X-Vault-Token"]=R;function Y(E){return typeof E==="object"&&E!==null&&!Array.isArray(E)}async function B(E,w){let q=await fetch(`${L}/${E}`,{headers:{...D}});if(q.status!==200){let k=q.status===401||q.status===403?`Vault returned ${q.status} ${q.statusText} (auth error) from URL: ${L}/${E}`:`Vault returned invalid status, ${q.status}: '${q.statusText}' from URL: ${L}/${E}`;throw Error(k)}try{return(await q.json()).data}catch(V){throw Error("Error retrieving secret",{cause:V})}}async function M(E,w,q){if(!Y(w))throw Error(`putSecret requires an object value for vault source at path ${E}`);let V=await fetch(`${L}/${E}`,{method:"POST",headers:D,body:JSON.stringify(w)});if(V.status!==200&&V.status!==201&&V.status!==204){let k=await V.text().catch(()=>"");throw Error(`Vault putSecret failed (${V.status}) for ${L}/${E}: ${k}`)}}async function X(E,w){let q=await fetch(`${L}/${E}`,{method:"DELETE",headers:D});if(q.status!==200&&q.status!==202&&q.status!==204){let V=await q.text().catch(()=>"");throw Error(`Vault deleteSecret failed (${q.status}) for ${L}/${E}: ${V}`)}}async function Q(E,w){let q=`${L}/${E}`,V=async(s)=>{if(s==="LIST")return fetch(q,{method:"LIST",headers:D});let p=q.includes("?")?"&":"?";return fetch(`${q}${p}list=true`,{method:"GET",headers:D})},k=await V("LIST");if(k.status===405||k.status===501)k=await V("GET");if(k.status!==200){let s=await k.text().catch(()=>"");throw Error(`Vault listPaths failed (${k.status}) for ${L}/${E}: ${s}`)}let g=await k.json().catch(()=>null),t;if(g&&typeof g==="object"){let s=g,p=s.data;if(p&&typeof p==="object")t=p.keys;else t=s.keys}if(!Array.isArray(t))throw Error(`Vault listPaths returned an unexpected response for ${L}/${E}`);return t.filter((s)=>typeof s==="string")}async function H(E,w){let q=await fetch(`${L}/${E}`,{headers:D});if(q.status===200)return!0;if(q.status===404)return!1;if(q.status===401||q.status===403)throw Error(`Vault exists failed (${q.status}) for ${L}/${E}: permission denied`);let V=await q.text().catch(()=>"");throw Error(`Vault exists failed (${q.status}) for ${L}/${E}: ${V}`)}async function A(E,w,q){throw Error(`Vault requestRotate is not implemented for source ${$} at path ${E}`)}async function y(E,w,q){throw Error(`Vault requestRevoke is not implemented for source ${$} at path ${E}`)}async function f(E,w){return(await B(E,w)).metadata}return{type:$,getFullSecret:B,getSecret:async(E,w)=>{return(await B(E,w)).data},putSecret:M,deleteSecret:X,listPaths:Q,exists:H,requestRotate:A,requestRevoke:y,getMetadata:f,subscribe:(E,w)=>{if(!U)return console.warn("OpenBao/Hashicorp compatible vaults require ttl to be set if you want to subscribe to changes"),()=>{};let q,V=setInterval(async()=>{try{let k=await B(E);if(q===void 0){q=k.metadata.version;return}if(k.metadata.version!==q)q=k.metadata.version,w(k)}catch(k){console.warn(`Error retrieving remote config from vault. Retrying in ${S.ttl} milliseconds`,k)}},U);return()=>clearInterval(V)}}}function aS(S){if(!S||typeof S!=="object"||Array.isArray(S))return{};let $=S;if(!(("tenantId"in $)||("sso"in $)||("iam"in $)||("workload"in $)||("secrets"in $)||("tenant"in $)||("ciam"in $))&&Object.keys($).length===1&&"data"in $){let R=$.data;if(R&&typeof R==="object"&&!Array.isArray(R))return R}return $}function ES(S){let $=LS(S.path,"path","vaultConfig"),L=S.vault??XS({type:"vault",url:S.url,token:S.token,ttl:S.ttl});return{load:async()=>{try{let R=await L.getFullSecret($);return aS(R.data)}catch(R){if(!S?.retryInterval)throw Error("Error retrieving remote config from vault",{cause:R});else return console.warn(`Error retrieving remote config from vault. Retrying in ${S.ttl} seconds`,R),{}}},subscribe:(R)=>{return L.subscribe($,(U)=>{R(aS(U.data))})}}}function kS(S){if(!S)return;let $=Number.parseInt(S,10);return Number.isFinite($)?$:void 0}function vS(S){let $=S?.type??process.env.ES_CONFIG_TYPE;if(!$||$==="dev"){let L=S??{};return IS({appId:L?.appId??process.env.ES_APP_ID,path:process.env.ES_CONFIG_PATH??L?.path,ioniteUrl:process.env.ES_IONITE_URL??L?.ioniteUrl})}else if($==="lfv"){let L=S??{};return xS({path:process.env.ES_LFV_PATH??L?.path,lfvServerUrl:process.env.ES_LFV_SERVER_URL??L?.lfvServerUrl,clientId:process.env.ES_LFV_CLIENT_ID??L?.clientId,signature:process.env.ES_LFV_SIGNATURE??L?.signature,deliveryEndpoint:process.env.ES_LFV_DELIVERY_ENDPOINT??L?.deliveryEndpoint,verifyPublicKey:process.env.ES_LFV_VERIFY_PUBLIC_KEY??L?.verifyPublicKey,eventsEndpoint:process.env.ES_LFV_EVENTS_ENDPOINT??L?.eventsEndpoint,deliveryTimeout:kS(process.env.ES_LFV_DELIVERY_TIMEOUT)??L?.deliveryTimeout,retryInterval:kS(process.env.ES_LFV_RETRY_INTERVAL)??L?.retryInterval,warnInterval:kS(process.env.ES_LFV_WARN_INTERVAL)??L?.warnInterval})}else if($==="localFile"){let L=S??{};return yS({path:process.env.ES_FILE_PATH??L?.path,watch:process.env.ES_FILE_WATCH==="true"||L?.watch,ttl:process.env.ES_FILE_TTL?parseInt(process.env.ES_FILE_TTL,10):void 0})}else if($==="vault"){let L=S??{};return L.vault?ES(L):ES({url:process.env.ES_VAULT_URL??L?.url,token:process.env.ES_VAULT_TOKEN??L?.token,path:process.env.ES_VAULT_PATH??L?.path,ttl:process.env.ES_VAULT_TTL?parseInt(process.env.ES_VAULT_TTL,10):void 0})}else if($==="azure"){let L=S??{};return L.vault?NS(L):NS({apiVersion:process.env.ES_AZURE_API_VERSION??L?.apiVersion,scope:process.env.ES_AZURE_SCOPE??L?.scope,secretNamePrefix:process.env.ES_AZURE_SECRET_NAME_PREFIX??L?.secretNamePrefix,authMethod:process.env.ES_AZURE_AUTH_METHOD??L?.authMethod,tenantId:process.env.ES_AZURE_TENANT_ID??L?.tenantId,clientId:process.env.ES_AZURE_CLIENT_ID??L?.clientId,clientSecret:process.env.ES_AZURE_CLIENT_SECRET??L?.clientSecret,federatedTokenFile:process.env.ES_AZURE_FEDERATED_TOKEN_FILE??L?.federatedTokenFile,managedIdentityClientId:process.env.ES_AZURE_MANAGED_IDENTITY_CLIENT_ID??L?.managedIdentityClientId,imdsApiVersion:process.env.ES_AZURE_IMDS_API_VERSION??L?.imdsApiVersion,vaultUrl:process.env.ES_AZURE_VAULT_URL??L?.vaultUrl,vaultName:process.env.ES_AZURE_VAULT_NAME??L?.vaultName,ttl:process.env.ES_AZURE_TTL?parseInt(process.env.ES_AZURE_TTL,10):void 0})}else if($==="aws"){let L=S??{};return L.vault?MS(L):MS({webhookUrl:process.env.ES_AWS_WEBHOOK_URL??L?.webhookUrl,ttl:process.env.ES_AWS_TTL?parseInt(process.env.ES_AWS_TTL,10):void 0})}else if($==="gcp"){let L=S??{};return L.vault?HS(L):HS({ttl:process.env.ES_GCP_TTL?parseInt(process.env.ES_GCP_TTL,10):void 0})}throw Error(`ES_CONFIG_TYPE="${$}" is not a valid ConfigSourceType when using envConfig().`)}import{defaultLogger as W$}from"@enterprisestandard/core";import{list as P$}from"@enterprisestandard/core";class JS{groups=new Map;externalIdIndex=new Map;displayNameIndex=new Map;async get(S){return this.groups.get(S)??null}async getByExternalId(S){let $=this.externalIdIndex.get(S);if(!$)return null;return this.groups.get($)??null}async getByDisplayName(S){let $=this.displayNameIndex.get(S.toLowerCase());if(!$)return null;return this.groups.get($)??null}async list(S){let $=Array.from(this.groups.values()),L=Math.max(0,S?.start??0),R=S?.limit;if(S?.sort?.length)$=[...$].sort((B,M)=>{for(let{field:X,direction:Q}of S.sort){let H=B[X],A=M[X],y=T$(H,A);if(y!==0)return Q==="desc"?-y:y}return 0});let U=$.length,D=R!=null?L+R:void 0,Y=$.slice(L,D);return P$(U,Y,L,R)}async upsert(S){let $=this.groups.get(S.id);if($){if($.externalId&&$.externalId!==S.externalId)this.externalIdIndex.delete($.externalId);if($.displayName.toLowerCase()!==S.displayName.toLowerCase())this.displayNameIndex.delete($.displayName.toLowerCase())}if(this.groups.set(S.id,S),S.externalId)this.externalIdIndex.set(S.externalId,S.id);this.displayNameIndex.set(S.displayName.toLowerCase(),S.id)}async delete(S){let $=this.groups.get(S);if($){if($.externalId)this.externalIdIndex.delete($.externalId);this.displayNameIndex.delete($.displayName.toLowerCase())}this.groups.delete(S)}async addMember(S,$){let L=this.groups.get(S);if(!L)throw Error(`Group ${S} not found`);let R=L.members??[];if(!R.some((U)=>U.value===$.value))R.push($),L.members=R,L.updatedAt=new Date}async removeMember(S,$){let L=this.groups.get(S);if(!L)throw Error(`Group ${S} not found`);if(L.members)L.members=L.members.filter((R)=>R.value!==$),L.updatedAt=new Date}}function T$(S,$){let L=S===void 0||S===null,R=$===void 0||$===null;if(L&&R)return 0;if(L)return 1;if(R)return-1;if(S instanceof Date&&$ instanceof Date)return S.getTime()-$.getTime();let U=String(S),D=String($);return U.localeCompare(D)}class jS{magicLinks=new Map;async create(S,$,L){if(this.magicLinks.has(S))throw Error(`Magic link with token ${S} already exists`);let R={token:S,user:$,createdAt:new Date,expiresAt:L};this.magicLinks.set(S,R)}async get(S){let $=this.magicLinks.get(S);if(!$)return null;if(Date.now()>$.expiresAt.getTime())return this.magicLinks.delete(S),null;return $}async delete(S){this.magicLinks.delete(S)}}class qS{sessions=new Map;async create(S){if(this.sessions.has(S.sid))throw Error(`Session with sid ${S.sid} already exists`);this.sessions.set(S.sid,S)}async get(S){return this.sessions.get(S)??null}async update(S,$){let L=this.sessions.get(S);if(!L)throw Error(`Session with sid ${S} not found`);let R={...L,...$};this.sessions.set(S,R)}async delete(S){this.sessions.delete(S)}}import{list as V$}from"@enterprisestandard/core";class FS{users=new Map;emailIndex=new Map;userNameIndex=new Map;async get(S){return this.users.get(S)??null}async getByEmail(S){let $=this.emailIndex.get(S.toLowerCase());if(!$)return null;return this.users.get($)??null}async getByUserName(S){let $=this.userNameIndex.get(S.toLowerCase());if(!$)return null;return this.users.get($)??null}async upsert(S){let $=this.users.get(S.id);if($){if($.email&&$.email.toLowerCase()!==S.email?.toLowerCase())this.emailIndex.delete($.email.toLowerCase());if($.userName&&$.userName.toLowerCase()!==S.userName?.toLowerCase())this.userNameIndex.delete($.userName.toLowerCase())}if(this.users.set(S.id,S),S.email)this.emailIndex.set(S.email.toLowerCase(),S.id);if(S.userName)this.userNameIndex.set(S.userName.toLowerCase(),S.id)}async delete(S){let $=this.users.get(S);if($){if($.email)this.emailIndex.delete($.email.toLowerCase());if($.userName)this.userNameIndex.delete($.userName.toLowerCase())}this.users.delete(S)}async list(S){let $=Array.from(this.users.values()),L=Math.max(0,S?.start??0),R=S?.limit;if(S?.sort?.length)$=[...$].sort((B,M)=>{for(let{field:X,direction:Q}of S.sort){let H=B[X],A=M[X],y=O$(H,A);if(y!==0)return Q==="desc"?-y:y}return 0});let U=$.length,D=R!=null?L+R:void 0,Y=$.slice(L,D);return V$(U,Y,L,R)}}function O$(S,$){let L=S===void 0||S===null,R=$===void 0||$===null;if(L&&R)return 0;if(L)return 1;if(R)return-1;if(S instanceof Date&&$ instanceof Date)return S.getTime()-$.getTime();return String(S).localeCompare(String($))}class RS{tokens=new Map;async set(S){this.tokens.set(S.workload_id,S)}async get(S){let $=this.tokens.get(S);if(!$)return null;if(Date.now()>$.expires_at.getTime())return this.tokens.delete(S),null;return $}async delete(S){this.tokens.delete(S)}async isValid(S){return await this.get(S)!==null}async cleanup(){let S=Date.now();for(let[$,L]of this.tokens.entries())if(S>L.expires_at.getTime())this.tokens.delete($)}}var bS="__esDynamicConfig";function AS(S){if(!S)return;try{return new URL(S).pathname}catch{return S.startsWith("/")?S:`/${S}`}}function I$(S){let $=S.workload;if(!$||typeof $!=="object")return;if(typeof $.tokenUrl==="string")return AS($.tokenUrl);let L=$.incoming;if(L&&typeof L.tokenUrl==="string")return AS(L.tokenUrl);let R=$.default;if(R&&typeof R.tokenUrl==="string")return AS(R.tokenUrl);return}function w$(S,$,L){let R={...$},U=L.basePath,D=L.stores;if(L.validators&&!R.validators)R.validators=L.validators;if(L.logger&&!R.logger)R.logger=L.logger;if(S.sso&&!R.sso)R.sso={redirectUri:AS(S.sso.redirectUri)??`${U}/auth/callback`,loginUrl:`${U}/auth/login`,userUrl:`${U}/auth/user`,logoutUrl:`${U}/auth/logout`,logoutBackChannelUrl:`${U}/auth/logout/backchannel`,sessionStore:D.sessionStore,userStore:D.userStore,enableJitUserProvisioning:!0};if(S.iam&&!R.iam)R.iam={usersUrl:`${U}/iam/Users`,groupsUrl:`${U}/iam/Groups`,userStore:D.userStore,groupStore:D.groupStore};if(S.workload&&!R.workload)R.workload={tokenUrl:I$(S)??`${U}/workload/token`,validateUrl:`${U}/workload/validate`,jwksUrl:`${U}/workload/jwks`,refreshUrl:`${U}/workload/refresh`,tokenStore:D.workloadTokenStore};if(S.ciam&&!R.ciam)R.ciam={magicLinkUrl:`${U}/magic-link`,magicLinkLoginUrl:`${U}/magic-link/login`,logoutUrl:`${U}/auth/logout`,logoutBackChannelUrl:`${U}/auth/logout/backchannel`,landingUrl:"/",sessionStore:D.sessionStore,userStore:D.userStore,magicLinkStore:D.magicLinkStore,enableJitUserProvisioning:!0};if(S.tenant&&!R.tenant)R.tenant={};return R}function x$(S,$){return(L,R,U)=>{let D=w$(L,R,$),Y=S?.(L,D,U);return{config:Y?.config??L,frameworkConfig:Y?.frameworkConfig??D}}}function y$(S={}){return{validators:S.validators,logger:S.logger,stores:{sessionStore:S.stores?.sessionStore??new qS,userStore:S.stores?.userStore??new FS,groupStore:S.stores?.groupStore??new JS,magicLinkStore:S.stores?.magicLinkStore??new jS,workloadTokenStore:S.stores?.workloadTokenStore??new RS},basePath:S.basePath??"/api/es"}}function PS(S={}){let $=y$(S);return{validators:$.validators,logger:$.logger,[bS]:$}}function k$(S={}){return PS(S)}function eS(S,$){let L=S??{},R=L[bS];if(!R)return{config:S??{},options:$};let U={...L};delete U[bS];let D={...$??{},beforeChange:x$($?.beforeChange,R)};return(U.logger??W$).info?.("Dynamic framework configuration enabled",{basePath:R.basePath,adaptiveStores:!0}),{config:U,options:D}}import{logout as oS,logoutBackChannel as S$}from"@enterprisestandard/core/server";function $$(S){if(!S)return;try{return new URL(S).pathname}catch{return S.startsWith("/")?S:`/${S}`}}function L$(S){return S==="/"?S:S.replace(/\/+$/,"")}function v$(S){let $=L$(S);return{matchesPath:(U)=>{if(!U)return!1;let D=$$(U);if(!D)return!1;return L$(D)===$},startsWithPath:(U)=>{if(!U)return!1;let D=$$(U);if(!D)return!1;return S===D||S.startsWith(`${D}/`)}}}function b$(S,$){let L=new URL(S.url).pathname,{matchesPath:R,startsWithPath:U}=v$(L);if($.sso){let D=$.sso;if(R($.sso.userUrl))return{module:"sso",kind:"sso.user",handler:async(Y)=>{let B=await D.handler(Y);if(B.status===401&&$.ciam){let M=await $.ciam.getUser(Y);if(M)return new Response(JSON.stringify(M),{headers:{"Content-Type":"application/json"}})}return B}};if(R($.sso.logoutUrl))return{module:"sso",kind:"sso.logout",handler:async(Y)=>oS(Y,$)};if(R($.sso.logoutBackChannelUrl))return{module:"sso",kind:"sso.logout_backchannel",handler:async(Y)=>S$(Y,$)};if(R($.sso.loginUrl)||R($.sso.tokenUrl)||R($.sso.refreshUrl)||R($.sso.jwksUrl)||R($.sso.redirectUri))return{module:"sso",kind:"sso.handler",handler:async(Y)=>D.handler(Y)}}if($.ciam){if(R($.ciam.logoutUrl))return{module:"ciam",kind:"ciam.logout",handler:async(D)=>oS(D,$)};if(R($.ciam.logoutBackChannelUrl))return{module:"ciam",kind:"ciam.logout_backchannel",handler:async(D)=>S$(D,$)}}if($.iam){let D=$.iam;if(U($.iam.usersUrl)||U($.iam.groupsUrl))return{module:"iam",kind:"iam.handler",handler:async(Y)=>D.handler(Y)}}if($.workload){let D=$.workload,M=D._handlerTokenUrl??(D.tokenUrl?.startsWith("/")?D.tokenUrl:void 0)??(D.tokenUrl&&!D.tokenUrl.startsWith("http")?D.tokenUrl:void 0),X="validateUrl"in D?D.validateUrl:void 0,Q="jwksUrl"in D?D.jwksUrl:void 0,H="refreshUrl"in D?D.refreshUrl:void 0;if(R(M)||R(X)||R(Q)||R(H))return{module:"workload",kind:"workload.handler",handler:async(A)=>D.handler(A)}}if($.secrets){let D=$.secrets;if(D.isLfvDeliveryRequest?.(S)&&D.handleLfvDelivery){let Y=D.handleLfvDelivery;return{module:"secrets",kind:"secrets.lfv_delivery",handler:async(B)=>Y(B)}}if(D.isLfvEventsRequest?.(S)&&D.handleLfvEvents){let Y=D.handleLfvEvents;return{module:"secrets",kind:"secrets.lfv_events",handler:async(B)=>Y(B)}}}if($.ciam){let D=$.ciam,Y=$.ciam.magicLinkUrl||"/magic-link",B=$.ciam.magicLinkLoginUrl||"/magic-link/login";if(R(Y)&&S.method==="POST"||R(B)&&S.method==="GET")return{module:"ciam",kind:"ciam.handler",handler:async(M)=>D.handler(M)}}return}async function R$(S,$,L){if(L?.filter){let Y=await L.filter(S,$);if(Y instanceof Response)return Y;if(Y==="not_handled")return new Response("Not Found",{status:404})}let R=()=>b$(S,$),U=await L?.resolve?.(S,$,R)??R();if(!U)return new Response("Not Found",{status:404});let D=async()=>U.handler(S);if(L?.wrap)return await L.wrap(S,U,D,$);return await D()}import{readFile as m$,stat as C$}from"node:fs/promises";function TS(S,$){if(!S||S.trim().length===0)throw Error(`Missing required Azure config: ${$}`);return S}function u$(S){return S.replace(/^\/+|\/+$/g,"").replaceAll("/","--")}function mS(S,$){return`${S.replace(/\/+$/g,"")}/${$.replace(/^\/+/g,"")}`}function h$(S){try{let L=new URL(S).pathname.split("/").filter(Boolean),R=L.indexOf("secrets");if(R===-1)return;return L[R+2]||void 0}catch{return}}function d$(S){return typeof S==="object"&&S!==null&&!Array.isArray(S)}function U$(S){let $=S.apiVersion??"7.4",L=S.scope??"https://vault.azure.net/.default",R=S.secretNameTransform??u$,U=S.authMethod,D="/var/run/secrets/azure/tokens/azure-identity-token",Y=S.federatedTokenFile??"/var/run/secrets/azure/tokens/azure-identity-token",B=S.vaultUrl??(S.vaultName?`https://${S.vaultName}.vault.azure.net`:void 0)??void 0,M=TS(B,"vaultUrl or vaultName (ES_AZURE_KEY_VAULT_URL / ES_AZURE_KEY_VAULT_NAME)");async function X(P){try{return await C$(P),!0}catch{return!1}}let Q,H;async function A(P){let{tenantId:C,clientId:x}=S;if(!C)throw Error("Workload identity requires tenantId");if(!x)throw Error("Workload identity requires clientId");if(!await X(Y))throw Error(`Federated token file not found at ${Y}`);let v=(await m$(Y,"utf8")).trim();if(!v)throw Error("Federated token file was empty");let b=`https://login.microsoftonline.com/${encodeURIComponent(C)}/oauth2/v2.0/token`,u=new URLSearchParams({client_id:x,grant_type:"client_credentials",scope:L,client_assertion_type:"urn:ietf:params:oauth:client-assertion-type:jwt-bearer",client_assertion:v}),W=await fetch(b,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:u});if(W.status!==200){let z=await W.text().catch(()=>"");throw Error(`Azure workload identity token exchange returned ${W.status} ${W.statusText}. tenantId=${C}. Response: ${z}`)}let m=await W.json();if(!m?.access_token)throw Error("Azure token response missing access_token");return Q={accessToken:m.access_token,expiresAtMs:P+(m.expires_in??0)*1000},m.access_token}async function y(P){let C=S.imdsApiVersion??"2018-02-01",x="https://vault.azure.net",v=new URL("http://169.254.169.254/metadata/identity/oauth2/token");if(v.searchParams.set("api-version",C),v.searchParams.set("resource","https://vault.azure.net"),S.managedIdentityClientId)v.searchParams.set("client_id",S.managedIdentityClientId);let b=await fetch(v.toString(),{headers:{Metadata:"true",Accept:"application/json"}});if(b.status!==200){let m=await b.text().catch(()=>"");throw Error(`Azure IMDS token endpoint returned ${b.status} ${b.statusText}. Response: ${m}`)}let u=await b.json();if(!u?.access_token)throw Error("IMDS token response missing access_token");let W=P+60000;if(u.expires_on){let m=Number.parseInt(u.expires_on,10);if(Number.isFinite(m)&&m>0)W=m*1000;else{let z=Date.parse(u.expires_on);if(Number.isFinite(z))W=z}}else if(u.expires_in){let m=Number.parseInt(u.expires_in,10);if(Number.isFinite(m)&&m>0)W=P+m*1000}return Q={accessToken:u.access_token,expiresAtMs:W},u.access_token}async function f(P){let C=TS(S.tenantId,"tenantId (or ES_AZURE_TENANT_ID/AZURE_TENANT_ID)"),x=TS(S.clientId,"clientId (or ES_AZURE_CLIENT_ID/AZURE_CLIENT_ID)"),v=TS(S.clientSecret,"clientSecret (or ES_AZURE_CLIENT_SECRET)"),b=`https://login.microsoftonline.com/${encodeURIComponent(C)}/oauth2/v2.0/token`,u=new URLSearchParams({client_id:x,client_secret:v,grant_type:"client_credentials",scope:L}),W=await fetch(b,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:u});if(W.status!==200){let z=await W.text().catch(()=>"");throw Error(`Azure token endpoint returned ${W.status} ${W.statusText}. tenantId=${C}. Response: ${z}`)}let m=await W.json();if(!m?.access_token)throw Error("Azure token response missing access_token");return Q={accessToken:m.access_token,expiresAtMs:P+(m.expires_in??0)*1000},m.access_token}async function E(){let P=Date.now();if(Q&&Q.expiresAtMs-60000>P)return Q.accessToken;if(H)return H;H=(async()=>{if(U==="workload_identity")return await A(P);if(U==="managed_identity")return await y(P);if(U==="client_secret")return await f(P);if(await X(Y))try{return await A(P)}catch{}try{return await y(P)}catch{}return await f(P)})();try{return await H}finally{H=void 0}}async function w(P){let C=await E(),x=mS(M,`/secrets/${encodeURIComponent(P)}?api-version=${encodeURIComponent($)}`),v=await fetch(x,{headers:{Authorization:`Bearer ${C}`,Accept:"application/json"}});if(v.status!==200){let b=await v.text().catch(()=>"");throw Error(`Key Vault returned ${v.status} ${v.statusText} for ${x}. Response: ${b}`)}return await v.json()}async function q(P,C){let x=R(P),v=S.secretNamePrefix?`${S.secretNamePrefix}${x}`:x,b=await w(v),u=b.value;try{u=JSON.parse(b.value)}catch{}let W=b.attributes?.created?b.attributes.created*1000:void 0,m=h$(b.id);return{data:u,metadata:{path:P,version:Number.parseInt(m??"",10)||0,created:W?new Date(W):new Date}}}async function V(P,C,x){if(!d$(C))throw Error(`putSecret requires an object value for azure source at path ${P}`);let v=R(P),b=S.secretNamePrefix?`${S.secretNamePrefix}${v}`:v,u=await E(),W=mS(M,`/secrets/${encodeURIComponent(b)}?api-version=${encodeURIComponent($)}`),m=JSON.stringify({value:JSON.stringify(C)}),z=await fetch(W,{method:"PUT",headers:{Authorization:`Bearer ${u}`,"Content-Type":"application/json",Accept:"application/json"},body:m});if(z.status!==200&&z.status!==201){let G=await z.text().catch(()=>"");throw Error(`Key Vault putSecret returned ${z.status} for ${W}: ${G}`)}}async function k(P,C){let x=R(P),v=S.secretNamePrefix?`${S.secretNamePrefix}${x}`:x,b=await E(),u=mS(M,`/secrets/${encodeURIComponent(v)}?api-version=${encodeURIComponent($)}`),W=await fetch(u,{method:"DELETE",headers:{Authorization:`Bearer ${b}`,Accept:"application/json"}});if(W.status!==200&&W.status!==202&&W.status!==204){let m=await W.text().catch(()=>"");throw Error(`Key Vault deleteSecret returned ${W.status} for ${u}: ${m}`)}}async function g(P,C){throw Error(`listPaths is not implemented for Azure Key Vault source at path ${P}`)}async function t(P,C){try{return await q(P),!0}catch(x){if((x instanceof Error?x.message:String(x)).includes(" 404 "))return!1;throw x}}async function s(P,C,x){throw Error(`requestRotate is not implemented for Azure Key Vault source at path ${P}`)}async function p(P,C,x){throw Error(`requestRevoke is not implemented for Azure Key Vault source at path ${P}`)}async function DS(P,C){let x=R(P),v=S.secretNamePrefix?`${S.secretNamePrefix}${x}`:x,b=await w(v);return{id:b.id,...b.attributes??{}}}return{type:S.type,getFullSecret:q,getSecret:async(P,C)=>{return(await q(P,C)).data},putSecret:V,deleteSecret:k,listPaths:g,exists:t,requestRotate:s,requestRevoke:p,getMetadata:DS,subscribe:(P,C)=>{throw Error("TODO: subscribe not implemented for azure vault")}}}function D$(S){async function $(X,Q){throw Error("Error retrieving secret",{cause:Error("Not implemented")})}async function L(X,Q,H){throw Error("putSecret not implemented for dev vault")}async function R(X,Q){throw Error(`deleteSecret not implemented for dev vault at path ${X}`)}async function U(X,Q){throw Error(`listPaths not implemented for dev vault at path ${X}`)}async function D(X,Q){throw Error(`exists not implemented for dev vault at path ${X}`)}async function Y(X,Q,H){throw Error(`requestRotate not implemented for dev vault at path ${X}`)}async function B(X,Q,H){throw Error(`requestRevoke not implemented for dev vault at path ${X}`)}async function M(X,Q){throw Error(`getMetadata not implemented for dev vault at path ${X}`)}return{type:S.type,getFullSecret:$,getSecret:async(X,Q)=>{return(await $(X,Q)).data},putSecret:L,deleteSecret:R,listPaths:U,exists:D,requestRotate:Y,requestRevoke:B,getMetadata:M,subscribe:(X,Q)=>{throw Error("TODO: subscribe not implemented for dev vault")}}}function _$(S,$){let L=(R,U)=>{throw Error(`${R} is not implemented for source "${$}" (type: ${S}) at path ${U}`)};return{type:S,getFullSecret:(R,U)=>Promise.reject(L("getFullSecret",R)),getSecret:(R,U)=>Promise.reject(L("getSecret",R)),putSecret:(R,U,D)=>Promise.reject(L("putSecret",R)),subscribe:(R,U)=>{return L("subscribe",R),()=>{}},deleteSecret:(R,U)=>Promise.reject(L("deleteSecret",R)),listPaths:(R,U)=>Promise.reject(L("listPaths",R)),exists:(R,U)=>Promise.reject(L("exists",R)),requestRotate:(R,U,D)=>Promise.reject(L("requestRotate",R)),requestRevoke:(R,U,D)=>Promise.reject(L("requestRevoke",R)),getMetadata:(R,U)=>Promise.reject(L("getMetadata",R))}}function c$(S,$){if($.type==="vault")return XS($);if($.type==="lfv")return BS($);if($.type==="azure")return U$($);if($.type==="dev")return D$($);if($.type==="aws")return _$($.type,S);if($.type==="gcp")return _$($.type,S);throw Error(`Unsupported secrets source type for "${S}"`)}function f$(S){return S.type==="lfv"&&typeof S.isDeliveryRequest==="function"&&typeof S.isEventsRequest==="function"&&typeof S.handleDelivery==="function"&&typeof S.handleEvents==="function"}function n$(S,$){let L={},R=new Set([...Object.keys(S??{}),...Object.keys($??{})]);for(let U of R){let D=S?.[U],Y=$?.[U];L[U]={...D??{},...Y??{}}}return L}function CS(S,$,L,R){if(!L&&!R)return;let U=n$(L,R),D={};for(let[Q,H]of Object.entries(U))S?.validateSourceConfig?.(Q,H),D[Q]=c$(Q,H);let Y=(Q)=>{let H=D[Q];if(!H)throw $.warn?.(`Secrets source "${Q}" is not configured`),Error(`Secrets source "${Q}" is not configured`);return H},B=()=>{return Object.values(D).filter(f$)},M=(Q)=>{return B().find((H)=>H.isDeliveryRequest(Q))},X=(Q)=>{return B().find((H)=>H.isEventsRequest(Q))};return{config:D,listSecretsSources:()=>Object.keys(D),getSecretsSource:Y,getSecret:(Q,H,A)=>Y(Q).getSecret(H,A),getFullSecret:(Q,H,A)=>Y(Q).getFullSecret(H,A),putSecret:(Q,H,A,y)=>Y(Q).putSecret(H,A,y),deleteSecret:(Q,H,A)=>Y(Q).deleteSecret(H,A),listPaths:(Q,H,A)=>Y(Q).listPaths(H,A),exists:(Q,H,A)=>Y(Q).exists(H,A),requestRotate:(Q,H,A,y)=>Y(Q).requestRotate(H,A,y),requestRevoke:(Q,H,A,y)=>Y(Q).requestRevoke(H,A,y),getMetadata:(Q,H,A)=>Y(Q).getMetadata(H,A),subscribe:(Q,H,A)=>Y(Q).subscribe(H,A),isLfvDeliveryRequest:(Q)=>M(Q)!==void 0,isLfvEventsRequest:(Q)=>X(Q)!==void 0,handleLfvDelivery:async(Q)=>{let H=M(Q);if(!H)return new Response("Not Found",{status:404});return H.handleDelivery(Q)},handleLfvEvents:async(Q)=>{let H=X(Q);if(!H)return new Response("Not Found",{status:404});return H.handleEvents(Q)}}}import{must as r}from"@enterprisestandard/core";var Y$=new Map;function l(S){if(S===void 0||S===null)return!1;let $=S;return $.workloadId!==void 0&&$.workloadId!==null||$.privateKey!==void 0&&$.privateKey!==null}function e(S){if(S===void 0||S===null)return!1;let $=S,L=$.clientId!==void 0&&$.clientId!==null,R=$.clientSecret!==void 0&&$.clientSecret!==null,U=$.workloadId!==void 0&&$.workloadId!==null,D=$.privateKey!==void 0&&$.privateKey!==null;return(L||R)&&!U&&!D}function uS(S){if(S===void 0||S===null)return!1;let $=S,L=$.jwksUri!==void 0&&$.jwksUri!==null,R=$.workloadId!==void 0&&$.workloadId!==null,U=$.clientId!==void 0&&$.clientId!==null,D=$.clientSecret!==void 0&&$.clientSecret!==null,Y=$.privateKey!==void 0&&$.privateKey!==null;return L&&!R&&!Y&&!U&&!D}function Z$(S){if(S===null||typeof S!=="object"||Array.isArray(S))return!1;let $=S;return"clientId"in $||"jwksUri"in $||"workloadId"in $}function g$(S){if(S===null||typeof S!=="object"||Array.isArray(S))return!1;let $=S;if(Z$($))return!1;let L=Object.entries($);if(L.length===0)return!1;return L.every(([,R])=>Z$(R))}function s$(S){if(S===null||typeof S!=="object"||Array.isArray(S))return!1;let $=S;if("incoming"in $||"outgoing"in $){if($.incoming!==void 0&&(typeof $.incoming!=="object"||$.incoming===null))return!1;if($.outgoing!==void 0&&(typeof $.outgoing!=="object"||$.outgoing===null||Array.isArray($.outgoing)))return!1;return!0}return!1}function US(S,$,L,R){if(!L&&!R)return;if(L&&s$(L)){let z=L.incoming,G=z?{...z,...R,jwksUri:z.jwksUri,issuer:z.issuer}:R;if(!G||!G.tokenUrl&&!G.jwksUri)$.warn("Workload vault config has incoming/outgoing but no server config (incoming or framework) with tokenUrl/jwksUri; workload module handler will be unavailable.");let N=G&&(G.tokenUrl||G.jwksUri)?US(S,$,z??void 0,R):void 0,F=Object.entries(L.outgoing??{}),J={};for(let[K,_]of F){let Z=US(S,$,_,void 0);if(Z)J[K]=Z}if(!N&&Object.keys(J).length===0)return;return{...N?.config??{},getToken:async(K,_)=>{if(_?.client){let j=J[_.client];if(!j)throw Error(`Unknown workload client: ${_.client}`);return j.getToken(K)}if(N)return N.getToken(K);let Z=Object.keys(J);if(Z.length>1)throw Error(`Multiple named clients are configured, but no client was specified. Available clients: ${Z.join(", ")}`);if(Z.length===1)return J[Z[0]].getToken(K);throw Error("No workload config available; specify options.client")},refreshToken:async(K)=>{if(!N)throw Error("No default workload config");return N.refreshToken(K)},generateJWTAssertion:async(K)=>{if(!N)throw Error("No default workload config");return N.generateJWTAssertion(K)},revokeToken:async(K)=>{if(!N)throw Error("No default workload config");return N.revokeToken(K)},validateToken:async(K)=>{if(!N)throw Error("No default workload config");return N.validateToken(K)},getWorkloadIdentity:async(K)=>{if(!N)return;return N.getWorkloadIdentity(K)},parseJWT:async(K)=>{if(!N)throw Error("No default workload config");return N.parseJWT(K)},handler:async(K)=>{if(!N)return new Response("Not Found",{status:404});return N.handler(K)}}}if(L&&g$(L)){let z=L.default,G=z?{...z,...R,jwksUri:z.jwksUri,issuer:z.issuer}:R;if(!G||!G.tokenUrl&&!G.jwksUri)$.warn('Workload vault config is a clients map but no server config (workload["default"] or framework workload) with tokenUrl/jwksUri; workload module handler will be unavailable.');let N=G&&(G.tokenUrl||G.jwksUri)?US(S,$,z??void 0,R):void 0,F=Object.entries(L).filter(([K])=>K!=="default"),J={};for(let[K,_]of F){let Z=US(S,$,_,void 0);if(Z)J[K]=Z}if(!N&&Object.keys(J).length===0)return;return{...N?.config??{},getToken:async(K,_)=>{if(_?.client){let j=J[_.client];if(!j)throw Error(`Unknown workload client: ${_.client}`);return j.getToken(K)}if(N)return N.getToken(K);let Z=Object.keys(J);if(Z.length>1)throw Error(`Multiple named clients are configured, but no client was specified. Available clients: ${Z.join(", ")}`);if(Z.length===1)return J[Z[0]].getToken(K);throw Error("No workload config available; specify options.client")},refreshToken:async(K)=>{if(!N)throw Error("No default workload config");return N.refreshToken(K)},generateJWTAssertion:async(K)=>{if(!N)throw Error("No default workload config");return N.generateJWTAssertion(K)},revokeToken:async(K)=>{if(!N)throw Error("No default workload config");return N.revokeToken(K)},validateToken:async(K)=>{if(!N)throw Error("No default workload config");return N.validateToken(K)},getWorkloadIdentity:async(K)=>{if(!N)return;return N.getWorkloadIdentity(K)},parseJWT:async(K)=>{if(!N)throw Error("No default workload config");return N.parseJWT(K)},handler:async(K)=>{if(!N)return new Response("Not Found",{status:404});return N.handler(K)}}}let U=L,D=R?.tokenUrl,Y=D?.startsWith("/")?D:void 0,B=U?.idpTokenUrl??R?.idpTokenUrl??(U?.tokenUrl&&(U.tokenUrl.startsWith("http://")||U.tokenUrl.startsWith("https://"))?U.tokenUrl:void 0),M={...U,...R,tokenUrl:Y??R?.tokenUrl??U?.tokenUrl,idpTokenUrl:B,jwksUri:U?.jwksUri,issuer:U?.issuer};M._handlerTokenUrl=Y;let X,Q=M,H=l(M),A=e(M),y=uS(M);if(!H&&!A&&!y){if(!U||Object.keys(U).length===0)return;throw $.error("WorkloadConfig validation failed. Config:",{keys:Object.keys(M),clientId:Q.clientId,clientSecret:Q.clientSecret?"[REDACTED]":void 0,workloadId:Q.workloadId,privateKey:Q.privateKey?"[REDACTED]":void 0,jwksUri:Q.jwksUri,tokenUrl:Q.tokenUrl,idpTokenUrl:Q.idpTokenUrl,fromVaultKeys:U?Object.keys(U):[],fromCodeKeys:R?Object.keys(R):[]}),Error("Invalid WorkloadConfig: must provide the correct config for one of the following modes: JWT Bearer Grant, OAuth2 Client Credentials, or Server-Only")}if(H)X={...M,tokenUrl:M.tokenUrl,idpTokenUrl:r(M.idpTokenUrl,"Missing 'idpTokenUrl' from Workload Config"),workloadId:r(M.workloadId,"Missing 'workloadId' from Workload Config"),privateKey:r(M.privateKey,"Missing 'privateKey' from Workload Config"),audience:r(M.audience,"Missing 'audience' from Workload Config"),scope:M.scope??"",algorithm:M.algorithm??"RS256",tokenLifetime:M.tokenLifetime??300,refreshThreshold:M.refreshThreshold??60,autoRefresh:M.autoRefresh!==void 0?M.autoRefresh:!0,tokenStore:M.tokenStore??new RS};else if(e(M))X={...M,tokenUrl:M.tokenUrl,idpTokenUrl:r(M.idpTokenUrl,"Missing 'idpTokenUrl' from Workload Config"),clientId:r(M.clientId,"Missing 'clientId' from Workload Config"),clientSecret:r(M.clientSecret,"Missing 'clientSecret' from Workload Config"),scope:M.scope??"",tokenLifetime:M.tokenLifetime??300,refreshThreshold:M.refreshThreshold??60,autoRefresh:M.autoRefresh!==void 0?M.autoRefresh:!0,tokenStore:M.tokenStore??new RS};else if(uS(M))X=M;function f(){let z=new Uint8Array(16);return crypto.getRandomValues(z),Array.from(z,(G)=>G.toString(16).padStart(2,"0")).join("")}function E(z){let G;if(typeof z==="string")G=btoa(z);else G=btoa(String.fromCharCode(...z));return G.replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function w(z){let G=z.replace(/-/g,"+").replace(/_/g,"/");while(G.length%4)G+="=";return atob(G)}function q(z){if(z.startsWith("RS"))return{name:"RSASSA-PKCS1-v1_5",hash:z==="RS256"?"SHA-256":z==="RS384"?"SHA-384":"SHA-512"};else if(z.startsWith("ES"))return{name:"ECDSA",namedCurve:z==="ES256"?"P-256":z==="ES384"?"P-384":"P-521",hash:z==="ES256"?"SHA-256":z==="ES384"?"SHA-384":"SHA-512"};throw Error(`Unsupported algorithm: ${z}`)}async function V(z,G){let N=z.replace(/-----BEGIN PRIVATE KEY-----/,"").replace(/-----END PRIVATE KEY-----/,"").replace(/\s/g,""),F=Uint8Array.from(atob(N),(I)=>I.charCodeAt(0)),J=q(G);return crypto.subtle.importKey("pkcs8",F,J,!1,["sign"])}async function k(z,G,N){let F=await V(G,N),I=new TextEncoder().encode(z),K=q(N),_=await crypto.subtle.sign(K,F,I);return E(new Uint8Array(_))}async function g(z,G=3,N=1000,F=30000){let J=Error("Placeholder Error");for(let I=0;I<=G;I++)try{return await z()}catch(K){if(J=K instanceof Error?K:Error(String(K)),J.message.includes("400")||J.message.includes("401")||J.message.includes("403")||J.message.includes("404"))throw J;if(I<G){let _=Math.min(N*2**I,F),Z=Math.random()*_*0.1;await new Promise((j)=>setTimeout(j,_+Z))}}throw J}async function t(z){if(!l(X))throw Error("generateJWTAssertion is only available in JWT Bearer Grant mode");let G=X,N=Math.floor(Date.now()/1000),F={iss:G.workloadId,sub:G.workloadId,aud:G.audience??"",exp:N+G.tokenLifetime,iat:N,jti:f(),scope:z??G.scope},J={alg:G.algorithm,typ:"JWT",kid:G.keyId},I=E(JSON.stringify(J)),K=E(JSON.stringify(F)),_=`${I}.${K}`,Z=await k(_,G.privateKey,G.algorithm);return`${_}.${Z}`}async function s(z){if(!l(X))throw Error("generateJWTAssertion is only available in JWT Bearer Grant mode");let G=X;return g(async()=>{let N=G.idpTokenUrl,F=await t(z),J=new URLSearchParams;if(J.append("grant_type","urn:ietf:params:oauth:grant-type:jwt-bearer"),J.append("assertion",F),z)J.append("scope",z);let I=await fetch(N,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:J.toString()}),K=await I.json();if(!I.ok)throw $.error("Token acquisition error:",K),Error(`Token acquisition failed: ${K.error||I.statusText} - ${K.error_description||""}`.trim());let _=await S.tokenResponse["~standard"].validate(K);if(_.issues)throw $.error("Token response validation failed:",_.issues),Error(`Token response validation failed: ${_.issues.map((Z)=>Z.message).join("; ")}`);if(G.tokenStore){let Z=new Date(Date.now()+(_.value.expires_in??300)*1000),j={workload_id:G.workloadId,access_token:_.value.access_token,token_type:_.value.token_type,scope:_.value.scope,expires_at:Z,created_at:new Date,refresh_token:_.value.refresh_token};await G.tokenStore.set(j)}return _.value})}async function p(z){if(!e(X))throw Error("acquireTokenClientCredentials is only available in OAuth2 Client Credentials mode");let G=X;return g(async()=>{let N=G.idpTokenUrl,F=new URLSearchParams;if(F.append("grant_type","client_credentials"),F.append("client_id",G.clientId),F.append("client_secret",G.clientSecret),z)F.append("scope",z);let J=await fetch(N,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json"},body:F.toString()}),I=await J.json();if(!J.ok)throw $.error("Token acquisition error:",I),Error(`Token acquisition failed: ${I.error||J.statusText} - ${I.error_description||""}`.trim());let K=await S.tokenResponse["~standard"].validate(I);if(K.issues)throw $.error("Token response validation failed:",K.issues),Error(`Token response validation failed: ${K.issues.map((_)=>_.message).join("; ")}`);if(G.tokenStore){let _=new Date(Date.now()+(K.value.expires_in??300)*1000),Z={workload_id:G.clientId,access_token:K.value.access_token,token_type:K.value.token_type,scope:K.value.scope,expires_at:_,created_at:new Date,refresh_token:K.value.refresh_token};await G.tokenStore.set(Z)}return K.value})}async function DS(z){if(!l(X)&&!e(X)){let J=X;throw Error(`Acquiring tokens is only available in JWT Bearer Grant or OAuth2 Client Credentials mode. Current config: hasClientId=${!!J.clientId}, hasClientSecret=${!!J.clientSecret}, hasWorkloadId=${!!J.workloadId}, hasPrivateKey=${!!J.privateKey}, hasJwksUri=${!!J.jwksUri}`)}let G=X;z=z??G.scope;let N=l(X)?X.workloadId:X.clientId;if(G.tokenStore){let J=await G.tokenStore.get(N);if(J){let I=Date.now(),K=J.expires_at.getTime(),_=G.refreshThreshold*1000;if(I+_<K)return J.access_token;if(G.autoRefresh)try{return(l(X)?await s(z):await p(z)).access_token}catch(Z){if(I<K)return $.warn("Token refresh failed, using cached token:",Z),J.access_token;throw Z}}}return(l(X)?await s(z):await p(z)).access_token}async function P(z){if(!l(X)&&!e(X))throw Error("Refreshing tokens is only available in JWT Bearer Grant or OAuth2 Client Credentials mode");let G=X;return z=z??G.scope,l(G)?await s(z):await p(z)}async function C(z){if(!l(X)&&!e(X))throw Error("Revoking tokens is only available in JWT Bearer Grant or OAuth2 Client Credentials mode");let G=X;try{if(!X.revocationEndpoint)return;let N=new URLSearchParams;if(N.append("token",z),N.append("token_type_hint","access_token"),l(X)){let J=X;N.append("client_id",J.workloadId)}else if(e(X)){let J=X;N.append("client_id",J.clientId),N.append("client_secret",J.clientSecret)}let F=await fetch(X.revocationEndpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:N.toString()});if(!F.ok)$.warn("Token revocation failed:",F.status,F.statusText);else $.info("Token revoked successfully");if(X.tokenStore){let J;if(l(X))J=X.workloadId;else if(e(X))J=X.clientId;else return;await X.tokenStore.delete(J)}}catch(N){$.warn("Error revoking token:",N)}}async function x(){if(!X?.jwksUri)throw Error("No JWKS URI configured in Workload Config");let z=X.jwksUri,G=Y$.get(z);if(G)return G;return g(async()=>{let N=await fetch(z);if(!N.ok)throw Error("Failed to fetch JWKS");let F=await N.json();return Y$.set(z,F),F})}async function v(z){let N=(await x()).keys.find((I)=>I.kid===z);if(!N)throw Error("Public key not found");let F=l(X)?X.algorithm:"RS256",J=q(N.alg||F);return crypto.subtle.importKey("jwk",N,J,!1,["verify"])}async function b(z){try{let G=z.split(".");if(G.length!==3)throw Error("Invalid JWT");let N=JSON.parse(w(G[0])),F=JSON.parse(w(G[1])),J=await v(N.kid),I=G[2],_=new TextEncoder().encode(`${G[0]}.${G[1]}`),Z=Uint8Array.from(w(I),(d)=>d.charCodeAt(0)),j=q(N.alg);if(!await crypto.subtle.verify(j,J,Z,_))throw Error("Invalid JWT signature");let O=await S.jwtAssertionClaims["~standard"].validate(F);if(O.issues)throw $.error("JWT claims validation failed:",O.issues),Error(`JWT claims validation failed: ${O.issues.map((d)=>d.message).join("; ")}`);return O.value}catch(G){throw $.error("Error verifying JWT:",G),G}}async function u(z){if(!l(X)&&!e(X)&&!uS(X))throw Error("Validating tokens is only available in JWT Bearer Grant, OAuth2 Client Credentials, or Server-Only mode");try{let G=await b(z),N=Math.floor(Date.now()/1000);if(G.exp&&G.exp<N)return{valid:!1,error:"Token expired"};if(l(X)){if(X.audience&&G.aud!==X.audience)return{valid:!1,error:"Invalid audience"}}else if(e(X)){if(X.issuer&&G.iss!==X.issuer)return{valid:!1,error:"Invalid issuer"};if(X.audience&&G.aud!==X.audience)return{valid:!1,error:"Invalid audience"}}else{let F=X;if(F.issuer&&G.iss!==F.issuer)return{valid:!1,error:"Invalid issuer"}}return{valid:!0,claims:G,expiresAt:G.exp?new Date(G.exp*1000):void 0}}catch(G){return{valid:!1,error:G instanceof Error?G.message:String(G)}}}async function W(z){let G=z.headers.get("Authorization");if(!G||!G.startsWith("Bearer "))return;let N=G.substring(7),F=await u(N);if(!F.valid||!F.claims)return;return{workloadId:F.claims.sub,clientId:typeof F.claims.client_id==="string"?F.claims.client_id:void 0,scope:F.claims.scope,claims:F.claims}}async function m(z){if(!X)throw Error("Enterprise Standard Workload Manager not initialized");let G=new URL(z.url).pathname,N=(Z)=>{if(!Z)return;try{return new URL(Z).pathname}catch{return Z.startsWith("/")?Z:`/${Z}`}},F=X._handlerTokenUrl;if(N(F||X.tokenUrl)===G&&z.method==="GET")try{let j=new URL(z.url).searchParams.get("scope")||void 0,T=await DS(j);return new Response(JSON.stringify({access_token:T,token_type:"Bearer"}),{headers:[["Content-Type","application/json"]]})}catch(Z){return $.error("Error in token endpoint:",Z),new Response(JSON.stringify({error:Z instanceof Error?Z.message:"Internal server error"}),{status:500,headers:[["Content-Type","application/json"]]})}if(N(X.validateUrl)===G&&z.method==="POST"){let Z=z.headers.get("Authorization");if(!Z||!Z.startsWith("Bearer "))return new Response(JSON.stringify({valid:!1,error:"Missing Authorization header"}),{status:401,headers:[["Content-Type","application/json"]]});let j=Z.substring(7),T=await u(j);return new Response(JSON.stringify(T),{status:T.valid?200:401,headers:[["Content-Type","application/json"]]})}if(N(X.jwksUrl)===G&&z.method==="GET"){let Z=await x();return new Response(JSON.stringify(Z),{headers:[["Content-Type","application/json"]]})}if(N(X.refreshUrl)===G&&z.method==="POST")try{let Z=await P();return new Response(JSON.stringify(Z),{headers:[["Content-Type","application/json"]]})}catch(Z){return $.error("Error in refresh endpoint:",Z),new Response(JSON.stringify({error:Z instanceof Error?Z.message:"Internal server error"}),{status:500,headers:[["Content-Type","application/json"]]})}return new Response("Not Found",{status:404})}return{...X,getToken:DS,refreshToken:P,generateJWTAssertion:t,revokeToken:C,validateToken:u,getWorkloadIdentity:W,parseJWT:b,handler:m}}function hS(S){return S=S??"Workload authentication unavailable",new Response(JSON.stringify({error:S}),{status:503,statusText:S,headers:{"Content-Type":"application/json"}})}var VS="EnterpriseStandard instance is required. Create one with enterpriseStandard(source, config) and pass it to this function.",l$="EnterpriseStandard or Workload instance is required. Create an ES with enterpriseStandard(source, config) or pass a Workload instance.";async function p$(S,$){r($,VS);let L=$.workload;if(!L)return;return L.getWorkloadIdentity(S)}async function i$(S,$,L){r($,VS);let R=$.workload;if(!R)throw hS();return R.getToken(L,{client:S})}async function t$(S,$){r($,l$);let L="validateToken"in $&&typeof $.validateToken==="function"?$:$.workload;if(!L)return{valid:!1,error:"Workload authentication unavailable"};let R=S.headers.get("Authorization");if(!R||!R.startsWith("Bearer "))return{valid:!1,error:"Missing or invalid Authorization header"};let U=R.substring(7);return L.validateToken(U)}async function r$(S,$){r($,VS);let L=$.workload;if(!L)throw hS();return L.revokeToken(S)}async function a$(S,$){r($,VS);let L=$.workload;if(!L)throw hS();return L.handler(S)}export*from"@enterprisestandard/core";import{InMemoryTenantStore as yR,parseTenantRequest as kR,sendTenantWebhook as vR,TenantRequestError as bR,tenant as mR}from"@enterprisestandard/core";import{callback as uR,ciam as hR,getCIAMUser as dR,getRequiredSSOorCIAMUser as cR,getSSOorCIAMUser as fR,getSSOorCIAMUser as nR,getSSOUser as gR,iam as sR,initiateLogin as lR,logout as pR,logoutBackChannel as iR,sso as tR,verifyUser as rR}from"@enterprisestandard/core/server";import{setActiveSession as e$}from"@enterprisestandard/core";async function o$(S,$){let L=[];for(let[R,U]of $.entries()){if(!U.sso)continue;try{let D=await U.sso.getUser(S);if(!D)continue;L.push({clientId:R,user:D,valid:!0,expiresAt:D.sso?.expires})}catch{}}return L}async function SL(S,$,L,R={}){let U=L.get($);if(!U?.sso)return new Response(JSON.stringify({error:"Unknown tenant session"}),{status:404,headers:{"Content-Type":"application/json"}});if(await U.sso.getUser(S)){let M=e$($,{cookieName:R.activeSessionCookieName,path:R.cookiePath,secure:R.cookieSecure,sameSite:R.cookieSameSite,maxAge:R.cookieMaxAge});return new Response(JSON.stringify({success:!0}),{status:200,headers:{"Content-Type":"application/json","Set-Cookie":M}})}let Y=R.loginUrl??U.sso.loginUrl;if(!Y)return new Response(JSON.stringify({error:"Session expired"}),{status:401,headers:{"Content-Type":"application/json"}});let B=new URL(Y,S.url);if(!B.searchParams.has("clientId"))B.searchParams.set("clientId",$);return new Response(null,{status:302,headers:{Location:B.toString()}})}async function $L(S,$,L){await S.putSecret($,L)}function LL(S){let{type:$,...L}=S;return XS({type:"vault",...L})}function a(S){if(!S)return;try{return new URL(S,"http://dummy").pathname}catch{return S.startsWith("/")?S:`/${S}`}}function ZL(S,$){if(S?.sso?.redirectUri&&$.sso?.redirectUri){let L=a(S.sso.redirectUri),R=a($.sso.redirectUri);if(L!==R)throw Error(`redirectUri path in framework config must match ConfigSource redirectUri path. ConfigSource path: ${L}, framework path: ${R}`)}}function cS(S){let $={};if(!S)return $;for(let[L,R]of Object.entries(S))if(R.type==="lfv")$[L]=R;return $}function XL(S){return S[wS]}function GL(S,$){let L=cS(S.secrets),R=a($.deliveryEndpoint),U=a($.eventsEndpoint),D=a($.path);for(let Y of Object.values(L)){if(a(Y.deliveryEndpoint)!==R)continue;if(a(Y.eventsEndpoint)!==U)continue;let B=Y.path?a(Y.path):void 0;if(D&&B&&D!==B)continue;return!0}return!1}function QL(S,$){let L=XL($);if(!L)return S;if(GL(S,L))return S;let R={type:"lfv",path:L.path,lfvServerUrl:L.lfvServerUrl,clientId:L.clientId,signature:L.signature,deliveryTimeout:L.deliveryTimeout,retryInterval:L.retryInterval,warnInterval:L.warnInterval,deliveryEndpoint:L.deliveryEndpoint,eventsEndpoint:L.eventsEndpoint,verifyPublicKey:L.verifyPublicKey},U=S.secrets??{},D="LFV_BOOTSTRAP",Y=1;while(D in U)Y+=1,D=`LFV_BOOTSTRAP_${Y}`;return{...S,secrets:{...U,[D]:R}}}function zL(S,$){let L=cS(S.secrets),R=cS($.secrets);for(let[U,D]of Object.entries(R)){let Y=L[U];if(!Y)continue;let B=a(Y.deliveryEndpoint),M=a(D.deliveryEndpoint);if(B&&M&&B!==M)throw Error(`LFV deliveryEndpoint path for secrets source "${U}" in framework config must match ConfigSource path. ConfigSource path: ${B}, framework path: ${M}`);let X=a(Y.eventsEndpoint),Q=a(D.eventsEndpoint);if(X&&Q&&X!==Q)throw Error(`LFV eventsEndpoint path for secrets source "${U}" in framework config must match ConfigSource path. ConfigSource path: ${X}, framework path: ${Q}`)}}function X$(S,$){if($===void 0)return!1;return JSON.stringify(S)===JSON.stringify($)}function Q$(S,$,L,R,U){let D={logger:R,tenantId:S.tenantId,config:S,handler:async()=>new Response("Not Found",{status:404})};return D.workload=US(L.workload,R,S?.workload,$.workload),D.secrets=CS(L.secrets,R,S?.secrets,$?.secrets),D.sso=YL(L.sso,R,S?.sso,$.sso),D.iam=_L(L.iam,R,D.workload,S?.iam,$.iam),D.tenants=UL(L.tenant,R,S?.tenant,$.tenant),D.ciam=DL(L.ciam,R,S?.ciam,$.ciam,D.workload),D.handler=async(Y)=>R$(Y,D,U?.routing),D}function ML(S,$,L,R,U,D){ZL($,L),zL($,L);let Y=Q$($,L,R,U,D);S.tenantId=$.tenantId,S.config=$,S.logger=U,S.workload=Y.workload,S.secrets=Y.secrets,S.sso=Y.sso,S.iam=Y.iam,S.tenants=Y.tenants,S.ciam=Y.ciam,S.handler=Y.handler}function NL(S,$,L,R){let U=S,D=$;if(R?.beforeChange){let Y=R.beforeChange(S,$,L);if(Y?.config!==void 0)U=Y.config;if(Y?.frameworkConfig!==void 0)D=Y.frameworkConfig}return{effectiveRemoteConfig:U,effectiveFrameworkConfig:D}}function G$(S){return!!S&&typeof S==="object"&&typeof S.load==="function"}function OS(S){if(!S||typeof S!=="object")return!1;let $=S;return"beforeChange"in $||"afterChange"in $||"routing"in $}async function WR(S,$,L){let R,U,D,Y=!1;if(G$(S))R=S,U=OS($)?void 0:$,D=OS($)?$:L;else Y=!0,R=vS(),U=S,D=OS($)?$:L;if(G$(S)&&OS($)&&L)D=L;if(Y&&!process.env.ES_CONFIG_TYPE)(U?.logger??dS).warn?.("enterpriseStandard() defaulted to envConfig() with no ES_CONFIG_TYPE set. Falling back to dev config source.");if(Y&&!U)U=PS();let B=eS(U,D);U=B.config,D=B.options;let M=QL(U??{},R),X=M.validators||RL(),Q=M.logger||dS,H,A=M,y=Q$({},M,X,Q,D);function f(E){if(H!==void 0&&X$(E,H))return;let w=H,{effectiveRemoteConfig:q,effectiveFrameworkConfig:V}=NL(E,A,H,D);if(H!==void 0&&X$(q,H)&&V===A)return;let k=V.logger||dS;ML(y,q,V,X,k,D),H=q,A=V,M=V,X=V.validators??X,D?.afterChange?.(y,q,A,w)}if(y.reload=async()=>{let E=await R.load();f(E)},y.reconfigure=async(E)=>{if(E!=null)M={...M,...E},A=M,X=M.validators??X;let w=await R.load();f(w)},R.subscribe)R.subscribe((E)=>f(E));return R.load().then((E)=>f(E),(E)=>Q.warn?.("ConfigSource initial load failed",E)),y}export{$L as writeEsaConfigToVault,a$ as workloadHandler,US as workload,rR as verifyUser,ES as vaultConfig,t$ as validateWorkloadToken,mR as tenantManagement,SL as switchSession,tR as sso,vR as sendTenantWebhook,CS as secrets,r$ as revokeWorkloadToken,kR as parseTenantRequest,LL as openbaoVault,iR as logoutBackChannel,pR as logout,yS as localFileConfig,xS as lfvConfig,lR as initiateLogin,sR as iam,i$ as getWorkloadToken,p$ as getWorkload,nR as getUser,fR as getSSOorCIAMUser,gR as getSSOUser,cR as getRequiredSSOorCIAMUser,dR as getCIAMUser,HS as gcpConfig,vS as envConfig,WR as enterpriseStandard,PS as dynamicConfig,o$ as discoverSessions,IS as devConfig,hR as ciam,uR as callback,NS as azureConfig,MS as awsConfig,k$ as adaptiveFramework,bR as TenantRequestError,RS as InMemoryWorkloadTokenStore,FS as InMemoryUserStore,yR as InMemoryTenantStore,qS as InMemorySessionStore,jS as InMemoryMagicLinkStore,JS as InMemoryGroupStore};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enterprisestandard/server",
3
- "version": "0.0.8",
3
+ "version": "0.0.9-beta.20260301.1",
4
4
  "description": "Enterprise Standard Server (Node/server-only)",
5
5
  "private": false,
6
6
  "author": "enterprisestandard",
@@ -21,10 +21,10 @@
21
21
  "./package.json": "./package.json"
22
22
  },
23
23
  "dependencies": {
24
- "@enterprisestandard/core": "^0.0.8"
24
+ "@enterprisestandard/core": "0.0.9-beta.20260301.1"
25
25
  },
26
26
  "peerDependencies": {
27
- "@enterprisestandard/zod": "^0.0.8",
28
- "@enterprisestandard/valibot": "^0.0.8"
27
+ "@enterprisestandard/zod": "0.0.9-beta.20260301.1",
28
+ "@enterprisestandard/valibot": "0.0.9-beta.20260301.1"
29
29
  }
30
30
  }