@zuplo/runtime 6.59.47 → 6.59.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/out/esm/index.js CHANGED
@@ -113,7 +113,7 @@ data: ${o}
113
113
 
114
114
  `))!==-1;){let b=u.slice(0,v);if(u=u.slice(v+2),!b.includes('"usage"'))continue;let S="";for(let x of b.split(`
115
115
  `))if(x.startsWith("data: ")){S=x.slice(6);break}if(S&&S.trim()!=="[DONE]")try{let x=JSON.parse(S);if(x.usage&&x.usage.total_tokens>0){if(a){let $=x.usage;n.waitUntil((async()=>{try{let O=$.prompt_tokens||0,L=$.completion_tokens||0,_=$.total_tokens||0,z=re.getLogger(n),D=await pt(n),j=Tt(e.model,"mistral",O,L,D,z);z.info("Mistral streaming usage tracked",{userId:a.sub,promptTokens:O,completionTokens:L,totalTokens:_,model:e.model,provider:"mistral",cost:j});let C=a.configuration?.id;if(C){let T={requests:1,tokens:_,costs:j};await it.incrementMeters(C,T,n)}else n.log.warn("No configuration ID found for streaming usage metering")}catch(O){n.log.error("Error processing Mistral streaming token usage",{error:O})}})())}u="";break}}catch{}}if(u.length>8192){let b=u.lastIndexOf(`
116
- `);b>4096&&(u=u.slice(b))}},flush(){}}),[d,p]=s.body.tee();return n.waitUntil(p.pipeThrough(l).pipeTo(new WritableStream({write(){},close(){},abort(){}})).catch(m=>{n.log.warn("Background usage tracking stream error",{error:m})})),new Response(d,{status:s.status,statusText:s.statusText,headers:s.headers})}async embed(e,r){let n=He(MT,e),o=await fetch("https://api.mistral.ai/v1/embeddings",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`},body:JSON.stringify(n)});if(!o.ok){let a=await o.json();throw new Error(`Mistral API error: ${a.message||"Unknown error"}`)}return{...await o.json(),provider:"mistral"}}};var Kr=Ze("zuplo:policies:AkamaiAIFirewallPolicy"),nm=Symbol("ai-gateway-llm-input"),om=Symbol("ai-gateway-llm-output"),Qr=class t extends xe{static{i(this,"AkamaiAIFirewallPolicy")}static setLlmInput(e,r){de.set(e,nm,r)}static getLlmInput(e){return de.get(e,nm)}static setLlmOutput(e,r){de.set(e,om,r)}static getLlmOutput(e){return de.get(e,om)}static hasLlmInput(e){return de.get(e,nm)!==void 0}static hasLlmOutput(e){return de.get(e,om)!==void 0}constructor(e,r){super(e,r),w("policy.inbound.akamai-ai-firewall")}async handler(e,r){let n=Date.now(),o=re.getLogger(r);try{if(t.hasLlmInput(r)){Kr(`AkamaiAIFirewallPolicy '${this.policyName}' - checking LLM input`);let s=t.getLlmInput(r);if(s){let a=await this.checkWithAkamai(s,"input",r,o);if(a)return this.createBlockedResponse(a,"completion request")}}return r.addResponseSendingHook(async(s,a,u)=>{try{if(t.hasLlmOutput(u)){Kr(`AkamaiAIFirewallPolicy '${this.policyName}' - checking LLM output`);let c=t.getLlmOutput(u);if(c){let l=await this.checkWithAkamai(c,"output",u,o);if(l)return this.createBlockedResponse(l,"completion response")}}return s}catch(c){return o.error(c,`AkamaiAIFirewallPolicy '${this.policyName}' - Failed to check LLM output`),s}}),e}catch(s){return o.error(s,`AkamaiAIFirewallPolicy '${this.policyName}' - Error in handler`),e}finally{let s=Date.now()-n;Kr(`AkamaiAIFirewallPolicy '${this.policyName}' - latency ${s}ms`)}}async checkWithAkamai(e,r,n,o){try{let s=`https://aisec.akamai.com/fai/v1/fai-configurations/${this.options.configurationId}/detect`,a=e.text;if(!a)return Kr(`AkamaiAIFirewallPolicy '${this.policyName}' - no text content to analyze for ${r}`),null;let u={clientRequestId:n.requestId};this.options.applicationId&&(u.userApplicationId=this.options.applicationId),r==="input"?u.llmInput=a:u.llmOutput=a;let c=new Headers({"Content-Type":"application/json","Fai-Api-Key":this.options["api-key"]});Kr(`AkamaiAIFirewallPolicy '${this.policyName}' - calling Akamai API for ${r}`);let l=await fetch(s,{method:"POST",headers:c,body:JSON.stringify(u)});if(!l.ok)throw new ue(`Akamai API call failed: ${l.status} ${l.statusText}`);let d=await l.json();return Kr(`AkamaiAIFirewallPolicy '${this.policyName}' - Akamai response: overall risk ${d.overallRiskScore}, rules triggered: ${d.rulesTriggered.length}`),d.rulesTriggered.find(m=>m.action==="deny")||null}catch(s){return o.error(s,`AkamaiAIFirewallPolicy '${this.policyName}' - Failed to check with Akamai for ${r}`),null}}createBlockedResponse(e,r){let n={error:{message:`Request blocked by AI Firewall during ${r}. ${e.message} (Rule: ${e.ruleId})`,code:e.ruleId}};return new Response(JSON.stringify(n),{status:400,headers:{"Content-Type":"application/json"}})}};var Co=new Map;Co.set("openai",new Hs);Co.set("anthropic",new Bs);Co.set("google",new Gs);Co.set("mistral",new Vs);function zT(t){return Se[t]}i(zT,"getApiKey");function Et(t,e,r){let o={error:{message:e,type:r||(t===400?"invalid_request_error":"api_error"),code:t===400?"bad_request":"internal_error"}};return new Response(JSON.stringify(o),{status:t,headers:{"Content-Type":"application/json"}})}i(Et,"createErrorResponse");async function Vv(t,e,r,n,o,s=!1,a){if(t.method!=="POST")return Et(405,"Only POST method is allowed");let u;if(a)u=a;else try{u=await t.json()}catch{return Et(400,"Invalid JSON body")}let c=o(u);if(c)return Et(400,c);try{let l=t.user;if(!l?.configuration)throw new y("No configuration found in request.user. Ensure ai-gateway-auth-inbound policy runs first.");let d=l.configuration.models[r];if(!d||d.length===0)return Et(400,`No ${r==="completions"?"chat completions":"embeddings"} models configured for this user`,"invalid_request_error");let p=d[0],m=Co.get(p.provider.toLowerCase());if(!m)throw new y(`Provider '${p.provider}' not found in registry`);let g=await pt(e);if(!Dv(p.model,p.provider,r,g)){let b=Zv(p.provider,r,g),S=r==="completions"?"chat completions":"embeddings";return Et(500,`Model '${p.model}' is not supported by provider '${p.provider}' for ${S}. Supported models: ${b.join(", ")||"none"}`,"api_error")}u.model=p.model,e.custom.userContext=l,e.custom.modelConfig=p,e.log.info("Provider selected",{providerName:m.name,model:u.model});let h=zT(p.environmentVariable);if(!h)throw new y(`Missing API key for environment variable: ${p.environmentVariable}`);let v=await n(m,u,h,e);if(!v)return Et(500,`Provider ${m.name} does not support this operation`,"api_error");if(s&&v instanceof Response)return v;if(!s&&r==="completions"&&l?.configuration?.policies?.["akamai-ai-firewall"]?.enabled){let x=v?.choices;if(x&&Array.isArray(x)){let $=x.map(O=>O.message?.content).filter(O=>typeof O=="string").join(" ");$&&Qr.setLlmOutput(e,{text:$})}}return new Response(JSON.stringify(v),{status:200,headers:{"Content-Type":"application/json"}})}catch(l){e.log.error("Error processing LLM request:",l);let d=l instanceof Error?l.message:"Unknown error";return Et(500,d)}}i(Vv,"handleLlmRequest");async function UT(t,e){let r;try{r=await t.clone().json()}catch{return Et(400,"Invalid JSON body")}let n=r.stream===!0;n&&(e.custom.streamingUsageHandled=!0);let s=t.user?.configuration?.policies?.["akamai-ai-firewall"];if(s?.enabled){let a=r.messages.map(u=>u.content).filter(u=>typeof u=="string").join(" ");if(a){Qr.setLlmInput(e,{text:a});let c=await new Qr({configurationId:s.configurationId,"api-key":s["api-key"],applicationId:s.applicationId},"akamai-ai-firewall").handler(t,e);if(c instanceof Response)return c}}return Vv(t,e,"completions",n?async(a,u,c,l)=>{if(!a.chatCompleteStream)throw new Error(`Provider '${a.name}' does not support streaming`);return await a.chatCompleteStream(u,c,l)}:(a,u,c)=>a.chatComplete?.(u,c),a=>{let u=a;return!u.messages||!Array.isArray(u.messages)?"Missing or invalid field: messages must be an array":null},n,r)}i(UT,"handleChatCompletions");async function DT(t,e){return Vv(t,e,"embeddings",(r,n,o)=>r.embed?.(n,o),r=>r.input?null:"Missing required field: input")}i(DT,"handleEmbeddings");async function Jv(t,e){let r=Date.now(),o=new URL(t.url).pathname;try{let s;switch(o){case"/v1/chat/completions":s=await UT(t,e);break;case"/v1/embeddings":s=await DT(t,e);break;default:return Et(404,"Endpoint not found")}let a=Date.now()-r;e.log.info("LLM Translation Layer request completed",{elapsedMs:a,path:o,status:s.status});let u=t.user,c=u?.configuration?.models?.completions?.[0];return s.status===200&&c&&e.analyticsContext.addAnalyticsEvent(a,Qe.AI_GATEWAY_LATENCY_HISTOGRAM,{model:c.model,provider:c.provider,configId:u.configuration.id}),s}catch(s){let a=Date.now()-r;return e.log.error("LLM Translation Layer internal error",{elapsedMs:a,path:o,error:s}),Et(500,"Internal server error")}}i(Jv,"handleLlmTranslationRequest");async function ZT(t,e){return w("handler.ai-gateway"),Jv(t,e)}i(ZT,"aiGatewayHandler");var $o=class extends Ee{static{i(this,"OAuthProtectedResourcePlugin")}options;constructor(e){super(),this.options=e}createOauthProtectedResourceHandler(){return async(e,r)=>{let n=new URL(e.url),o=e.params.resourcePath,a={resource:o?`${n.origin}/${o}`:n.origin,authorization_servers:this.options.authorizationServers,resource_name:this.options.resourceName};return new Response(JSON.stringify(a),{headers:{"Content-Type":"application/json"}})}}registerRoutes(e){let{router:r}=e;r.addPluginRoute({methods:["GET"],path:"/.well-known/oauth-protected-resource/:resourcePath*",handler:this.createOauthProtectedResourceHandler(),corsPolicy:"anything-goes",processors:[Er]})}};var im=class extends Ae{constructor(r){super();this.options=r}static{i(this,"DynaTraceLoggingPlugin")}getTransport(){return new sm(this.options)}},sm=class{static{i(this,"DynaTraceTransport")}constructor(e){w("logging.dynatrace"),this.#e=e.url,this.#t=e.apiToken,this.#r=R.instance.loggingEnvironmentType,this.#o=R.instance.loggingEnvironmentStage,this.#n=R.instance.deploymentName,this.#i=e.fields??{}}#e;#t;#n;#r;#o;#i;log(e,r){e.messages.forEach(n=>{let o=Object.assign({timestamp:new Date().toISOString(),message:Ye(n),severity:e.level,"log.source":e.logSource,requestId:e.requestId,"custom.atomicCounter":e.vectorClock,"custom.environment":this.#n,"custom.environmentStage":this.#o,"custom.environmentType":this.#r,"custom.loggingId":e.loggingId,"custom.rayId":e.rayId===null?void 0:e.rayId},this.#i);this.batcher.enqueue(o)}),r.waitUntil(this.batcher.waitUntilFlushed())}#s=i(async e=>{if(e.length!==0)try{let r=await W.fetch(this.#e,{method:"POST",body:JSON.stringify(e),headers:{"content-type":"application/json; charset=utf-8",authorization:`Api-Token ${this.#t}`}});r.ok||await fe({level:"error",messages:[`Failed to send logs to Dynatrace: ${r.status} - ${r.statusText}`]},r)}catch{await fe({level:"error",messages:["Failed to connect to Dynatrace logging service. Check that the URL is correct."]})}},"#dispatchFunction");batcher=new ce("dyna-trace-log-transport",10,this.#s)};var am=class extends Ae{constructor(r){super();this.options=r}static{i(this,"NewRelicLoggingPlugin")}getTransport(){return new um(this.options)}},um=class{static{i(this,"NewRelicTransport")}constructor(e){w("logging.newrelic"),this.#e=e.url??"https://log-api.newrelic.com/log/v1",this.#t=e.apiKey,this.#r=R.instance.loggingEnvironmentType,this.#o=R.instance.loggingEnvironmentStage,this.#n=R.instance.deploymentName,this.#i=e.fields??{},this.#s=e.service??"Zuplo"}#e;#t;#n;#r;#o;#i;#s;log(e,r){e.messages.forEach(n=>{let o=Object.assign({message:Ye(n),level:e.level,timestamp:Date.now(),service:this.#s,request_id:e.requestId,atomic_counter:e.vectorClock,environment:this.#n,environment_stage:this.#o,environment_type:this.#r,logging_id:e.loggingId,ray_id:e.rayId===null?void 0:e.rayId,log_source:e.logSource},this.#i);this.batcher.enqueue(o)}),r.waitUntil(this.batcher.waitUntilFlushed())}#u=i(async e=>{if(e.length!==0)try{let r=await W.fetch(this.#e,{method:"POST",body:JSON.stringify(e),headers:{"Content-Type":"application/json","Api-Key":this.#t}});r.ok||await fe({level:"error",messages:[`Failed to send logs to New Relic: ${r.status} - ${r.statusText}`]},r)}catch{await fe({level:"error",messages:["Failed to connect to New Relic logging service. Check that the URL is correct."]})}},"#dispatchFunction");batcher=new ce("new-relic-log-transport",10,this.#u)};var cm=class extends Ae{constructor(r){super();this.options=r}static{i(this,"LokiLoggingPlugin")}getTransport(){return new dm(this.options)}},lm=class{static{i(this,"LokiStream")}constructor(e,r,n,o,s,a){this.level=e,this.environment=r,this.environmentType=n,this.environmentStage=o,this.requestId=a,this.job=s}job;level;environment;environmentType;environmentStage;requestId;equals=i(e=>this.level===e.level&&this.requestId===e.requestId,"equals")};function jT(t,e){return btoa(`${t}:${e}`)}i(jT,"createBasicDigest");var dm=class{static{i(this,"LokiTransport")}constructor(e){w("logging.loki"),this.#n=e.url,this.#r=jT(e.username,e.password),this.#i=R.instance.loggingEnvironmentType,this.#s=R.instance.loggingEnvironmentStage,this.#o=R.instance.deploymentName,this.#e=e.version??1,this.#t=e.job??"zuplo",this.#u=e.fields??{}}#e;#t;#n;#r;#o;#i;#s;#u;log(e,r){let n=new lm(e.level,this.#o,this.#i,this.#s,this.#t,this.#e===1?e.requestId:void 0);e.messages.forEach(o=>{let s=Object.assign({stream:n,requestId:e.requestId,rayId:e.rayId,atomicCounter:e.vectorClock,message:Ye(o),nanoSecondEpoch:`${e.timestamp.getTime()}000000`},this.#u);this.batcher.enqueue(s)}),r.waitUntil(this.batcher.waitUntilFlushed())}#c=i(e=>{let r={streams:[]};return e.forEach(n=>{let o=r.streams.find(s=>s.stream.equals(n.stream));o||(o={stream:n.stream,values:[]},r.streams.push(o)),o.values.push(this.#e>1?[n.nanoSecondEpoch,n.message,{requestId:n.requestId,rayId:n.rayId,atomicCounter:JSON.stringify(n.atomicCounter)}]:[n.nanoSecondEpoch,n.message])}),r},"#convertToLokiStreamsBatch");#l=i(async e=>{if(e.length===0)return;let r=this.#c(e);try{let n=await W.fetch(this.#n,{method:"POST",body:JSON.stringify(r),headers:{"content-type":"application/json",authorization:`Basic ${this.#r}`}});n.ok||await fe({level:"error",messages:[`Failed to send logs to Loki: ${n.status} - ${n.statusText}`]},n)}catch{await fe({level:"error",messages:["Failed to connect to Loki logging service. Check that the URL is correct."]})}},"#dispatchFunction");batcher=new ce("loki-log-transport",10,this.#l)};var pm=class extends Ae{constructor(r){super();this.options=r}static{i(this,"SumoLogicLoggingPlugin")}getTransport(){return new mm(this.options)}},mm=class{static{i(this,"SumoLogicTransport")}constructor(e){w("logging.sumologic"),this.#e=e.url,this.#o=e.category,this.#i=e.name,this.#n=R.instance.loggingEnvironmentType,this.#r=R.instance.loggingEnvironmentStage,this.#t=R.instance.deploymentName,this.#s=e.fields??{}}#e;#t;#n;#r;#o;#i;#s;log(e,r){e.messages.forEach(n=>{let o=Object.assign({timestamp:new Date().toISOString(),message:Ye(n),severity:e.level,source:e.logSource,requestId:e.requestId,environment:this.#t,environmentType:this.#n,environmentStage:this.#r,rayId:e.rayId===null?void 0:e.rayId},this.#s);this.batcher.enqueue(o)}),r.waitUntil(this.batcher.waitUntilFlushed())}#u=i(async e=>{if(e.length===0)return;let r=e.map(o=>JSON.stringify(o)).join(`
116
+ `);b>4096&&(u=u.slice(b))}},flush(){}}),[d,p]=s.body.tee();return n.waitUntil(p.pipeThrough(l).pipeTo(new WritableStream({write(){},close(){},abort(){}})).catch(m=>{n.log.warn("Background usage tracking stream error",{error:m})})),new Response(d,{status:s.status,statusText:s.statusText,headers:s.headers})}async embed(e,r){let n=He(MT,e),o=await fetch("https://api.mistral.ai/v1/embeddings",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r}`},body:JSON.stringify(n)});if(!o.ok){let a=await o.json();throw new Error(`Mistral API error: ${a.message||"Unknown error"}`)}return{...await o.json(),provider:"mistral"}}};var Kr=Ze("zuplo:policies:AkamaiAIFirewallPolicy"),nm=Symbol("ai-gateway-llm-input"),om=Symbol("ai-gateway-llm-output"),Qr=class t extends xe{static{i(this,"AkamaiAIFirewallPolicy")}static setLlmInput(e,r){de.set(e,nm,r)}static getLlmInput(e){return de.get(e,nm)}static setLlmOutput(e,r){de.set(e,om,r)}static getLlmOutput(e){return de.get(e,om)}static hasLlmInput(e){return de.get(e,nm)!==void 0}static hasLlmOutput(e){return de.get(e,om)!==void 0}constructor(e,r){super(e,r),w("policy.inbound.akamai-ai-firewall")}async handler(e,r){let n=Date.now(),o=re.getLogger(r);try{if(t.hasLlmInput(r)){Kr(`AkamaiAIFirewallPolicy '${this.policyName}' - checking LLM input`);let s=t.getLlmInput(r);if(s){let a=await this.checkWithAkamai(s,"input",r,o);if(a)return this.createBlockedResponse(a,"completion request")}}return r.addResponseSendingHook(async(s,a,u)=>{try{if(t.hasLlmOutput(u)){Kr(`AkamaiAIFirewallPolicy '${this.policyName}' - checking LLM output`);let c=t.getLlmOutput(u);if(c){let l=await this.checkWithAkamai(c,"output",u,o);if(l)return this.createBlockedResponse(l,"completion response")}}return s}catch(c){return o.error(c,`AkamaiAIFirewallPolicy '${this.policyName}' - Failed to check LLM output`),s}}),e}catch(s){return o.error(s,`AkamaiAIFirewallPolicy '${this.policyName}' - Error in handler`),e}finally{let s=Date.now()-n;Kr(`AkamaiAIFirewallPolicy '${this.policyName}' - latency ${s}ms`)}}async checkWithAkamai(e,r,n,o){try{let s=`https://aisec.akamai.com/fai/v1/fai-configurations/${this.options.configurationId}/detect`,a=e.text;if(!a)return Kr(`AkamaiAIFirewallPolicy '${this.policyName}' - no text content to analyze for ${r}`),null;let u={clientRequestId:n.requestId};this.options.applicationId&&(u.userApplicationId=this.options.applicationId),r==="input"?u.llmInput=a:u.llmOutput=a;let c=new Headers({"Content-Type":"application/json","Fai-Api-Key":this.options["api-key"]});Kr(`AkamaiAIFirewallPolicy '${this.policyName}' - calling Akamai API for ${r}`);let l=await fetch(s,{method:"POST",headers:c,body:JSON.stringify(u)});if(!l.ok)throw new ue(`Akamai API call failed: ${l.status} ${l.statusText}`);let d=await l.json();return Kr(`AkamaiAIFirewallPolicy '${this.policyName}' - Akamai response: overall risk ${d.overallRiskScore}, rules triggered: ${d.rulesTriggered.length}`),d.rulesTriggered.find(m=>m.action==="deny")||null}catch(s){return o.error(s,`AkamaiAIFirewallPolicy '${this.policyName}' - Failed to check with Akamai for ${r}`),null}}createBlockedResponse(e,r){let n={error:{message:`Request blocked by AI Firewall during ${r}. ${e.message} (Rule: ${e.ruleId})`,code:e.ruleId}};return new Response(JSON.stringify(n),{status:400,headers:{"Content-Type":"application/json"}})}};var Co=new Map;Co.set("openai",new Hs);Co.set("anthropic",new Bs);Co.set("google",new Gs);Co.set("mistral",new Vs);function zT(t){return Se[t]}i(zT,"getApiKey");function Et(t,e,r){let o={error:{message:e,type:r||(t===400?"invalid_request_error":"api_error"),code:t===400?"bad_request":"internal_error"}};return new Response(JSON.stringify(o),{status:t,headers:{"Content-Type":"application/json"}})}i(Et,"createErrorResponse");async function Vv(t,e,r,n,o,s=!1,a){if(t.method!=="POST")return Et(405,"Only POST method is allowed");let u;if(a)u=a;else try{u=await t.json()}catch{return Et(400,"Invalid JSON body")}let c=o(u);if(c)return Et(400,c);try{let l=t.user;if(!l?.configuration)throw new y("No configuration found in request.user. Ensure ai-gateway-auth-inbound policy runs first.");let d=l.configuration.models[r];if(!d||d.length===0)return Et(400,`No ${r==="completions"?"chat completions":"embeddings"} models configured for this user`,"invalid_request_error");let p=d[0],m=Co.get(p.provider.toLowerCase());if(!m)throw new y(`Provider '${p.provider}' not found in registry`);let g=await pt(e);if(!Dv(p.model,p.provider,r,g)){let b=Zv(p.provider,r,g),S=r==="completions"?"chat completions":"embeddings";return Et(500,`Model '${p.model}' is not supported by provider '${p.provider}' for ${S}. Supported models: ${b.join(", ")||"none"}`,"api_error")}u.model=p.model,e.custom.userContext=l,e.custom.modelConfig=p,e.log.info("Provider selected",{providerName:m.name,model:u.model});let h=zT(p.environmentVariable);if(!h)throw new y(`Missing API key for environment variable: ${p.environmentVariable}`);let v=await n(m,u,h,e);if(!v)return Et(500,`Provider ${m.name} does not support this operation`,"api_error");if(s&&v instanceof Response)return v;if(!s&&r==="completions"&&l?.configuration?.policies?.["akamai-ai-firewall"]?.enabled){let x=v?.choices;if(x&&Array.isArray(x)){let $=x.map(O=>O.message?.content).filter(O=>typeof O=="string").join(" ");$&&Qr.setLlmOutput(e,{text:$})}}return new Response(JSON.stringify(v),{status:200,headers:{"Content-Type":"application/json"}})}catch(l){e.log.error("Error processing LLM request:",l);let d=l instanceof Error?l.message:"Unknown error";return Et(500,d)}}i(Vv,"handleLlmRequest");async function UT(t,e){let r;try{r=await t.clone().json()}catch{return Et(400,"Invalid JSON body")}let n=r.stream===!0;n&&(e.custom.streamingUsageHandled=!0);let s=t.user?.configuration?.policies?.["akamai-ai-firewall"];if(s?.enabled&&r.messages&&Array.isArray(r.messages)){let a=r.messages.map(u=>u.content).filter(u=>typeof u=="string").join(" ");if(a){Qr.setLlmInput(e,{text:a});let c=await new Qr({configurationId:s.configurationId,"api-key":s["api-key"],applicationId:s.applicationId},"akamai-ai-firewall").handler(t,e);if(c instanceof Response)return c}}return Vv(t,e,"completions",n?async(a,u,c,l)=>{if(!a.chatCompleteStream)throw new Error(`Provider '${a.name}' does not support streaming`);return await a.chatCompleteStream(u,c,l)}:(a,u,c)=>a.chatComplete?.(u,c),a=>{let u=a;return!u.messages||!Array.isArray(u.messages)?"Missing or invalid field: messages must be an array":null},n,r)}i(UT,"handleChatCompletions");async function DT(t,e){return Vv(t,e,"embeddings",(r,n,o)=>r.embed?.(n,o),r=>r.input?null:"Missing required field: input")}i(DT,"handleEmbeddings");async function Jv(t,e){let r=Date.now(),o=new URL(t.url).pathname;try{let s;switch(o){case"/v1/chat/completions":s=await UT(t,e);break;case"/v1/embeddings":s=await DT(t,e);break;default:return Et(404,"Endpoint not found")}let a=Date.now()-r;e.log.info("LLM Translation Layer request completed",{elapsedMs:a,path:o,status:s.status});let u=t.user,c=u?.configuration?.models?.completions?.[0];return s.status===200&&c&&e.analyticsContext.addAnalyticsEvent(a,Qe.AI_GATEWAY_LATENCY_HISTOGRAM,{model:c.model,provider:c.provider,configId:u.configuration.id}),s}catch(s){let a=Date.now()-r;return e.log.error("LLM Translation Layer internal error",{elapsedMs:a,path:o,error:s}),Et(500,"Internal server error")}}i(Jv,"handleLlmTranslationRequest");async function ZT(t,e){return w("handler.ai-gateway"),Jv(t,e)}i(ZT,"aiGatewayHandler");var $o=class extends Ee{static{i(this,"OAuthProtectedResourcePlugin")}options;constructor(e){super(),this.options=e}createOauthProtectedResourceHandler(){return async(e,r)=>{let n=new URL(e.url),o=e.params.resourcePath,a={resource:o?`${n.origin}/${o}`:n.origin,authorization_servers:this.options.authorizationServers,resource_name:this.options.resourceName};return new Response(JSON.stringify(a),{headers:{"Content-Type":"application/json"}})}}registerRoutes(e){let{router:r}=e;r.addPluginRoute({methods:["GET"],path:"/.well-known/oauth-protected-resource/:resourcePath*",handler:this.createOauthProtectedResourceHandler(),corsPolicy:"anything-goes",processors:[Er]})}};var im=class extends Ae{constructor(r){super();this.options=r}static{i(this,"DynaTraceLoggingPlugin")}getTransport(){return new sm(this.options)}},sm=class{static{i(this,"DynaTraceTransport")}constructor(e){w("logging.dynatrace"),this.#e=e.url,this.#t=e.apiToken,this.#r=R.instance.loggingEnvironmentType,this.#o=R.instance.loggingEnvironmentStage,this.#n=R.instance.deploymentName,this.#i=e.fields??{}}#e;#t;#n;#r;#o;#i;log(e,r){e.messages.forEach(n=>{let o=Object.assign({timestamp:new Date().toISOString(),message:Ye(n),severity:e.level,"log.source":e.logSource,requestId:e.requestId,"custom.atomicCounter":e.vectorClock,"custom.environment":this.#n,"custom.environmentStage":this.#o,"custom.environmentType":this.#r,"custom.loggingId":e.loggingId,"custom.rayId":e.rayId===null?void 0:e.rayId},this.#i);this.batcher.enqueue(o)}),r.waitUntil(this.batcher.waitUntilFlushed())}#s=i(async e=>{if(e.length!==0)try{let r=await W.fetch(this.#e,{method:"POST",body:JSON.stringify(e),headers:{"content-type":"application/json; charset=utf-8",authorization:`Api-Token ${this.#t}`}});r.ok||await fe({level:"error",messages:[`Failed to send logs to Dynatrace: ${r.status} - ${r.statusText}`]},r)}catch{await fe({level:"error",messages:["Failed to connect to Dynatrace logging service. Check that the URL is correct."]})}},"#dispatchFunction");batcher=new ce("dyna-trace-log-transport",10,this.#s)};var am=class extends Ae{constructor(r){super();this.options=r}static{i(this,"NewRelicLoggingPlugin")}getTransport(){return new um(this.options)}},um=class{static{i(this,"NewRelicTransport")}constructor(e){w("logging.newrelic"),this.#e=e.url??"https://log-api.newrelic.com/log/v1",this.#t=e.apiKey,this.#r=R.instance.loggingEnvironmentType,this.#o=R.instance.loggingEnvironmentStage,this.#n=R.instance.deploymentName,this.#i=e.fields??{},this.#s=e.service??"Zuplo"}#e;#t;#n;#r;#o;#i;#s;log(e,r){e.messages.forEach(n=>{let o=Object.assign({message:Ye(n),level:e.level,timestamp:Date.now(),service:this.#s,request_id:e.requestId,atomic_counter:e.vectorClock,environment:this.#n,environment_stage:this.#o,environment_type:this.#r,logging_id:e.loggingId,ray_id:e.rayId===null?void 0:e.rayId,log_source:e.logSource},this.#i);this.batcher.enqueue(o)}),r.waitUntil(this.batcher.waitUntilFlushed())}#u=i(async e=>{if(e.length!==0)try{let r=await W.fetch(this.#e,{method:"POST",body:JSON.stringify(e),headers:{"Content-Type":"application/json","Api-Key":this.#t}});r.ok||await fe({level:"error",messages:[`Failed to send logs to New Relic: ${r.status} - ${r.statusText}`]},r)}catch{await fe({level:"error",messages:["Failed to connect to New Relic logging service. Check that the URL is correct."]})}},"#dispatchFunction");batcher=new ce("new-relic-log-transport",10,this.#u)};var cm=class extends Ae{constructor(r){super();this.options=r}static{i(this,"LokiLoggingPlugin")}getTransport(){return new dm(this.options)}},lm=class{static{i(this,"LokiStream")}constructor(e,r,n,o,s,a){this.level=e,this.environment=r,this.environmentType=n,this.environmentStage=o,this.requestId=a,this.job=s}job;level;environment;environmentType;environmentStage;requestId;equals=i(e=>this.level===e.level&&this.requestId===e.requestId,"equals")};function jT(t,e){return btoa(`${t}:${e}`)}i(jT,"createBasicDigest");var dm=class{static{i(this,"LokiTransport")}constructor(e){w("logging.loki"),this.#n=e.url,this.#r=jT(e.username,e.password),this.#i=R.instance.loggingEnvironmentType,this.#s=R.instance.loggingEnvironmentStage,this.#o=R.instance.deploymentName,this.#e=e.version??1,this.#t=e.job??"zuplo",this.#u=e.fields??{}}#e;#t;#n;#r;#o;#i;#s;#u;log(e,r){let n=new lm(e.level,this.#o,this.#i,this.#s,this.#t,this.#e===1?e.requestId:void 0);e.messages.forEach(o=>{let s=Object.assign({stream:n,requestId:e.requestId,rayId:e.rayId,atomicCounter:e.vectorClock,message:Ye(o),nanoSecondEpoch:`${e.timestamp.getTime()}000000`},this.#u);this.batcher.enqueue(s)}),r.waitUntil(this.batcher.waitUntilFlushed())}#c=i(e=>{let r={streams:[]};return e.forEach(n=>{let o=r.streams.find(s=>s.stream.equals(n.stream));o||(o={stream:n.stream,values:[]},r.streams.push(o)),o.values.push(this.#e>1?[n.nanoSecondEpoch,n.message,{requestId:n.requestId,rayId:n.rayId,atomicCounter:JSON.stringify(n.atomicCounter)}]:[n.nanoSecondEpoch,n.message])}),r},"#convertToLokiStreamsBatch");#l=i(async e=>{if(e.length===0)return;let r=this.#c(e);try{let n=await W.fetch(this.#n,{method:"POST",body:JSON.stringify(r),headers:{"content-type":"application/json",authorization:`Basic ${this.#r}`}});n.ok||await fe({level:"error",messages:[`Failed to send logs to Loki: ${n.status} - ${n.statusText}`]},n)}catch{await fe({level:"error",messages:["Failed to connect to Loki logging service. Check that the URL is correct."]})}},"#dispatchFunction");batcher=new ce("loki-log-transport",10,this.#l)};var pm=class extends Ae{constructor(r){super();this.options=r}static{i(this,"SumoLogicLoggingPlugin")}getTransport(){return new mm(this.options)}},mm=class{static{i(this,"SumoLogicTransport")}constructor(e){w("logging.sumologic"),this.#e=e.url,this.#o=e.category,this.#i=e.name,this.#n=R.instance.loggingEnvironmentType,this.#r=R.instance.loggingEnvironmentStage,this.#t=R.instance.deploymentName,this.#s=e.fields??{}}#e;#t;#n;#r;#o;#i;#s;log(e,r){e.messages.forEach(n=>{let o=Object.assign({timestamp:new Date().toISOString(),message:Ye(n),severity:e.level,source:e.logSource,requestId:e.requestId,environment:this.#t,environmentType:this.#n,environmentStage:this.#r,rayId:e.rayId===null?void 0:e.rayId},this.#s);this.batcher.enqueue(o)}),r.waitUntil(this.batcher.waitUntilFlushed())}#u=i(async e=>{if(e.length===0)return;let r=e.map(o=>JSON.stringify(o)).join(`
117
117
  `),n=new Headers({"content-type":"application/json; charset=utf-8"});this.#i&&n.set("X-Sumo-Name",this.#i),this.#o&&n.set("X-Sumo-Category",this.#o);try{let o=await W.fetch(this.#e,{method:"POST",body:r,headers:n});o.ok||await fe({level:"error",messages:[`Failed to send logs to Sumologic: ${o.status} - ${o.statusText}`]},o)}catch{await fe({level:"error",messages:["Failed to connect to Sumologic logging service. Check that the URL is correct."]})}},"#dispatchFunction");batcher=new ce("sumo-logic-log-transport",10,this.#u)};var qT="d3a5b78f823648f5b1df4fe269d41172",fm=class extends Ae{constructor(r){super();this.options=r}static{i(this,"VMWareLogInsightLoggingPlugin")}getTransport(){return new gm(this.options)}},gm=class{static{i(this,"VMWareLogInsightTransport")}constructor(e){w("logging.vmware-loginsight");let r;try{r=new URL(e.url),r.pathname==="/"&&(r.pathname=`/api/v1/events/ingest/${e.agentId??qT}`)}catch{throw new y(`Invalid option 'url' on 'VMWareLogInsightTransport' plugin. Must be a valid URL, received '${e.url}'`)}this.#e=r.toString(),this.#r=R.instance.loggingEnvironmentType,this.#o=R.instance.loggingEnvironmentStage,this.#n=R.instance.deploymentName,this.#i=e.onMessageSending,this.#t=e.textReplacements,e.fields&&(this.#s=Object.entries(e.fields).map(([n,o])=>({name:n,content:o})))}#e;#t;#n;#r;#o;#i;#s;log(e,r){let n=this.buildEntry(e,r);this.batcher.enqueue(n),r.waitUntil(this.batcher.waitUntilFlushed())}buildEntry(e,r){let n=Kg(e.messages);this.#t?.forEach(s=>{n=n.replaceAll(s[0],s[1])});let o={timestamp:Date.now(),text:n,fields:[{name:"severity",content:e.level.toUpperCase()},{name:"request_id",content:e.requestId},{name:"environment_type",content:this.#r},{name:"environment_stage",content:this.#o},{name:"log_source",content:e.logSource},{name:"atomic_counter",content:e.vectorClock}]};return e.rayId&&o.fields.push({name:"request_ray_id",content:e.rayId}),this.#n&&o.fields.push({name:"environment",content:this.#n}),this.#s&&o.fields.push(...this.#s),r.custom&&Object.entries(r.custom).forEach(([s,a])=>{let u=Fa(a);u&&o.fields.push({name:s,content:u})}),this.#i&&(o=this.#i(o)),o}#u=i(async e=>{if(e.length!==0)try{let r=await W.fetch(this.#e,{method:"POST",body:JSON.stringify({events:e}),headers:{"content-type":"application/json; charset=utf-8"}});r.ok||await fe({level:"error",messages:[`Failed to send logs to Log Insight: ${r.status} - ${r.statusText}`]},r)}catch{await fe({level:"error",messages:["Failed to connect to Log Insight logging service. Check that the URL is correct."]})}},"#dispatchFunction");batcher=new ce("vmware-log-insights-log-transport",10,this.#u)};var hm=class extends Ae{constructor(r){super();this.options=r}static{i(this,"AWSLoggingPlugin")}getTransport(){return new ym(this.options)}},ym=class{static{i(this,"AWSLogTransport")}awsClient;environment;environmentType;environmentStage;logGroupName;logStreamName;region;fields;batcher=new ce("aws-log-transport",10,async e=>{if(e.length===0)return;let r=JSON.stringify({logGroupName:this.logGroupName,logStreamName:this.logStreamName,logEvents:e});try{let n=await this.awsClient.fetch(`https://logs.${this.region}.amazonaws.com`,{headers:{"Content-Type":"application/x-amz-json-1.1","x-amz-Target":"Logs_20140328.PutLogEvents"},body:r,aws:{accessKeyId:this.awsClient.accessKeyId,secretAccessKey:this.awsClient.secretAccessKey,service:this.awsClient.service,region:this.awsClient.region}});n.ok||await fe({level:"error",messages:[`Failed to send logs to AWS: ${n.status} - ${n.statusText}`]},n)}catch{await fe({level:"error",messages:["Failed to connect to AWS logging service. Check that the URL is correct."]})}});constructor({accessKeyId:e,logStreamName:r,logGroupName:n,secretAccessKey:o,region:s,fields:a}){w("logging.aws"),this.awsClient=new Ar({accessKeyId:e,secretAccessKey:o,service:"logs",region:s}),this.logGroupName=n,this.logStreamName=r,this.region=s,this.environmentType=R.instance.loggingEnvironmentType,this.environmentStage=R.instance.loggingEnvironmentStage,this.environment=R.instance.deploymentName,this.fields=a??{}}log(e,r){e.messages.forEach(n=>{let o={timestamp:new Date().getTime(),message:JSON.stringify(Object.assign({data:Ye(n),severity:e.level,source:e.logSource,environment:this.environment,atomicCounter:e.vectorClock,requestId:e.requestId,environmentType:this.environmentType,environmentStage:this.environmentStage,rayId:e.rayId===null?void 0:e.rayId},this.fields))};this.batcher.enqueue(o)}),r.waitUntil(this.batcher.waitUntilFlushed())}};var bm=class extends Ae{constructor(r){super();this.options=r}static{i(this,"SplunkLoggingPlugin")}getTransport(){return new vm(this.options)}},vm=class{static{i(this,"SplunkTransport")}constructor(e){w("logging.splunk"),this.#e=e.url,this.#t=e.token,this.#r=R.instance.loggingEnvironmentType,this.#o=R.instance.loggingEnvironmentStage,this.#n=R.instance.deploymentName,this.#i=e.fields??{},this.#s=e.index??"main",this.#u=e.sourcetype??"json",this.#c=e.host??"zuplo-api",this.#l=e.channel}#e;#t;#n;#r;#o;#i;#s;#u;#c;#l;log(e,r){e.messages.forEach(n=>{let s={event:{message:Ye(n),level:e.level,timestamp:new Date().toISOString(),request_id:e.requestId,atomic_counter:e.vectorClock,environment:this.#n,environment_stage:this.#o,environment_type:this.#r,logging_id:e.loggingId,ray_id:e.rayId===null?void 0:e.rayId,log_source:e.logSource,...this.#i},sourcetype:this.#u,host:this.#c,index:this.#s,time:Math.floor(Date.now()/1e3)};this.batcher.enqueue(s)}),r.waitUntil(this.batcher.waitUntilFlushed())}#a=i(async e=>{if(e.length!==0)try{for(let r of e){let n={"Content-Type":"application/json",Authorization:`Splunk ${this.#t}`};this.#l&&(n["X-Splunk-Request-Channel"]=this.#l);let o=await W.fetch(this.#e,{method:"POST",body:JSON.stringify(r),headers:n});if(!o.ok){let s=await o.text();await fe({level:"error",messages:[`Failed to send logs to Splunk: ${o.status} - ${o.statusText}`,`Response: ${s}`]},o)}}}catch(r){await fe({level:"error",messages:["Failed to connect to Splunk logging service. Check that the URL is correct.",`Error: ${r instanceof Error?r.message:String(r)}`]})}},"#dispatchFunction");batcher=new ce("splunk-log-transport",10,this.#a)};var wm=new WeakMap,FT={tags:[]},xm=class extends xt{constructor(r){super();this.options=r;w("metrics.datadog")}static{i(this,"DataDogMetricsPlugin")}getTransport(){return new Pm(this.options)}static setContext(r,n){let o=wm.get(r);o||(o=FT);let s=Object.assign({...o},n);wm.set(r,s)}},Pm=class{static{i(this,"DataDogMetricsTransport")}#e;#t;#n;#r;#o;#i=void 0;constructor(e){this.#e=e.apiKey,this.#t=e.url??"https://api.datadoghq.com/api/v2/series",this.#n=Object.assign({latency:!0,requestContentLength:!0,responseContentLength:!0},e.metrics),this.#o=e.include??{},this.#r=e.tags??[]}pushMetrics(e,r){this.#i===void 0&&(this.#i=new ce("data-dog-metrics-transport",10,this.dispatchFunction,re.getLogger(r)));let n=Math.floor(e.timestamp.getTime()/1e3),o=this.#r.concat(wm.get(r)?.tags??[]);if(this.#o.country&&o.push(`country:${e.country}`),this.#o.httpMethod&&o.push(`httpMethod:${e.method}`),this.#o.statusCode&&o.push(`statusCode:${e.statusCode}`),this.#o.path){let s=e.systemRouteName||e.routePath;o.push(`path:${s}`)}this.#n.latency&&this.#i.enqueue({metric:"zuplo.request.latency",type:3,points:[{timestamp:n,value:e.durationMs}],tags:o}),this.#n.requestContentLength&&e.requestContentLength&&this.#i.enqueue({metric:"zuplo.request.content_length",type:3,points:[{timestamp:n,value:e.requestContentLength}],tags:o}),this.#n.responseContentLength&&e.responseContentLength&&this.#i.enqueue({metric:"zuplo.response.content_length",type:3,points:[{timestamp:n,value:e.responseContentLength}],tags:o}),r.waitUntil(this.#i.waitUntilFlushed())}dispatchFunction=i(async e=>{if(e.length!==0)try{let r=JSON.stringify({series:e}),n=await W.fetch(this.#t,{method:"POST",body:r,headers:{"content-type":"application/json","DD-API-KEY":this.#e}});n.ok||await fe({level:"error",messages:["Failed to send metrics to DataDog."]},n)}catch{await fe({level:"error",messages:["Failed to connect to DataDog metrics service. Check that the URL is correct."]})}},"dispatchFunction")};var Rm=new WeakMap,HT={dimensions:[]},Im=class extends xt{constructor(r){super();this.options=r;w("metrics.dynatrace")}static{i(this,"DynatraceMetricsPlugin")}getTransport(){return new Sm(this.options)}static setContext(r,n){let o=Rm.get(r);o||(o=HT);let s=Object.assign({...o},n);Rm.set(r,s)}},Sm=class{static{i(this,"DynaTraceMetricsTransport")}apiToken;#e;#t;dimensions;#n;#r=void 0;constructor(e){this.apiToken=e.apiToken,this.#e=e.url,this.#t=Object.assign({latency:!0,requestContentLength:!0,responseContentLength:!0},e.metrics),this.#n=e.include??{},this.dimensions=e.dimensions??[]}pushMetrics(e,r){this.#r===void 0&&(this.#r=new ce("dynatrace-metrics-transport",10,this.dispatchFunction,re.getLogger(r)));let n=Math.floor(e.timestamp.getTime()),o=this.dimensions.concat(Rm.get(r)?.dimensions??[]);if(this.#n.country&&o.push(`country="${e.country}"`),this.#n.httpMethod&&o.push(`http_method="${e.method}"`),this.#n.statusCode&&o.push(`status_code="${e.statusCode}"`),this.#n.path){let a=e.systemRouteName||e.routePath;o.push(`path="${a}"`)}let s=o.join(",");this.#t.latency&&this.#r.enqueue(`zuplo.request.latency,${s} ${e.durationMs} ${n}`),this.#t.requestContentLength&&e.requestContentLength&&this.#r.enqueue(`zuplo.request.content_length,${s} ${e.requestContentLength} ${n}`),this.#t.responseContentLength&&e.responseContentLength&&this.#r.enqueue(`zuplo.response.content_length,${s} ${e.responseContentLength} ${n}`),r.waitUntil(this.#r.waitUntilFlushed())}dispatchFunction=i(async e=>{if(e.length!==0)try{let r=e.join(`
118
118
  `),n=await W.fetch(this.#e,{method:"POST",body:r,headers:{"content-type":"text/plain",Authorization:`Api-Token ${this.apiToken}`}});n.ok||await fe({level:"error",messages:["Failed to send metrics to Dynatrace."]},n)}catch{await fe({level:"error",messages:["Failed to connect to Dynatrace metrics service. Check that the URL is correct."]})}},"dispatchFunction")};var km=new WeakMap,BT={attributes:{}},_m=class extends xt{constructor(r){super();this.options=r;w("metrics.newrelic")}static{i(this,"NewRelicMetricsPlugin")}getTransport(){return new Tm(this.options)}static setContext(r,n){let o=km.get(r);o||(o=BT);let s=Object.assign({...o},n);km.set(r,s)}},Tm=class{static{i(this,"NewRelicMetricsTransport")}#e;#t;#n;#r;#o;#i=void 0;constructor(e){this.#e=e.apiKey,this.#t=e.url??"https://metric-api.newrelic.com/metric/v1",this.#n=Object.assign({latency:!0,requestContentLength:!0,responseContentLength:!0},e.metrics),this.#o=e.include??{},this.#r=e.attributes??{service:"zuplo"}}pushMetrics(e,r){this.#i===void 0&&(this.#i=new ce("new-relic-metrics-transport",10,this.dispatchFunction,re.getLogger(r)));let n=Math.floor(e.timestamp.getTime()),o={...this.#r,...km.get(r)?.attributes};if(this.#o.country&&(o.country=e.country),this.#o.httpMethod&&(o.httpMethod=e.method),this.#o.statusCode&&(o.statusCode=e.statusCode.toString()),this.#o.path){let s=e.systemRouteName||e.routePath;o.path=s}this.#n.latency&&this.#i.enqueue({name:"zuplo.request.latency",type:"gauge",value:e.durationMs,timestamp:n,attributes:o}),this.#n.requestContentLength&&e.requestContentLength&&this.#i.enqueue({name:"zuplo.request.content_length",type:"gauge",value:e.requestContentLength,timestamp:n,attributes:o}),this.#n.responseContentLength&&e.responseContentLength&&this.#i.enqueue({name:"zuplo.response.content_length",type:"gauge",value:e.responseContentLength,timestamp:n,attributes:o}),r.waitUntil(this.#i.waitUntilFlushed())}dispatchFunction=i(async e=>{if(e.length!==0)try{let r=JSON.stringify([{metrics:e}]),n=await W.fetch(this.#t,{method:"POST",body:r,headers:{"Content-Type":"application/json","Api-Key":this.#e}});n.ok||await fe({level:"error",messages:[`Failed to send metrics to New Relic. Status: ${n.status} ${n.statusText}`]},n)}catch{await fe({level:"error",messages:["Failed to connect to New Relic metrics service. Check that the URL is correct."]})}},"dispatchFunction")};var Em=class{static{i(this,"AuditLogDataStaxProvider")}constructor(e){this.#e=e,w("audit-logs.datastax")}#e;writeLogBatch=i(async e=>{await Promise.allSettled(e.map(async r=>{await W.fetch(this.#e.url,{method:"POST",headers:{"X-Cassandra-Token":this.#e.xCassandraToken,"content-type":"application/json"},body:JSON.stringify(r)})}))},"writeLogBatch")};var Cm=class extends Ee{static{i(this,"AuditLogPlugin")}constructor(e,r){super(),this.#e=e,this.#t=r,w("audit-logs")}#e;#t;async initialize(e){new $m(e,this.#e,this.#t)}},Wv=i(t=>{let e={};return t.forEach((r,n)=>{e[n]=r}),e},"serializableHeaders"),GT={requestFilter:i(async()=>!0,"requestFilter"),include:{request:{headers:!0,body:!0},response:{headers:!0,body:!0}}},$m=class{static{i(this,"AuditPluginImpl")}constructor(e,r,n){this.#t=r;let o={...GT};n?.requestFilter&&(o.requestFilter=n.requestFilter),n?.include?.request&&Object.assign(o,n.include.request),n?.include?.response&&Object.assign(o,n.include.response),this.#e=o,e.addRequestHook(this.#i),this.#n=new ce("audit-log",10,this.#r)}#e;#t;#n;#r=i(async e=>{await this.#t.writeLogBatch(e)},"#dispatch");#o=i(async(e,r,n,o,s,a)=>{try{let u={timestamp:o,durationMs:s,routePath:n.route.path,requestId:n.requestId,userSub:a,request:{url:r.url,method:r.method,headers:this.#e.include?.request?.headers?Wv(r.headers):void 0,body:this.#e.include?.request?.body?await r.text():void 0},response:{status:e.status,statusText:e.statusText,headers:this.#e.include?.response?.headers?Wv(e.headers):void 0,body:this.#e.include?.response?.body?await e.text():void 0}};this.#n.enqueue(u),n.waitUntil(this.#n.waitUntilFlushed())}catch(u){n.log.error(u)}},"#asyncPrepLogs");#i=i(async(e,r)=>{try{if(!await this.#e.requestFilter(e,r))return e;let o=new Date,s=Date.now(),a=e.clone();return r.addResponseSendingFinalHook(async(u,c)=>{let l=Date.now(),d=u.clone(),p=this.#o(d,a,r,o,l-s,c.user?.sub).catch(m=>{r.log.error(m)});r.waitUntil(p)}),e}catch(n){return r.log.error(n),e}},"#auditHook")};var Om={None:0,JsonEscape:1},Oo=class{constructor(e,r={}){this.stream=e;this.options=r;this.placeholder=`__STREAM_TOKEN_${crypto.randomUUID()}__`}static{i(this,"StreamToken")}placeholder;getRawStream(){return this.stream}getOptions(){return this.options}getSafeToken(){return this.placeholder}async getContent(){if(!this.stream)return this.options.useEmptyStringIfNull?"":null;let e=this.stream.getReader(),r=[];try{for(;;){let{done:u,value:c}=await e.read();if(u)break;r.push(c)}}finally{e.releaseLock()}let n=r.reduce((u,c)=>u+c.length,0),o=new Uint8Array(n),s=0;for(let u of r)o.set(u,s),s+=u.length;let a=new TextDecoder().decode(o);return this.options.base64Encode&&(a=btoa(a)),a}},Js=class{static{i(this,"StreamBuilder")}template;tokens;flags;constructor(e){this.template=e.template,this.tokens=e.tokens,this.flags=e.flags}escapeJsonString(e){return e.replace(/[\\\"\n\r\t\f\b]/g,r=>{switch(r){case"\\":return"\\\\";case'"':return'\\"';case`
119
119
  `:return"\\n";case"\r":return"\\r";case" ":return"\\t";case"\f":return"\\f";case"\b":return"\\b";default:return r}})}async toString(){let r=this.getStream().getReader(),n=new TextDecoder,o="";for(;;){let{done:s,value:a}=await r.read();if(s)break;o+=n.decode(a,{stream:!0})}return o+=n.decode(),o}getStream(){let e=this.template,r=this.flags,n=new TextEncoder,o=new Map;for(let m of this.tokens)o.set(m.getSafeToken(),m);let s=/"(__STREAM_TOKEN_[^"]+__)"|(__STREAM_TOKEN_[^"]+__)/g,a=[],u=0,c;for(;(c=s.exec(e))!==null;){if(c.index>u&&a.push({type:"literal",value:e.substring(u,c.index)}),c[1]){let m=o.get(c[1]);m?a.push({type:"token",token:m,isQuoted:!0}):a.push({type:"literal",value:c[0]})}else if(c[2]){let m=o.get(c[2]);m?a.push({type:"token",token:m,isQuoted:!1}):a.push({type:"literal",value:c[0]})}u=s.lastIndex}u<e.length&&a.push({type:"literal",value:e.substring(u)});function l(){let m="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",g=new Uint8Array(0);return new TransformStream({transform(h,v){let b=new Uint8Array(g.length+h.length);b.set(g),b.set(h,g.length);let S=b.length%3,x=b.length-S;if(x>0){let $=b.subarray(0,x),O="";for(let L=0;L<$.length;L+=3){let _=$[L],z=$[L+1],D=$[L+2],j=_<<16|z<<8|D;O+=m[j>>18&63],O+=m[j>>12&63],O+=m[j>>6&63],O+=m[j&63]}v.enqueue(O)}g=b.subarray(b.length-S)},flush(h){if(g.length>0){let v=g[0],b=g.length>1?g[1]:0,S=v<<16|b<<8,x="";x+=m[S>>18&63],x+=m[S>>12&63],x+=g.length===2?m[S>>6&63]:"=",x+="=",h.enqueue(x)}}})}i(l,"createBase64EncodeTransformStream");function d(){return new TransformStream({transform(m,g){let h=m.replace(/[\\\"\n\r\t\f\b]/g,v=>{switch(v){case"\\":return"\\\\";case'"':return'\\"';case`
@@ -131,7 +131,7 @@ Signature verification is impossible without access to the original signed mater
131
131
  `+d}):new $t(e,t,{message:`No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?
132
132
  If a webhook request is being forwarded by a third-party tool, ensure that the exact request body, including JSON formatting and new line style, is preserved.
133
133
  `+l+`
134
- `+d});let p=Math.floor((typeof u=="number"?u:Date.now())/1e3)-r.timestamp;if(o>0&&p>o)throw new $t(e,t,{message:"Timestamp outside the tolerance zone"});return!0}i(gE,"validateComputedSignature");function hE(t,e){return typeof t!="string"?null:t.split(",").reduce((r,n)=>{let o=n.split("=");return o[0]==="t"&&(r.timestamp=parseInt(o[1],10)),o[0]===e&&r.signatures.push(o[1]),r},{timestamp:-1,signatures:[]})}i(hE,"parseHeader");function yE(t,e){if(t.length!==e.length)return!1;let r=t.length,n=0;for(let o=0;o<r;++o)n|=t.charCodeAt(o)^e.charCodeAt(o);return n===0}i(yE,"secureCompare");async function bE(t,e){let r=new TextEncoder,n=await crypto.subtle.importKey("raw",r.encode(e),{name:"HMAC",hash:{name:"SHA-256"}},!1,["sign"]),o=await crypto.subtle.sign("hmac",n,r.encode(t)),s=new Uint8Array(o),a=new Array(s.length);for(let u=0;u<s.length;u++)a[u]=Fm[s[u]];return a.join("")}i(bE,"computeHMACSignatureAsync");var Fm=new Array(256);for(let t=0;t<Fm.length;t++)Fm[t]=t.toString(16).padStart(2,"0");function ae(t,e,r="policy",n){let o=`${r} '${e}'`;if(!ar(t))throw new y(`Options on ${o} is expected to be an object. Received the type '${typeof t}'.`);let s=i((c,l,d)=>{let p=t[c],m=n?`${n}.${String(c)}`:String(c);if(!(d&&p===void 0)){if(p===void 0)throw new y(`Value of '${m}' on ${o} is required, but no value was set. If using an environment variable, check that it is set correctly.`);if(l==="array"){if(!Array.isArray(p))throw new y(`Value of '${m}' on ${o} must be an array. Received type ${typeof p}.`)}else if(typeof p!==l)throw new y(`Value of '${m}' on ${o} must be of type ${l}. Received type ${typeof p}.`);if(typeof p=="string"&&p.length===0)throw new y(`Value of '${m}' on ${o} must be a non-empty string. The value received is empty. If using an environment variable, check that it is set correctly.`);if(typeof p=="number"&&isNaN(p))throw new y(`Value of '${m}' on ${o} must be valid number. If using an environment variable, check that it is set correctly.`)}},"validate"),a=i((c,l)=>(s(c,l,!0),{optional:a,required:u}),"optional"),u=i((c,l)=>(s(c,l,!1),{optional:a,required:u}),"required");return{optional:a,required:u}}i(ae,"optionValidator");var Lo=class extends xe{static{i(this,"StripeWebhookVerificationInboundPolicy")}constructor(e,r){super(e,r),w("policy.inbound.stripe-webhook-verification")}async handler(e,r){ae(this.options,this.policyName).required("signingSecret","string").optional("tolerance","number");let n=e.headers.get("stripe-signature");try{let o=await e.clone().text();await ow(o,n,this.options.signingSecret)}catch(o){let s=o.message;if(o.type&&o.type==="StripeSignatureVerificationError"){let a=o.message,c=/Note:(.*)/g.exec(a);s=c?c[1].trim():a,s.startsWith("No signatures found matching the expected signature for payload")&&(s="The Stripe Webhook Signature Secret provided is incorrect and does not match to the signature on the event received. Make sure your Zuplo configuration is correct.")}return r.log.error("Error validating stripe webhook",s),M.badRequest(e,r,{title:"Webhook Error",detail:s})}return e}};function iw(t){return t!==null&&typeof t=="object"&&"id"in t&&Xe(t.id)&&"type"in t&&Xe(t.type)}i(iw,"isStripeWebhookEvent");var vE={getSubscription:i(async({subscriptionId:t,stripeSecretKey:e,logger:r})=>{let n=await W.fetch(`https://api.stripe.com/v1/subscriptions/${t}`,{headers:{Authorization:`Bearer ${e}`}}),o=await n.json();if(n.status!==200){let s="Error retrieving subscription from Stripe API.";throw r.error(s,o),new q(s)}return o},"getSubscription"),getCustomer:i(async({customerId:t,stripeSecretKey:e,logger:r})=>{let n=await W.fetch(`https://api.stripe.com/v1/customers/${t}`,{headers:{Authorization:`Bearer ${e}`}}),o=await n.json();if(n.status!==200){let s="Error retrieving customer from Stripe API.";throw r.error(s,o),new q(s)}return o},"getCustomer"),getUpcomingInvoice:i(async({customerId:t,stripeSecretKey:e,logger:r})=>{let n=await W.fetch(`https://api.stripe.com/v1/invoices/upcoming?customer=${t}`,{headers:{Authorization:`Bearer ${e}`}}),o=await n.json();if(n.status!==200){let s="Error retrieving customer upcoming invoice from Stripe API.";throw r.error(s,o),new q(s)}return o},"getUpcomingInvoice")},Ws=vE;var Hm="https://api-key-management-service-eq7z4lly2a-ue.a.run.app",sw="My API Key";async function aw({apiKeyBucketName:t,stripeSubscriptionId:e,stripeProductId:r,stripeCustomerId:n,managerEmail:o,managerSub:s,context:a}){let{authApiJWT:u}=R.instance,c=new URL(`/v1/buckets/${t}/consumers`,Hm);c.searchParams.set("with-api-key","true");let l=crypto.randomUUID(),d={name:l,description:sw,tags:{subscriptionExternalId:e,planExternalIds:[r]},metadata:{stripeSubscriptionId:e,stripeProductId:r,stripeCustomerId:n},managers:[{sub:s,email:o}]},p=await Te({retryDelayMs:5,retries:2,logger:re.getLogger(a)},c.toString(),{method:"POST",headers:{Authorization:`Bearer ${u}`,"content-type":"application/json"},body:JSON.stringify(d)}),m=await p.json();if(p.status!==200){let g="Error creating API Key Consumer";throw a.log.error(g,m),new q(g)}return a.log.info("Successfully created API Key Consumer",{consumerId:l,stripeSubscriptionId:e,stripeProductId:r}),l}i(aw,"createConsumer");async function uw({apiKeyBucketName:t,stripeSubscriptionId:e,stripeProductId:r,stripeCustomerId:n,managerEmail:o,context:s}){let{authApiJWT:a}=R.instance,u=new URL(`/v1/buckets/${t}/consumers`,Hm);u.searchParams.set("with-api-key","true");let c=crypto.randomUUID(),l={name:c,description:sw,tags:{subscriptionExternalId:e,planExternalIds:[r]},metadata:{stripeSubscriptionId:e,stripeProductId:r,stripeCustomerId:n},managers:[o]},d=await Te({retryDelayMs:5,retries:2,logger:re.getLogger(s)},u.toString(),{method:"POST",headers:{Authorization:`Bearer ${a}`,"content-type":"application/json"},body:JSON.stringify(l)}),p=await d.json();if(d.status!==200){let m="Error creating API Key Consumer";throw s.log.error(m,p),new q(m)}return s.log.info("Successfully created API Key Consumer with Manager Invite",{consumerId:c,stripeSubscriptionId:e,stripeProductId:r}),c}i(uw,"createConsumerInvite");async function cw({apiKeyBucketName:t,consumerId:e,context:r}){let{authApiJWT:n}=R.instance,o=new URL(`/v1/buckets/${t}/consumers/${e}`,Hm);o.searchParams.set("with-api-key","true");let s=await Te({retryDelayMs:5,retries:2,logger:re.getLogger(r)},o.toString(),{method:"DELETE",headers:{Authorization:`Bearer ${n}`,"content-type":"application/json"},body:JSON.stringify({})});if(s.status!==204){let a=await s.json(),u="Error invalidating API Key Consumer";throw r.log.error(u,a),new q(u)}return r.log.info(`Successfully invalidated API Key Consumer '${e}`),e}i(cw,"deleteConsumer");async function lw({context:t,stripeSubscriptionId:e,stripeProductId:r,customerKey:n,meteringBucketId:o,meteringBucketRegion:s,customerExternalId:a,subscriptionStatus:u,metadata:c,trial:l}){let d={status:u,type:"periodic",renewalStrategy:"monthly",region:s,subscriptionExternalId:e,planExternalIds:[r],customerKey:n,customerExternalId:a,metadata:c,trialEndDate:l?l.trialEndDate:void 0,trialStartDate:l?l.trialStartDate:void 0,trialEndStatus:l?l.trialEndStatus:void 0},{authApiJWT:p,meteringServiceUrl:m}=R.instance;if(!_r(p))throw new ue("No Zuplo JWT token set.");let g=await Te({retryDelayMs:5,retries:2,logger:re.getLogger(t)},`${m}/internal/v1/metering/${o}/subscriptions`,{headers:{Authorization:`Bearer ${p}`,"Content-Type":"application/json","zp-rid":t.requestId},method:"POST",body:JSON.stringify(d)});if(!g.ok){let h=`Unable to create a monetization subscription for Stripe subscription '${e}'.`,v,b="";try{v=await g.json(),b=v.detail??v.title}catch{v={type:"https://zup.fail/http-status/500",title:"Internal Server Error",status:g.status,detail:g.statusText}}throw t.log.error(h,v),new q(`${h} ${b}`)}t.log.info("Successfully created monetization subscription.",d)}i(lw,"createSubscription");async function Xr({context:t,meteringSubscriptionId:e,meteringBucketId:r,requestBody:n}){let{authApiJWT:o,meteringServiceUrl:s}=R.instance;if(!_r(o))throw new ue("No Zuplo JWT token set.");let a=await Te({retryDelayMs:5,retries:2,logger:re.getLogger(t)},`${s}/internal/v1/metering/${r}/subscriptions/${e}`,{headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json","zp-rid":t.requestId},method:"PATCH",body:JSON.stringify(n)});if(!a.ok){let u=`Unable to update monetization subscription with: '${JSON.stringify(n)}'.`,c,l="";try{c=await a.json(),l=c.detail??c.title}catch{c={type:"https://zup.fail/http-status/500",title:"Internal Server Error",status:a.status,detail:a.statusText}}throw t.log.error(u,c),new q(`${u} ${l}`)}t.log.info(`Successfully updated monetization subscription with: '${JSON.stringify(n)}'.`)}i(Xr,"updateSubscription");async function Yr({context:t,stripeSubscriptionId:e,stripeCustomerId:r,meteringBucketId:n}){let{authApiJWT:o,meteringServiceUrl:s}=R.instance;if(!_r(o))throw new ue("No Zuplo JWT token set.");let a=await Te({retryDelayMs:5,retries:2,logger:re.getLogger(t)},`${s}/internal/v1/metering/${n}/subscriptions?subscriptionExternalId=${e}`,{headers:{Authorization:`Bearer ${o}`,"zp-rid":t.requestId},method:"GET"});if(!a.ok){let c=`Unable to retrieve the monetization subscription for Stripe subscription '${e}'.`,l,d="";try{l=await a.json(),d=l.detail??l.title}catch{l={type:"https://zup.fail/http-status/500",title:"Internal Server Error",status:a.status,detail:a.statusText}}throw t.log.error(c,l),new q(`${c} ${d}`)}let u=await a.json();if(u.data.length===0){let c=`Subscription was not found for Stripe subscription '${e}' and the event was ignored by Zuplo.`;throw t.log.error(c),new q(c)}if(u.data[0].customerExternalId!==r){let c=`Subscription was not found for Stripe customer '${r}' and the event was ignored by Zuplo.`;throw t.log.error(c),new q(c)}return u.data[0]}i(Yr,"getSubscription");var _e="Skipping since we're unable to process the webhook event.",or="Successfully processed the webhook event",We="See https://zuplo.com/docs/articles/monetization-troubleshooting for more details.";function Ks(t){return t.replaceAll("_","-")}i(Ks,"stripeStatusToMeteringStatus");function xr(t){return new Date(t*1e3).toISOString()}i(xr,"unixTimestampToISOString");async function Bm(t,e,r,n){let o=r.data.object.id;if(!o)return e.log.warn(`Invalid Stripe webhook event. Expected event '${r.id}' to have '.data.object.id' be the subscription ID.`),M.ok(t,e,{title:_e,detail:"Invalid Stripe webhook event. Expected '.data.object.id' to be the subscription ID."});let s=r.data.object.plan;if(!s||!s.product)return e.log.warn(`Invalid Stripe API result. Expected event '${r.id}' to have a plan data.`),M.ok(t,e,{title:_e,detail:"Invalid Stripe API result. Expected event to have a plan data."});let a=r.data.object.customer;if(!a)return e.log.warn(`Invalid Stripe webhook event. Expected '.data.object.customer' to be provided by event '${r.id}'`),M.ok(t,e,{title:_e,detail:"Invalid Stripe webhook event. Expected '.data.object.customer' to be provided"});if(r.data.object.metadata&&r.data.object.metadata.zuplo_created_by_deploymentName&&r.data.object.metadata.zuplo_created_by_deploymentName!==R.instance.deploymentName)return e.log.warn(`Subscription event '${r.id}' will not be handled since it was not issued for this Zuplo environment. It was intended for '${r.data.object.metadata.zuplo_created_by_deploymentName}'.`),M.ok(t,e,{title:_e,detail:`This subscription event is not meant to be handled by this environment's Stripe monetization plugin. It was intended for '${r.data.object.metadata.zuplo_created_by_deploymentName}'. This can happen because of a misconfiguration of Stripe or your Zuplo API.`+We});let u=s.product,c,l,d;try{if(r.data.object.metadata&&r.data.object.metadata.zuplo_created_by_email&&r.data.object.metadata.zuplo_created_by_sub)l=r.data.object.metadata.zuplo_created_by_email,d=r.data.object.metadata.zuplo_created_by_sub,c=await aw({apiKeyBucketName:n.apiKeyBucketName,stripeProductId:u,stripeSubscriptionId:o,stripeCustomerId:a,managerEmail:l,managerSub:d,context:e});else{let p=await Ws.getCustomer({logger:e.log,stripeSecretKey:n.stripeSecretKey,customerId:a});if(!p.email)return e.log.warn(`Invalid Stripe API result. Expected customer '${a}' to contain email address.`),M.ok(t,e,{title:_e,detail:"Invalid Stripe API result. Expected customer to contain email address."});c=await uw({apiKeyBucketName:n.apiKeyBucketName,stripeProductId:u,stripeSubscriptionId:o,stripeCustomerId:a,managerEmail:p.email,context:e})}}catch(p){return e.log.warn(`Failed to create API Key Consumer. Error: ${p.message}`),M.ok(t,e,{title:_e,detail:p.message})}if(!c)return M.ok(t,e,{title:_e,detail:"No API Key Consumer was created, skipping creation of subscription."});try{let p=Ks(r.data.object.status),m;l&&d&&(m={subscriber:{sub:d,email:l}});let g;r.data.object.trial_end!==null&&r.data.object.trial_start!==null&&r.data.object.trial_settings&&r.data.object.trial_settings.end_behavior&&(r.data.object.trial_settings.end_behavior.missing_payment_method==="cancel"||r.data.object.trial_settings.end_behavior.missing_payment_method==="pause")&&(g={trialEndStatus:r.data.object.trial_settings.end_behavior.missing_payment_method,trialEndDate:xr(r.data.object.trial_end),trialStartDate:xr(r.data.object.trial_start)}),await lw({context:e,stripeProductId:u,stripeSubscriptionId:o,customerKey:c,meteringBucketId:n.meteringBucketId,meteringBucketRegion:n.meteringBucketRegion,customerExternalId:a,subscriptionStatus:p,metadata:m,trial:g})}catch(p){return await cw({apiKeyBucketName:n.apiKeyBucketName,consumerId:c,context:e}),M.ok(t,e,{title:_e,detail:p.message})}return M.ok(t,e,{title:or})}i(Bm,"onCustomerSubscriptionCreated");async function Gm(t,e,r,n){let o=r.data.object.id;if(!o)return e.log.warn(`Invalid Stripe webhook event. Expected event '${r.id}' to have '.data.object.id' be the subscription ID.`),M.ok(t,e,{title:_e,detail:"Invalid Stripe webhook event. Expected '.data.object.id' to be the subscription ID."});let s=r.data.object.customer;if(!s)return e.log.warn(`Invalid Stripe webhook event. Expected '.data.object.customer' to be provided by event '${r.id}'`),M.ok(t,e,{title:_e,detail:"Invalid Stripe webhook event. Expected '.data.object.customer' to be provided"});if(r.data.object.metadata&&r.data.object.metadata.zuplo_created_by_deploymentName&&r.data.object.metadata.zuplo_created_by_deploymentName!==R.instance.deploymentName)return e.log.warn(`Subscription event '${r.id}' will not be handled since it was not issued for this Zuplo environment. It was intended for '${r.data.object.metadata.zuplo_created_by_deploymentName}'.`),M.ok(t,e,{title:_e,detail:`This 'customer.subscription.deleted' event is not meant to be handled by this environment's Stripe monetization plugin. It was intended for '${r.data.object.metadata.zuplo_created_by_deploymentName}'.This can happen because of a misconfiguration of Stripe or your Zuplo API.`+We});try{let a=await Yr({context:e,stripeSubscriptionId:o,stripeCustomerId:s,meteringBucketId:n.meteringBucketId});await Xr({context:e,meteringSubscriptionId:a.id,meteringBucketId:n.meteringBucketId,requestBody:{status:"canceled",planExternalIds:a.planExternalIds}})}catch(a){return M.ok(t,e,{title:_e,detail:`The event 'customer.subscription.deleted' could not be processed. ${a.message} This can happen because of a misconfiguration of Stripe or your Zuplo API. `+We})}return M.ok(t,e,{title:or})}i(Gm,"onCustomerSubscriptionDeleted");async function Vm(t,e,r,n){let o=r.data.object.id;if(!o)return e.log.warn(`Invalid Stripe webhook event. Expected event '${r.id}' to include '.data.object.id' as the subscription ID.`),M.ok(t,e,{title:_e,detail:"Invalid Stripe webhook event. Expected '.data.object.id' to be the subscription ID."});let s=r.data.object.customer;if(!s)return e.log.warn(`Invalid Stripe webhook event. Expected '.data.object.customer' to be provided by event '${r.id}'`),M.ok(t,e,{title:_e,detail:"Invalid Stripe webhook event. Expected '.data.object.customer' to be provided"});if(r.data.object.metadata&&r.data.object.metadata.zuplo_created_by_deploymentName&&r.data.object.metadata.zuplo_created_by_deploymentName!==R.instance.deploymentName)return e.log.warn(`Subscription event '${r.id}' will not be handled since it was not issued for this Zuplo environment. It was intended for '${r.data.object.metadata.zuplo_created_by_deploymentName}'.`),M.ok(t,e,{title:_e,detail:`This 'customer.subscription.updated' event is not meant to be handled by this environment's Stripe monetization plugin. It was intended for '${r.data.object.metadata.zuplo_created_by_deploymentName}'.This can happen because of a misconfiguration of Stripe or your Zuplo API.`+We});if(r.data.previous_attributes){let a=r.data.previous_attributes;if(a.status&&a.status!==r.data.object.status){try{e.log.debug(`Processing subscription status change from Stripe event '${r.id}'.`);let u=await Yr({context:e,stripeSubscriptionId:o,stripeCustomerId:s,meteringBucketId:n.meteringBucketId}),c=Ks(r.data.object.status),l;a.trial_end&&a.trial_end!==r.data.object.trial_end&&r.data.object.trial_end!==null&&(l=xr(r.data.object.trial_end)),await Xr({context:e,meteringSubscriptionId:u.id,meteringBucketId:n.meteringBucketId,requestBody:{status:c,planExternalIds:u.planExternalIds,trialEndDate:l}})}catch(u){return M.ok(t,e,{title:_e,detail:`The event 'customer.subscription.updated' could not be processed. ${u.message} This can happen because of a misconfiguration of Stripe or your Zuplo API. However, it also could be a temporary condition that happens when a subscription is created due to events being sent out of order. `+We})}return M.ok(t,e,{title:or})}if(a.plan&&a.plan.product!==r.data.object.plan.product){try{e.log.debug(`Processing subscription plan change from Stripe event '${r.id}'.`);let u=await Yr({context:e,stripeSubscriptionId:o,stripeCustomerId:s,meteringBucketId:n.meteringBucketId}),c=r.data.object.plan.product,d=(await Ws.getUpcomingInvoice({customerId:s,logger:e.log,stripeSecretKey:n.stripeSecretKey})).lines.data.filter(m=>m.proration&&m.price.product===c),p=0;d.length===0?e.log.warn(`The plan change does not include proration details. Subscription event '${r.id}'`):p=parseFloat(d[0].unit_amount_excluding_tax)/d[0].price.unit_amount,await Xr({context:e,meteringSubscriptionId:u.id,meteringBucketId:n.meteringBucketId,requestBody:{status:u.status,planExternalIds:[c],prorate:p}})}catch(u){return M.ok(t,e,{title:_e,detail:`The event 'customer.subscription.updated' could not be processed. ${u.message} This can happen because of a misconfiguration of Stripe or your Zuplo API. However, it also could be a temporary condition that happens when a subscription is created due to events being sent out of order. `+We})}return M.ok(t,e,{title:or})}if((a.cancel_at||a.cancel_at===null)&&a.cancel_at!==r.data.object.cancel_at&&a.cancel_at_period_end&&a.cancel_at_period_end!==r.data.object.cancel_at_period_end&&(a.canceled_at||a.canceled_at===null)&&a.canceled_at!==r.data.object.canceled_at||a.cancellation_details&&(a.cancellation_details.comment||a.cancellation_details.comment===null||a.cancellation_details.feedback||a.cancellation_details.feedback===null||a.cancellation_details.reason||a.cancellation_details.reason===null)){try{e.log.debug(`Processing subscription cancellation details from Stripe event '${r.id}'.`);let u=await Yr({context:e,stripeSubscriptionId:o,stripeCustomerId:s,meteringBucketId:n.meteringBucketId}),c={cancellation:{cancel_at:r.data.object.cancel_at?xr(r.data.object.cancel_at):null,cancel_at_period_end:r.data.object.cancel_at_period_end,canceled_at:r.data.object.canceled_at?xr(r.data.object.canceled_at):null,cancellation_details:r.data.object.cancellation_details}},l;u.metadata?l={...u.metadata,...c}:l=c,await Xr({context:e,meteringSubscriptionId:u.id,meteringBucketId:n.meteringBucketId,requestBody:{status:u.status,planExternalIds:u.planExternalIds,metadata:l}})}catch(u){return M.ok(t,e,{title:_e,detail:`The event 'customer.subscription.updated' could not be processed. ${u.message} This can happen because of a misconfiguration of Stripe or your Zuplo API. However, it also could be a temporary condition that happens when a subscription is created due to events being sent out of order. `+We})}return M.ok(t,e,{title:or})}}return e.log.warn(`This update event '${r.id}' is not supported by Stripe monetization plugin webhook.`),M.ok(t,e,{title:_e,detail:"This 'customer.subscription.updated' event could not be processed. The Stripe monetization plugin only supports update events for subscription plan changes or subscription status changes."+We})}i(Vm,"onCustomerSubscriptionUpdated");var dw=class extends ei{constructor(r){super();this.options=r;w("monetization.stripe")}static{i(this,"StripeMonetizationPlugin")}registerRoutes({router:r}){let n=i(async(u,c)=>{if(this.options.__testMode===!0)return c.log.warn("Received Stripe webhook event of in test mode."),"success";let{meteringBucketId:l,apiKeyBucketName:d}=this.options;if(!l)if(Se.ZUPLO_METERING_SERVICE_BUCKET_ID)l=Se.ZUPLO_METERING_SERVICE_BUCKET_ID;else throw new y("StripeMonetizationPlugin - No 'meteringBucketId' property provided");if(!d)if(Se.ZUPLO_API_KEY_SERVICE_BUCKET_NAME)d=Se.ZUPLO_API_KEY_SERVICE_BUCKET_NAME;else throw new y("StripeMonetizationPlugin - No 'apiKeyBucketName' property provided");if(!R.instance.build.ACCOUNT_NAME)throw new ue("Build environment is not configured correctly. Expected 'ACCOUNT_NAME' to be set.");let p=this.options.primaryDataRegion??"us-central1";if(!wE(p))throw new y(`StripeMonetizationPlugin - The value '${p}' on the property 'primaryDataRegion' is invalid.`);let m=await u.json();if(!iw(m))return M.ok(u,c,{title:_e,detail:"The event payload received was not in the expected format. This can happen because of a misconfiguration of Stripe or your Zuplo API. "+We});switch(c.log.info(`Received Stripe webhook event of type '${m.type}' with ID '${m.id}'.`),m.type){case"customer.subscription.created":return await Bm(u,c,m,{meteringBucketId:l,apiKeyBucketName:d,meteringBucketRegion:p,stripeSecretKey:this.options.stripeSecretKey});case"customer.subscription.updated":return await Vm(u,c,m,{meteringBucketId:l,apiKeyBucketName:d,meteringBucketRegion:p,stripeSecretKey:this.options.stripeSecretKey});case"customer.subscription.deleted":return await Gm(u,c,m,{meteringBucketId:l});default:return M.ok(u,c,{title:_e,detail:`Event '${m.type}' could not be processed because it is not supported by Stripe monetization plugin webhook. This can happen because of a misconfiguration of Stripe or your Zuplo API.`+We})}},"stripeWebhookHandler"),o=Zg({inboundPolicies:[new Lo({signingSecret:this.options.webhooks.signingSecret,tolerance:this.options.webhooks.tolerance},"stripe-webhook-verification")]});ae(this.options.webhooks,"StripeMonetizationPlugin","plugin").required("signingSecret","string").optional("tolerance","number");let s=new Le({processors:[qe,o],handler:n}),a=new Me({label:"PLUGIN_STRIPE_WEBHOOK_ROUTE",methods:["POST"],path:this.options.webhooks.routePath??"/__plugins/stripe/webhooks",systemRouteName:"stripe-plugin"});r.addRoute(a,s.execute)}};function wE(t){return t!==null&&typeof t=="string"&&["us-central1","us-east1","europe-west4"].includes(t)}i(wE,"isMetricsRegion");var mw=new WeakMap,pw={},Jm=class{static{i(this,"AmberfloMeteringPolicy")}static setRequestProperties(e,r){mw.set(e,r)}};async function xE(t,e,r,n){if(w("policy.inbound.amberflo-metering"),!r.statusCodes)throw new y(`Invalid AmberfloMeterInboundPolicy '${n}': options.statusCodes must be an array of HTTP status code numbers`);let o=Pt(r.statusCodes);return e.addResponseSendingFinalHook(async s=>{if(o.includes(s.status)){let a=mw.get(e),u=r.customerId;if(r.customerIdPropertyPath){if(!t.user)throw new q(`Unable to apply customerIdPropertyPath '${r.customerIdPropertyPath}' as request.user is 'undefined'.`);u=At(t.user,r.customerIdPropertyPath,"customerIdPropertyPath")}let c=a?.customerId??u;if(!c){e.log.error(`Error in AmberfloMeterInboundPolicy '${n}': customerId cannot be undefined`);return}let l=a?.meterApiName??r.meterApiName;if(!l){e.log.error(`Error in AmberfloMeterInboundPolicy '${n}': meterApiName cannot be undefined`);return}let d=a?.meterValue??r.meterValue;if(!d){e.log.error(`Error in AmberfloMeterInboundPolicy '${n}': meterValue cannot be undefined`);return}let p={customerId:c,meterApiName:l,meterValue:d,meterTimeInMillis:Date.now(),dimensions:Object.assign(r.dimensions??{},a?.dimensions)},m=pw[r.apiKey];if(!m){let g=r.apiKey,h=t.headers.get("zm-test-id")??"";m=new ce("amberflo-ingest-meter",10,async v=>{try{let b=r.url??"https://app.amberflo.io/ingest",S=await W.fetch(b,{method:"POST",body:JSON.stringify(v),headers:{"content-type":"application/json","x-api-key":g,"zm-test-id":h}});S.ok||e.log.error(`Unexpected response in AmberfloMeteringInboundPolicy '${n}'. ${S.status}: ${await S.text()}`)}catch(b){throw e.log.error(`Error in AmberfloMeteringInboundPolicy '${n}': ${b.message}`),b}}),pw[g]=m}m.enqueue(p),e.waitUntil(m.waitUntilFlushed())}}),t}i(xE,"AmberfloMeteringInboundPolicy");var fw={},Wm=Symbol("openmeter-meters"),Km=class extends xe{static{i(this,"OpenMeterInboundPolicy")}#e;#t;#n;#r;#o;#i;constructor(e,r){if(super(e,r),w("policy.inbound.openmeter-metering"),ae(this.options,this.policyName).required("apiKey","string").optional("apiUrl","string").optional("eventSource","string").optional("requiredEntitlements","array").optional("subjectPath","string"),this.options.meter!==void 0){if(typeof this.options.meter!="object"||this.options.meter===null)throw new y(`Invalid OpenMeterInboundPolicy '${this.policyName}': options.meter must be an object or array. Received type ${typeof this.options.meter}.`);let n=Array.isArray(this.options.meter)?this.options.meter:[this.options.meter];for(let o of n)if(!o.type)throw new y(`Invalid OpenMeterInboundPolicy '${this.policyName}': meter.type is required`)}if(this.options.meterOnStatusCodes!==void 0&&typeof this.options.meterOnStatusCodes!="string"&&!Array.isArray(this.options.meterOnStatusCodes))throw new y(`Invalid OpenMeterInboundPolicy '${this.policyName}': options.meterOnStatusCodes must be a string or array. Received type ${typeof this.options.meterOnStatusCodes}.`);this.#t=this.options.eventSource||"api-gateway",this.#n=this.options.apiUrl||"https://openmeter.cloud",this.#r=`${this.#n}/api/v1/events`,this.#e=new Headers({"content-type":"application/cloudevents-batch+json",Authorization:`Bearer ${e.apiKey}`}),this.#i=Pt(this.options.meterOnStatusCodes||"200-299"),this.#o=this.options.subjectPath||".sub"}async handler(e,r){if(this.options.requiredEntitlements&&this.options.requiredEntitlements.length>0){let n=this.getSubject(e);if(!n)r.log.error(`Error in OpenMeterInboundPolicy '${this.policyName}': subject cannot be undefined for entitlement checking`);else try{let o=this.options.requiredEntitlements.map(u=>this.checkEntitlement(n,u,r).then(c=>({featureKey:u,result:c}))),s=await Promise.all(o),a=null;for(let{result:u,featureKey:c}of s)!u.hasAccess&&!a&&(a={...u,featureKey:c});if(a)return r.log.warn(`OpenMeterInboundPolicy '${this.policyName}' blocked request due to insufficient entitlements on feature '${a.featureKey}' for subject '${n}'.`),M.tooManyRequests(e,r,{detail:"Your subscription has insufficient entitlements for this request."})}catch(o){let s=o instanceof Error?o.message:String(o);r.log.error(`Error during entitlement checking in OpenMeterInboundPolicy '${this.policyName}': ${s}`)}}return this.setupMetering(e,r),e}getSubject(e){if(!e.user)throw new q(`OpenMeterInboundPolicy '${this.policyName}' requires a user to be authenticated. Ensure you have an authentication policy set before this policy?`);return At(e.user,this.#o,"subjectPath")}async checkEntitlement(e,r,n){let o=`${this.#n}/api/v1/subjects/${encodeURIComponent(e)}/entitlements/${encodeURIComponent(r)}/value`,s={"content-type":"application/json"};this.options.apiKey&&(s.authorization=`Bearer ${this.options.apiKey}`);try{let a=await W.fetch(o,{method:"GET",headers:s});return a.ok?await a.json():(n.log.error(`Error checking entitlements in OpenMeterInboundPolicy '${this.policyName}'. ${a.status}: ${await a.text()}`),{hasAccess:!0})}catch(a){let u=a instanceof Error?a.message:String(a);return n.log.error(`Error in OpenMeterInboundPolicy '${this.policyName}': ${u}`),{hasAccess:!0}}}setupMetering(e,r){r.addResponseSendingFinalHook(async n=>{if(this.#i.includes(n.status)){let o=this.getSubject(e);if(!o){r.log.error(`Error in OpenMeterInboundPolicy '${this.policyName}': subject cannot be undefined for metering`);return}let s=de.get(r,Wm)??(this.options.meter?Array.isArray(this.options.meter)?this.options.meter:[this.options.meter]:[]),a=new Date().toISOString();for(let u of s){let c={specversion:"1.0",id:`${r.requestId}-${u.type}`,time:a,source:this.#t,subject:o,...u},l=this.#r,d=fw[l];d||(d=new ce("openmeter-ingest-event",10,async p=>{try{let m=await W.fetch(this.#r,{method:"POST",body:JSON.stringify(p),headers:this.#e});if(m.status!==204){let g=await m.text().catch(()=>"");r.log.error(`Unexpected response in OpenMeterInboundPolicy '${this.policyName}'. ${m.status}`,g)}}catch(m){let g=m instanceof Error?m.message:String(m);throw r.log.error(`Error in OpenMeterInboundPolicy '${this.policyName}': ${g}`),m}}),fw[l]=d),d.enqueue(c),r.waitUntil(d.waitUntilFlushed())}}})}static setMeters(e,r){let n=de.get(e,Wm)||[];de.set(e,Wm,[...n,...Array.isArray(r)?r:[r]])}};var gw="key-metadata-cache-type";function PE(t,e){return e.authScheme===""?t:t.replace(`${e.authScheme} `,"")}i(PE,"getKeyValue");async function Qm(t,e,r,n){if(w("policy.inbound.api-key"),!r.bucketName)if(Se.ZUPLO_API_KEY_SERVICE_BUCKET_NAME)r.bucketName=Se.ZUPLO_API_KEY_SERVICE_BUCKET_NAME;else throw new y(`ApiKeyInboundPolicy '${n}' - no bucketName property provided`);let o={authHeader:r.authHeader??"authorization",authScheme:r.authScheme??"Bearer",bucketName:r.bucketName,cacheTtlSeconds:r.cacheTtlSeconds??60,allowUnauthenticatedRequests:r.allowUnauthenticatedRequests??!1,disableAutomaticallyAddingKeyHeaderToOpenApi:r.disableAutomaticallyAddingKeyHeaderToOpenApi??!1};if(o.cacheTtlSeconds<60)throw new y(`ApiKeyInboundPolicy '${n}' - minimum cacheTtlSeconds value is 60s, '${o.cacheTtlSeconds}' is invalid`);let s=i(S=>o.allowUnauthenticatedRequests?t:M.unauthorized(t,e,{detail:S}),"unauthorizedResponse"),a=t.headers.get(o.authHeader);if(!a)return s("No Authorization Header");if(!a.toLowerCase().startsWith(o.authScheme.toLowerCase()))return s("Invalid Authorization Scheme");let u=PE(a,o);if(!u||u==="")return s("No key present");let c=await RE(u),l=await Pe(n,void 0,o),d=new be(l,e),p=await d.get(c);if(p&&p.isValid===!0)return t.user=p.user,t;if(p&&!p.isValid)return p.typeId!==gw&&re.getLogger(e).error(`ApiKeyInboundPolicy '${n}' - cached metadata has invalid typeId '${p.typeId}'`,p),s("Authorization Failed");let m={key:u},g=new Headers({"content-type":"application/json"});De(g,e.requestId);let h=await Te({retryDelayMs:5,retries:2,logger:re.getLogger(e)},`${R.instance.apiKeyServiceUrl}/v1/$validate/${o.bucketName}`,{method:"POST",headers:g,body:JSON.stringify(m)});if(h.status===401)return e.log.info(`ApiKeyInboundPolicy '${n}' - 401 response from Key Service`),s("Authorization Failed");if(h.status!==200){try{let S=await h.text(),x=JSON.parse(S);e.log.error("Unexpected response from key service",x)}catch{e.log.error("Invalid response from key service")}throw new q(`ApiKeyInboundPolicy '${n}' - unexpected response from Key Service. Status: ${h.status}`)}let v=await h.json(),b={isValid:!0,typeId:gw,user:{apiKeyId:v.id,sub:v.name,data:v.metadata}};return t.user=b.user,d.put(c,b,o.cacheTtlSeconds),t}i(Qm,"ApiKeyInboundPolicy");async function RE(t){let e=new TextEncoder().encode(t),r=await crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(r)).map(s=>s.toString(16).padStart(2,"0")).join("")}i(RE,"hashValue");var IE=Qm;var Xm="ai-gateway-key-metadata-cache-type";function SE(t,e){return e.authScheme===""?t:t.replace(`${e.authScheme} `,"")}i(SE,"getKeyValue");async function kE(t,e,r,n){w("policy.inbound.ai-gateway");let o=Se.ZUPLO_SERVICE_BUCKET_ID;if(!o)throw new y(`AIGatewayAuthInboundPolicy '${n}' - ZUPLO_SERVICE_BUCKET_ID environment variable is required`);let s={authHeader:r.authHeader??"authorization",authScheme:r.authScheme??"Bearer",cacheTtlSeconds:r.cacheTtlSeconds??60};if(s.cacheTtlSeconds<60)throw new y(`AIGatewayAuthInboundPolicy '${n}' - minimum cacheTtlSeconds value is 60s, '${s.cacheTtlSeconds}' is invalid`);let a=i(O=>M.unauthorized(t,e,{detail:O}),"unauthorizedResponse"),u=t.headers.get(s.authHeader);if(!u)return a("No Authorization Header");if(!u.toLowerCase().startsWith(s.authScheme.toLowerCase()))return a("Invalid Authorization Scheme");let c=SE(u,s);if(!c||c==="")return a("No key present");let l=await _E(c),d=await Pe(n,void 0,s),p=new be(d,e),m=await p.get(l);if(m&&m.isValid===!0)return t.user=m.user,t;if(m&&!m.isValid)return m.typeId!==Xm&&re.getLogger(e).error(`AIGatewayAuthInboundPolicy '${n}' - cached metadata has invalid typeId '${m.typeId}'`,m),a("Authorization Failed");let g={key:c},h=new Headers({"content-type":"application/json"});De(h,e.requestId);let v=re.getLogger(e),b=await Te({retryDelayMs:5,retries:2,logger:v},`${R.instance.zuploEdgeApiUrl}/v1/buckets/${o}/validate`,{method:"POST",headers:h,body:JSON.stringify(g)});if(b.status!==200){try{let O=await b.text(),L=JSON.parse(O);v.error("Unexpected response from Gateway service",L)}catch{v.error("Invalid response from Gateway service")}throw new q(`AIGatewayAuthInboundPolicy '${n}' - unexpected response from Gateway Service. Status: ${b.status}`)}let S=await b.json();if(!S.authorized){let O={isValid:!1,typeId:Xm};return p.put(l,O,s.cacheTtlSeconds),a("Authorization Failed")}let x={data:S.metadata,configuration:S.configuration,sub:S.name},$={isValid:!0,typeId:Xm,user:x};return t.user=x,p.put(l,$,s.cacheTtlSeconds),t}i(kE,"AIGatewayAuthInboundPolicy");async function _E(t){let e=new TextEncoder().encode(t),r=await crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(r)).map(s=>s.toString(16).padStart(2,"0")).join("")}i(_E,"hashValue");async function TE(t,e,r,n,o){let s=re.getLogger(r);if(r.custom.streamingUsageHandled===!0)return s.debug("Streaming usage will be handled in streaming transform, skipping sync usage tracker"),t;let u={requests:1},c=0,l=0,d=0,p="",m="";try{let x=await t.clone().json();if(x.usage){l=x.usage.prompt_tokens||0,d=x.usage.completion_tokens||0;let $=x.usage.total_tokens||0;p=x.model||"",m=x.provider||"";let O=await pt(r);c=Tt(p,m,l,d,O,s),s.info("Usage tracked",{userId:e.user?.sub,requestsIncrement:1,tokensUsed:$,promptTokens:l,completionTokens:d,model:p,provider:m,cost:c})}}catch(S){s.debug("Could not track token usage, tracking request only",{error:S})}u.tokens=l+d,u.costs=c,it.setIncrements(r,u);let g=new Headers(t.headers);u.tokens&&g.set("X-Tokens-Used",u.tokens.toString()),c>0&&(g.set("X-Cost-USD",c.toFixed(10)),g.set("X-Model",p)),g.set("X-Requests-Increment","1");let h=e.user;switch(r.analyticsContext.addAnalyticsEvent(1,Qe.AI_GATEWAY_REQUEST_COUNT,{model:p,provider:m,configId:h.configuration.id}),r.analyticsContext.addAnalyticsEvent(parseFloat(c.toFixed(10)),Qe.AI_GATEWAY_COST_SUM,{model:p,provider:m,configId:h.configuration.id}),new URL(e.url).pathname){case"/v1/chat/completions":r.analyticsContext.addAnalyticsEvent(l,Qe.AI_GATEWAY_TOKEN_SUM,{model:p,provider:m,configId:h.configuration.id,tokenType:"prompt"}),r.analyticsContext.addAnalyticsEvent(d,Qe.AI_GATEWAY_TOKEN_SUM,{model:p,provider:m,configId:h.configuration.id,tokenType:"completion"});break;case"/v1/embeddings":r.analyticsContext.addAnalyticsEvent(l,Qe.AI_GATEWAY_TOKEN_SUM,{model:p,provider:m,configId:h.configuration.id,tokenType:"embedding"});break;default:break}return new Response(t.body,{status:t.status,statusText:t.statusText,headers:g})}i(TE,"AIGatewayUsageTrackerPolicy");import{createRemoteJWKSet as CE,jwtVerify as yw}from"jose";import{createLocalJWKSet as EE}from"jose";var Ym=class{constructor(e,r,n){this.cache=r;if(!(e instanceof URL))throw new TypeError("url must be an instance of URL");this.url=new URL(e.href),this.options={agent:n?.agent,headers:n?.headers},this.timeoutDuration=typeof n?.timeoutDuration=="number"?n?.timeoutDuration:5e3,this.cooldownDuration=typeof n?.cooldownDuration=="number"?n?.cooldownDuration:3e4,this.cacheMaxAge=typeof n?.cacheMaxAge=="number"?n?.cacheMaxAge:6e5}static{i(this,"RemoteJWKSet")}url;timeoutDuration;cooldownDuration;cacheMaxAge;jwksTimestamp;pendingFetch;options;local;coolingDown(){return typeof this.jwksTimestamp=="number"?Date.now()<this.jwksTimestamp+this.cooldownDuration:!1}fresh(){return typeof this.jwksTimestamp=="number"?Date.now()<this.jwksTimestamp+this.cacheMaxAge:!1}async getKey(e,r){(!this.local||!this.fresh())&&await this.reload();try{return await this.local(e,r)}catch(n){if(n instanceof ef&&this.coolingDown()===!1)return await this.reload(),this.local(e,r);throw n}}async reload(){this.pendingFetch&&(this.pendingFetch=void 0);let e=new Headers(this.options.headers);e.has("User-Agent")||(e.set("User-Agent",R.instance.systemUserAgent),this.options.headers=Object.fromEntries(e.entries())),this.pendingFetch||=this.fetchJwks(this.url,this.timeoutDuration,this.options).then(r=>{this.local=EE(r),this.jwksTimestamp=Date.now(),this.pendingFetch=void 0}).catch(r=>{throw this.pendingFetch=void 0,r}),await this.pendingFetch}async fetchJwks(e,r,n){let o=await this.cache.get(this.url.href);if(o)return o;let s,a,u=!1;typeof AbortController=="function"&&(s=new AbortController,a=setTimeout(()=>{u=!0,s.abort()},r));let c=await W.fetch(e.href,{signal:s?s.signal:void 0,redirect:"manual",headers:n.headers}).catch(l=>{throw u?new tf("JWKS fetch timed out"):l});if(a!==void 0&&clearTimeout(a),c.status!==200)throw new en("Expected 200 OK from the JSON Web Key Set HTTP response");try{let l=await c.json();return this.cache.put(this.url.href,l,this.cacheMaxAge),l}catch{throw new en("Failed to parse the JSON Web Key Set HTTP response as JSON")}}};function hw(t,e,r){let n=new Ym(t,e,r);return async(o,s)=>n.getKey(o,s)}i(hw,"createRemoteJWKSet");var en=class extends q{static{i(this,"JWKSError")}},ef=class extends en{static{i(this,"JWKSNoMatchingKey")}},tf=class extends en{static{i(this,"JWKSTimeout")}};var Qs={},$E=i((t,e)=>async(r,n)=>{if(!n.jwkUrl||typeof n.jwkUrl!="string")throw new y("Invalid State - jwkUrl not set");if(!Qs[n.jwkUrl]){let s=!1;if("useExperimentalInMemoryCache"in n&&typeof n.useExperimentalInMemoryCache=="boolean"&&(s=n.useExperimentalInMemoryCache),s){let a=await Pe(t,void 0,n),u=new be(a,e);Qs[n.jwkUrl]=hw(new URL(n.jwkUrl),u,n.headers?{headers:n.headers}:void 0)}else Qs[n.jwkUrl]=CE(new URL(n.jwkUrl),n.headers?{headers:n.headers}:void 0)}let{payload:o}=await yw(r,Qs[n.jwkUrl],{issuer:n.issuer,audience:n.audience});return o},"createJwkVerifier"),OE=i(async(t,e)=>{let r;if(e.secret===void 0)throw new y("secretVerifier requires secret to be defined");if(typeof e.secret=="string"){let s=new TextEncoder().encode(e.secret);r=new Uint8Array(s)}else r=e.secret;let{payload:n}=await yw(t,r,{issuer:e.issuer,audience:e.audience});return n},"secretVerifier");function AE(t){let e=ve.instance,n=`/.well-known/oauth-protected-resource${t.pathname}`;return gt.some(a=>a instanceof $o)?!0:e.routeData.routes.some(a=>{let u=a.pathPattern||a.path;try{return new Ms({pathname:u}).test({pathname:n})}catch{return!1}})}i(AE,"ensureOAuthResourceMetadataRouteExists");var Be=i(async(t,e,r,n)=>{w("policy.inbound.open-id-jwt-auth");let o=r.authHeader??"Authorization",s=t.headers.get(o),a="bearer ",u=i(g=>M.unauthorized(t,e,{detail:g}),"unauthorizedResponse");if(!r.jwkUrl&&!r.secret)throw new y(`OpenIdJwtInboundPolicy policy '${n}': One of 'jwkUrl' or 'secret' options are required.`);if(r.jwkUrl&&r.secret)throw new y(`OpenIdJwtInboundPolicy policy '${n}': Only one of 'jwkUrl' and 'secret' options should be provided.`);let c=r.jwkUrl?$E(n,e):OE,d=await i(async()=>{if(!s){let h=new URL(t.url);if(r.oAuthResourceMetadataEnabled&&AE(h)){let v=new URL(`/.well-known/oauth-protected-resource${h.pathname}`,h.origin);return M.unauthorized(t,e,{detail:"Bearer token required"},{"WWW-Authenticate":`resource_metadata=${v.toString()}`})}return u("No authorization header")}if(s.toLowerCase().indexOf(a)!==0)return u("Invalid bearer token format for authorization header");let g=s.substring(a.length);if(!g||g.length===0)return u("No bearer token on authorization header");try{return await c(g,r)}catch(h){let v=new URL(t.url);return"code"in h&&h.code==="ERR_JWT_EXPIRED"?e.log.warn(`Expired token used on url: ${v.pathname} `,h):e.log.warn(`Invalid token on: ${t.method} ${v.pathname}`,h),u("Invalid token")}},"getJwtOrRejectedResponse")();if(d instanceof Response)return r.allowUnauthenticatedRequests===!0?t:d;let p=r.subPropertyName??"sub",m=d[p];return m?(t.user={sub:m,data:d},t):u(`Token is not valid, no '${p}' property found.`)},"OpenIdJwtInboundPolicy");var NE=i(async(t,e,r,n)=>(w("policy.inbound.auth0-jwt-auth"),Be(t,e,{issuer:`https://${r.auth0Domain}/`,audience:r.audience,jwkUrl:`https://${r.auth0Domain}/.well-known/jwks.json`,allowUnauthenticatedRequests:r.allowUnauthenticatedRequests,oAuthResourceMetadataEnabled:r.oAuthResourceMetadataEnabled},n)),"Auth0JwtInboundPolicy");var bw=new Map;function LE(t){let e=[],r=0;for(;r<t.length;){if(t[r]==="."){r++;continue}if(t[r]==="["){for(r++;r<t.length&&/\s/.test(t[r]);)r++;let n=t[r];if(n!=='"'&&n!=="'"){for(;r<t.length&&t[r]!=="]";)r++;r++;continue}r++;let o=r;for(;r<t.length&&t[r]!==n;)r++;let s=t.substring(o,r);for(e.push(s),r++;r<t.length&&/\s/.test(t[r]);)r++;t[r]==="]"&&r++}else{let n=r;for(;r<t.length&&t[r]!=="."&&t[r]!=="[";)r++;let o=t.substring(n,r).trim();o.length>0&&e.push(o)}}return e}i(LE,"parsePropertyPath");function Xs(t,e){let r="$authzen-prop(";if(!t.startsWith(r)||!t.endsWith(")"))return t;let n=t.slice(r.length,-1),o=bw.get(n);o||(o=LE(n),bw.set(n,o));let s=e;for(let a of o){if(s==null)return;typeof s.get=="function"?s=s.get(a):s=s[a]}return s}i(Xs,"evaluateAuthzenProp");var vw=Symbol("AUTHZEN_CONTEXT_DATA_52a5cf22-d922-4673-9815-6dc3d49071d9"),rf=class t extends xe{static{i(this,"AuthZenInboundPolicy")}#e;#t;constructor(e,r){if(super(e,r),ae(e,r).required("authorizerHostname","string").optional("authorizerAuthorizationHeader","string").optional("subject","object").optional("resource","object").optional("action","object").optional("throwOnError","boolean"),e.subject&&!e.subject.type)throw new y(`${this.policyType} '${this.policyName}' - subject.type is required.`);if(e.subject&&!e.subject.id)throw new y(`${this.policyType} '${this.policyName}' - subject.id is required.`);if(e.resource&&!e.resource.type)throw new y(`${this.policyType} '${this.policyName}' - resource.type is required.`);if(e.resource&&!e.resource.id)throw new y(`${this.policyType} '${this.policyName}' - resource.id is required.`);if(e.action&&!e.action.name)throw new y(`${this.policyType} '${this.policyName}' - action.name is required.`);this.#e=(e.authorizerHostname.startsWith("https://")?e.authorizerHostname:`https://${e.authorizerHostname}`)+"/access/v1/evaluation";try{new URL(this.#e)}catch(n){throw new y(`${this.policyType} '${this.policyName}' - authorizerUrl '${this.#e}' is not valid
134
+ `+d});let p=Math.floor((typeof u=="number"?u:Date.now())/1e3)-r.timestamp;if(o>0&&p>o)throw new $t(e,t,{message:"Timestamp outside the tolerance zone"});return!0}i(gE,"validateComputedSignature");function hE(t,e){return typeof t!="string"?null:t.split(",").reduce((r,n)=>{let o=n.split("=");return o[0]==="t"&&(r.timestamp=parseInt(o[1],10)),o[0]===e&&r.signatures.push(o[1]),r},{timestamp:-1,signatures:[]})}i(hE,"parseHeader");function yE(t,e){if(t.length!==e.length)return!1;let r=t.length,n=0;for(let o=0;o<r;++o)n|=t.charCodeAt(o)^e.charCodeAt(o);return n===0}i(yE,"secureCompare");async function bE(t,e){let r=new TextEncoder,n=await crypto.subtle.importKey("raw",r.encode(e),{name:"HMAC",hash:{name:"SHA-256"}},!1,["sign"]),o=await crypto.subtle.sign("hmac",n,r.encode(t)),s=new Uint8Array(o),a=new Array(s.length);for(let u=0;u<s.length;u++)a[u]=Fm[s[u]];return a.join("")}i(bE,"computeHMACSignatureAsync");var Fm=new Array(256);for(let t=0;t<Fm.length;t++)Fm[t]=t.toString(16).padStart(2,"0");function ae(t,e,r="policy",n){let o=`${r} '${e}'`;if(!ar(t))throw new y(`Options on ${o} is expected to be an object. Received the type '${typeof t}'.`);let s=i((c,l,d)=>{let p=t[c],m=n?`${n}.${String(c)}`:String(c);if(!(d&&p===void 0)){if(p===void 0)throw new y(`Value of '${m}' on ${o} is required, but no value was set. If using an environment variable, check that it is set correctly.`);if(l==="array"){if(!Array.isArray(p))throw new y(`Value of '${m}' on ${o} must be an array. Received type ${typeof p}.`)}else if(typeof p!==l)throw new y(`Value of '${m}' on ${o} must be of type ${l}. Received type ${typeof p}.`);if(typeof p=="string"&&p.length===0)throw new y(`Value of '${m}' on ${o} must be a non-empty string. The value received is empty. If using an environment variable, check that it is set correctly.`);if(typeof p=="number"&&isNaN(p))throw new y(`Value of '${m}' on ${o} must be valid number. If using an environment variable, check that it is set correctly.`)}},"validate"),a=i((c,l)=>(s(c,l,!0),{optional:a,required:u}),"optional"),u=i((c,l)=>(s(c,l,!1),{optional:a,required:u}),"required");return{optional:a,required:u}}i(ae,"optionValidator");var Lo=class extends xe{static{i(this,"StripeWebhookVerificationInboundPolicy")}constructor(e,r){super(e,r),w("policy.inbound.stripe-webhook-verification")}async handler(e,r){ae(this.options,this.policyName).required("signingSecret","string").optional("tolerance","number");let n=e.headers.get("stripe-signature");try{let o=await e.clone().text();await ow(o,n,this.options.signingSecret)}catch(o){let s=o.message;if(o.type&&o.type==="StripeSignatureVerificationError"){let a=o.message,c=/Note:(.*)/g.exec(a);s=c?c[1].trim():a,s.startsWith("No signatures found matching the expected signature for payload")&&(s="The Stripe Webhook Signature Secret provided is incorrect and does not match to the signature on the event received. Make sure your Zuplo configuration is correct.")}return r.log.error("Error validating stripe webhook",s),M.badRequest(e,r,{title:"Webhook Error",detail:s})}return e}};function iw(t){return t!==null&&typeof t=="object"&&"id"in t&&Xe(t.id)&&"type"in t&&Xe(t.type)}i(iw,"isStripeWebhookEvent");var vE={getSubscription:i(async({subscriptionId:t,stripeSecretKey:e,logger:r})=>{let n=await W.fetch(`https://api.stripe.com/v1/subscriptions/${t}`,{headers:{Authorization:`Bearer ${e}`}}),o=await n.json();if(n.status!==200){let s="Error retrieving subscription from Stripe API.";throw r.error(s,o),new q(s)}return o},"getSubscription"),getCustomer:i(async({customerId:t,stripeSecretKey:e,logger:r})=>{let n=await W.fetch(`https://api.stripe.com/v1/customers/${t}`,{headers:{Authorization:`Bearer ${e}`}}),o=await n.json();if(n.status!==200){let s="Error retrieving customer from Stripe API.";throw r.error(s,o),new q(s)}return o},"getCustomer"),getUpcomingInvoice:i(async({customerId:t,stripeSecretKey:e,logger:r})=>{let n=await W.fetch(`https://api.stripe.com/v1/invoices/upcoming?customer=${t}`,{headers:{Authorization:`Bearer ${e}`}}),o=await n.json();if(n.status!==200){let s="Error retrieving customer upcoming invoice from Stripe API.";throw r.error(s,o),new q(s)}return o},"getUpcomingInvoice")},Ws=vE;var Hm="https://api-key-management-service-eq7z4lly2a-ue.a.run.app",sw="My API Key";async function aw({apiKeyBucketName:t,stripeSubscriptionId:e,stripeProductId:r,stripeCustomerId:n,managerEmail:o,managerSub:s,context:a}){let{authApiJWT:u}=R.instance,c=new URL(`/v1/buckets/${t}/consumers`,Hm);c.searchParams.set("with-api-key","true");let l=crypto.randomUUID(),d={name:l,description:sw,tags:{subscriptionExternalId:e,planExternalIds:[r]},metadata:{stripeSubscriptionId:e,stripeProductId:r,stripeCustomerId:n},managers:[{sub:s,email:o}]},p=await Te({retryDelayMs:5,retries:2,logger:re.getLogger(a)},c.toString(),{method:"POST",headers:{Authorization:`Bearer ${u}`,"content-type":"application/json"},body:JSON.stringify(d)}),m=await p.json();if(p.status!==200){let g="Error creating API Key Consumer";throw a.log.error(g,m),new q(g)}return a.log.info("Successfully created API Key Consumer",{consumerId:l,stripeSubscriptionId:e,stripeProductId:r}),l}i(aw,"createConsumer");async function uw({apiKeyBucketName:t,stripeSubscriptionId:e,stripeProductId:r,stripeCustomerId:n,managerEmail:o,context:s}){let{authApiJWT:a}=R.instance,u=new URL(`/v1/buckets/${t}/consumers`,Hm);u.searchParams.set("with-api-key","true");let c=crypto.randomUUID(),l={name:c,description:sw,tags:{subscriptionExternalId:e,planExternalIds:[r]},metadata:{stripeSubscriptionId:e,stripeProductId:r,stripeCustomerId:n},managers:[o]},d=await Te({retryDelayMs:5,retries:2,logger:re.getLogger(s)},u.toString(),{method:"POST",headers:{Authorization:`Bearer ${a}`,"content-type":"application/json"},body:JSON.stringify(l)}),p=await d.json();if(d.status!==200){let m="Error creating API Key Consumer";throw s.log.error(m,p),new q(m)}return s.log.info("Successfully created API Key Consumer with Manager Invite",{consumerId:c,stripeSubscriptionId:e,stripeProductId:r}),c}i(uw,"createConsumerInvite");async function cw({apiKeyBucketName:t,consumerId:e,context:r}){let{authApiJWT:n}=R.instance,o=new URL(`/v1/buckets/${t}/consumers/${e}`,Hm);o.searchParams.set("with-api-key","true");let s=await Te({retryDelayMs:5,retries:2,logger:re.getLogger(r)},o.toString(),{method:"DELETE",headers:{Authorization:`Bearer ${n}`,"content-type":"application/json"},body:JSON.stringify({})});if(s.status!==204){let a=await s.json(),u="Error invalidating API Key Consumer";throw r.log.error(u,a),new q(u)}return r.log.info(`Successfully invalidated API Key Consumer '${e}`),e}i(cw,"deleteConsumer");async function lw({context:t,stripeSubscriptionId:e,stripeProductId:r,customerKey:n,meteringBucketId:o,meteringBucketRegion:s,customerExternalId:a,subscriptionStatus:u,metadata:c,trial:l}){let d={status:u,type:"periodic",renewalStrategy:"monthly",region:s,subscriptionExternalId:e,planExternalIds:[r],customerKey:n,customerExternalId:a,metadata:c,trialEndDate:l?l.trialEndDate:void 0,trialStartDate:l?l.trialStartDate:void 0,trialEndStatus:l?l.trialEndStatus:void 0},{authApiJWT:p,meteringServiceUrl:m}=R.instance;if(!_r(p))throw new ue("No Zuplo JWT token set.");let g=await Te({retryDelayMs:5,retries:2,logger:re.getLogger(t)},`${m}/internal/v1/metering/${o}/subscriptions`,{headers:{Authorization:`Bearer ${p}`,"Content-Type":"application/json","zp-rid":t.requestId},method:"POST",body:JSON.stringify(d)});if(!g.ok){let h=`Unable to create a monetization subscription for Stripe subscription '${e}'.`,v,b="";try{v=await g.json(),b=v.detail??v.title}catch{v={type:"https://zup.fail/http-status/500",title:"Internal Server Error",status:g.status,detail:g.statusText}}throw t.log.error(h,v),new q(`${h} ${b}`)}t.log.info("Successfully created monetization subscription.",d)}i(lw,"createSubscription");async function Xr({context:t,meteringSubscriptionId:e,meteringBucketId:r,requestBody:n}){let{authApiJWT:o,meteringServiceUrl:s}=R.instance;if(!_r(o))throw new ue("No Zuplo JWT token set.");let a=await Te({retryDelayMs:5,retries:2,logger:re.getLogger(t)},`${s}/internal/v1/metering/${r}/subscriptions/${e}`,{headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json","zp-rid":t.requestId},method:"PATCH",body:JSON.stringify(n)});if(!a.ok){let u=`Unable to update monetization subscription with: '${JSON.stringify(n)}'.`,c,l="";try{c=await a.json(),l=c.detail??c.title}catch{c={type:"https://zup.fail/http-status/500",title:"Internal Server Error",status:a.status,detail:a.statusText}}throw t.log.error(u,c),new q(`${u} ${l}`)}t.log.info(`Successfully updated monetization subscription with: '${JSON.stringify(n)}'.`)}i(Xr,"updateSubscription");async function Yr({context:t,stripeSubscriptionId:e,stripeCustomerId:r,meteringBucketId:n}){let{authApiJWT:o,meteringServiceUrl:s}=R.instance;if(!_r(o))throw new ue("No Zuplo JWT token set.");let a=await Te({retryDelayMs:5,retries:2,logger:re.getLogger(t)},`${s}/internal/v1/metering/${n}/subscriptions?subscriptionExternalId=${e}`,{headers:{Authorization:`Bearer ${o}`,"zp-rid":t.requestId},method:"GET"});if(!a.ok){let c=`Unable to retrieve the monetization subscription for Stripe subscription '${e}'.`,l,d="";try{l=await a.json(),d=l.detail??l.title}catch{l={type:"https://zup.fail/http-status/500",title:"Internal Server Error",status:a.status,detail:a.statusText}}throw t.log.error(c,l),new q(`${c} ${d}`)}let u=await a.json();if(u.data.length===0){let c=`Subscription was not found for Stripe subscription '${e}' and the event was ignored by Zuplo.`;throw t.log.error(c),new q(c)}if(u.data[0].customerExternalId!==r){let c=`Subscription was not found for Stripe customer '${r}' and the event was ignored by Zuplo.`;throw t.log.error(c),new q(c)}return u.data[0]}i(Yr,"getSubscription");var _e="Skipping since we're unable to process the webhook event.",or="Successfully processed the webhook event",We="See https://zuplo.com/docs/articles/monetization-troubleshooting for more details.";function Ks(t){return t.replaceAll("_","-")}i(Ks,"stripeStatusToMeteringStatus");function xr(t){return new Date(t*1e3).toISOString()}i(xr,"unixTimestampToISOString");async function Bm(t,e,r,n){let o=r.data.object.id;if(!o)return e.log.warn(`Invalid Stripe webhook event. Expected event '${r.id}' to have '.data.object.id' be the subscription ID.`),M.ok(t,e,{title:_e,detail:"Invalid Stripe webhook event. Expected '.data.object.id' to be the subscription ID."});let s=r.data.object.plan;if(!s||!s.product)return e.log.warn(`Invalid Stripe API result. Expected event '${r.id}' to have a plan data.`),M.ok(t,e,{title:_e,detail:"Invalid Stripe API result. Expected event to have a plan data."});let a=r.data.object.customer;if(!a)return e.log.warn(`Invalid Stripe webhook event. Expected '.data.object.customer' to be provided by event '${r.id}'`),M.ok(t,e,{title:_e,detail:"Invalid Stripe webhook event. Expected '.data.object.customer' to be provided"});if(r.data.object.metadata&&r.data.object.metadata.zuplo_created_by_deploymentName&&r.data.object.metadata.zuplo_created_by_deploymentName!==R.instance.deploymentName)return e.log.warn(`Subscription event '${r.id}' will not be handled since it was not issued for this Zuplo environment. It was intended for '${r.data.object.metadata.zuplo_created_by_deploymentName}'.`),M.ok(t,e,{title:_e,detail:`This subscription event is not meant to be handled by this environment's Stripe monetization plugin. It was intended for '${r.data.object.metadata.zuplo_created_by_deploymentName}'. This can happen because of a misconfiguration of Stripe or your Zuplo API.`+We});let u=s.product,c,l,d;try{if(r.data.object.metadata&&r.data.object.metadata.zuplo_created_by_email&&r.data.object.metadata.zuplo_created_by_sub)l=r.data.object.metadata.zuplo_created_by_email,d=r.data.object.metadata.zuplo_created_by_sub,c=await aw({apiKeyBucketName:n.apiKeyBucketName,stripeProductId:u,stripeSubscriptionId:o,stripeCustomerId:a,managerEmail:l,managerSub:d,context:e});else{let p=await Ws.getCustomer({logger:e.log,stripeSecretKey:n.stripeSecretKey,customerId:a});if(!p.email)return e.log.warn(`Invalid Stripe API result. Expected customer '${a}' to contain email address.`),M.ok(t,e,{title:_e,detail:"Invalid Stripe API result. Expected customer to contain email address."});c=await uw({apiKeyBucketName:n.apiKeyBucketName,stripeProductId:u,stripeSubscriptionId:o,stripeCustomerId:a,managerEmail:p.email,context:e})}}catch(p){return e.log.warn(`Failed to create API Key Consumer. Error: ${p.message}`),M.ok(t,e,{title:_e,detail:p.message})}if(!c)return M.ok(t,e,{title:_e,detail:"No API Key Consumer was created, skipping creation of subscription."});try{let p=Ks(r.data.object.status),m;l&&d&&(m={subscriber:{sub:d,email:l}});let g;r.data.object.trial_end!==null&&r.data.object.trial_start!==null&&r.data.object.trial_settings&&r.data.object.trial_settings.end_behavior&&(r.data.object.trial_settings.end_behavior.missing_payment_method==="cancel"||r.data.object.trial_settings.end_behavior.missing_payment_method==="pause")&&(g={trialEndStatus:r.data.object.trial_settings.end_behavior.missing_payment_method,trialEndDate:xr(r.data.object.trial_end),trialStartDate:xr(r.data.object.trial_start)}),await lw({context:e,stripeProductId:u,stripeSubscriptionId:o,customerKey:c,meteringBucketId:n.meteringBucketId,meteringBucketRegion:n.meteringBucketRegion,customerExternalId:a,subscriptionStatus:p,metadata:m,trial:g})}catch(p){return await cw({apiKeyBucketName:n.apiKeyBucketName,consumerId:c,context:e}),M.ok(t,e,{title:_e,detail:p.message})}return M.ok(t,e,{title:or})}i(Bm,"onCustomerSubscriptionCreated");async function Gm(t,e,r,n){let o=r.data.object.id;if(!o)return e.log.warn(`Invalid Stripe webhook event. Expected event '${r.id}' to have '.data.object.id' be the subscription ID.`),M.ok(t,e,{title:_e,detail:"Invalid Stripe webhook event. Expected '.data.object.id' to be the subscription ID."});let s=r.data.object.customer;if(!s)return e.log.warn(`Invalid Stripe webhook event. Expected '.data.object.customer' to be provided by event '${r.id}'`),M.ok(t,e,{title:_e,detail:"Invalid Stripe webhook event. Expected '.data.object.customer' to be provided"});if(r.data.object.metadata&&r.data.object.metadata.zuplo_created_by_deploymentName&&r.data.object.metadata.zuplo_created_by_deploymentName!==R.instance.deploymentName)return e.log.warn(`Subscription event '${r.id}' will not be handled since it was not issued for this Zuplo environment. It was intended for '${r.data.object.metadata.zuplo_created_by_deploymentName}'.`),M.ok(t,e,{title:_e,detail:`This 'customer.subscription.deleted' event is not meant to be handled by this environment's Stripe monetization plugin. It was intended for '${r.data.object.metadata.zuplo_created_by_deploymentName}'.This can happen because of a misconfiguration of Stripe or your Zuplo API.`+We});try{let a=await Yr({context:e,stripeSubscriptionId:o,stripeCustomerId:s,meteringBucketId:n.meteringBucketId});await Xr({context:e,meteringSubscriptionId:a.id,meteringBucketId:n.meteringBucketId,requestBody:{status:"canceled",planExternalIds:a.planExternalIds}})}catch(a){return M.ok(t,e,{title:_e,detail:`The event 'customer.subscription.deleted' could not be processed. ${a.message} This can happen because of a misconfiguration of Stripe or your Zuplo API. `+We})}return M.ok(t,e,{title:or})}i(Gm,"onCustomerSubscriptionDeleted");async function Vm(t,e,r,n){let o=r.data.object.id;if(!o)return e.log.warn(`Invalid Stripe webhook event. Expected event '${r.id}' to include '.data.object.id' as the subscription ID.`),M.ok(t,e,{title:_e,detail:"Invalid Stripe webhook event. Expected '.data.object.id' to be the subscription ID."});let s=r.data.object.customer;if(!s)return e.log.warn(`Invalid Stripe webhook event. Expected '.data.object.customer' to be provided by event '${r.id}'`),M.ok(t,e,{title:_e,detail:"Invalid Stripe webhook event. Expected '.data.object.customer' to be provided"});if(r.data.object.metadata&&r.data.object.metadata.zuplo_created_by_deploymentName&&r.data.object.metadata.zuplo_created_by_deploymentName!==R.instance.deploymentName)return e.log.warn(`Subscription event '${r.id}' will not be handled since it was not issued for this Zuplo environment. It was intended for '${r.data.object.metadata.zuplo_created_by_deploymentName}'.`),M.ok(t,e,{title:_e,detail:`This 'customer.subscription.updated' event is not meant to be handled by this environment's Stripe monetization plugin. It was intended for '${r.data.object.metadata.zuplo_created_by_deploymentName}'.This can happen because of a misconfiguration of Stripe or your Zuplo API.`+We});if(r.data.previous_attributes){let a=r.data.previous_attributes;if(a.status&&a.status!==r.data.object.status){try{e.log.debug(`Processing subscription status change from Stripe event '${r.id}'.`);let u=await Yr({context:e,stripeSubscriptionId:o,stripeCustomerId:s,meteringBucketId:n.meteringBucketId}),c=Ks(r.data.object.status),l;a.trial_end&&a.trial_end!==r.data.object.trial_end&&r.data.object.trial_end!==null&&(l=xr(r.data.object.trial_end)),await Xr({context:e,meteringSubscriptionId:u.id,meteringBucketId:n.meteringBucketId,requestBody:{status:c,planExternalIds:u.planExternalIds,trialEndDate:l}})}catch(u){return M.ok(t,e,{title:_e,detail:`The event 'customer.subscription.updated' could not be processed. ${u.message} This can happen because of a misconfiguration of Stripe or your Zuplo API. However, it also could be a temporary condition that happens when a subscription is created due to events being sent out of order. `+We})}return M.ok(t,e,{title:or})}if(a.plan&&a.plan.product!==r.data.object.plan.product){try{e.log.debug(`Processing subscription plan change from Stripe event '${r.id}'.`);let u=await Yr({context:e,stripeSubscriptionId:o,stripeCustomerId:s,meteringBucketId:n.meteringBucketId}),c=r.data.object.plan.product,d=(await Ws.getUpcomingInvoice({customerId:s,logger:e.log,stripeSecretKey:n.stripeSecretKey})).lines.data.filter(m=>m.proration&&m.price.product===c),p=0;d.length===0?e.log.warn(`The plan change does not include proration details. Subscription event '${r.id}'`):p=parseFloat(d[0].unit_amount_excluding_tax)/d[0].price.unit_amount,await Xr({context:e,meteringSubscriptionId:u.id,meteringBucketId:n.meteringBucketId,requestBody:{status:u.status,planExternalIds:[c],prorate:p}})}catch(u){return M.ok(t,e,{title:_e,detail:`The event 'customer.subscription.updated' could not be processed. ${u.message} This can happen because of a misconfiguration of Stripe or your Zuplo API. However, it also could be a temporary condition that happens when a subscription is created due to events being sent out of order. `+We})}return M.ok(t,e,{title:or})}if((a.cancel_at||a.cancel_at===null)&&a.cancel_at!==r.data.object.cancel_at&&a.cancel_at_period_end&&a.cancel_at_period_end!==r.data.object.cancel_at_period_end&&(a.canceled_at||a.canceled_at===null)&&a.canceled_at!==r.data.object.canceled_at||a.cancellation_details&&(a.cancellation_details.comment||a.cancellation_details.comment===null||a.cancellation_details.feedback||a.cancellation_details.feedback===null||a.cancellation_details.reason||a.cancellation_details.reason===null)){try{e.log.debug(`Processing subscription cancellation details from Stripe event '${r.id}'.`);let u=await Yr({context:e,stripeSubscriptionId:o,stripeCustomerId:s,meteringBucketId:n.meteringBucketId}),c={cancellation:{cancel_at:r.data.object.cancel_at?xr(r.data.object.cancel_at):null,cancel_at_period_end:r.data.object.cancel_at_period_end,canceled_at:r.data.object.canceled_at?xr(r.data.object.canceled_at):null,cancellation_details:r.data.object.cancellation_details}},l;u.metadata?l={...u.metadata,...c}:l=c,await Xr({context:e,meteringSubscriptionId:u.id,meteringBucketId:n.meteringBucketId,requestBody:{status:u.status,planExternalIds:u.planExternalIds,metadata:l}})}catch(u){return M.ok(t,e,{title:_e,detail:`The event 'customer.subscription.updated' could not be processed. ${u.message} This can happen because of a misconfiguration of Stripe or your Zuplo API. However, it also could be a temporary condition that happens when a subscription is created due to events being sent out of order. `+We})}return M.ok(t,e,{title:or})}}return e.log.warn(`This update event '${r.id}' is not supported by Stripe monetization plugin webhook.`),M.ok(t,e,{title:_e,detail:"This 'customer.subscription.updated' event could not be processed. The Stripe monetization plugin only supports update events for subscription plan changes or subscription status changes."+We})}i(Vm,"onCustomerSubscriptionUpdated");var dw=class extends ei{constructor(r){super();this.options=r;w("monetization.stripe")}static{i(this,"StripeMonetizationPlugin")}registerRoutes({router:r}){let n=i(async(u,c)=>{if(this.options.__testMode===!0)return c.log.warn("Received Stripe webhook event of in test mode."),"success";let{meteringBucketId:l,apiKeyBucketName:d}=this.options;if(!l)if(Se.ZUPLO_METERING_SERVICE_BUCKET_ID)l=Se.ZUPLO_METERING_SERVICE_BUCKET_ID;else throw new y("StripeMonetizationPlugin - No 'meteringBucketId' property provided");if(!d)if(Se.ZUPLO_API_KEY_SERVICE_BUCKET_NAME)d=Se.ZUPLO_API_KEY_SERVICE_BUCKET_NAME;else throw new y("StripeMonetizationPlugin - No 'apiKeyBucketName' property provided");if(!R.instance.build.ACCOUNT_NAME)throw new ue("Build environment is not configured correctly. Expected 'ACCOUNT_NAME' to be set.");let p=this.options.primaryDataRegion??"us-central1";if(!wE(p))throw new y(`StripeMonetizationPlugin - The value '${p}' on the property 'primaryDataRegion' is invalid.`);let m=await u.json();if(!iw(m))return M.ok(u,c,{title:_e,detail:"The event payload received was not in the expected format. This can happen because of a misconfiguration of Stripe or your Zuplo API. "+We});switch(c.log.info(`Received Stripe webhook event of type '${m.type}' with ID '${m.id}'.`),m.type){case"customer.subscription.created":return await Bm(u,c,m,{meteringBucketId:l,apiKeyBucketName:d,meteringBucketRegion:p,stripeSecretKey:this.options.stripeSecretKey});case"customer.subscription.updated":return await Vm(u,c,m,{meteringBucketId:l,apiKeyBucketName:d,meteringBucketRegion:p,stripeSecretKey:this.options.stripeSecretKey});case"customer.subscription.deleted":return await Gm(u,c,m,{meteringBucketId:l});default:return M.ok(u,c,{title:_e,detail:`Event '${m.type}' could not be processed because it is not supported by Stripe monetization plugin webhook. This can happen because of a misconfiguration of Stripe or your Zuplo API.`+We})}},"stripeWebhookHandler"),o=Zg({inboundPolicies:[new Lo({signingSecret:this.options.webhooks.signingSecret,tolerance:this.options.webhooks.tolerance},"stripe-webhook-verification")]});ae(this.options.webhooks,"StripeMonetizationPlugin","plugin").required("signingSecret","string").optional("tolerance","number");let s=new Le({processors:[qe,o],handler:n}),a=new Me({label:"PLUGIN_STRIPE_WEBHOOK_ROUTE",methods:["POST"],path:this.options.webhooks.routePath??"/__plugins/stripe/webhooks",systemRouteName:"stripe-plugin"});r.addRoute(a,s.execute)}};function wE(t){return t!==null&&typeof t=="string"&&["us-central1","us-east1","europe-west4"].includes(t)}i(wE,"isMetricsRegion");var mw=new WeakMap,pw={},Jm=class{static{i(this,"AmberfloMeteringPolicy")}static setRequestProperties(e,r){mw.set(e,r)}};async function xE(t,e,r,n){if(w("policy.inbound.amberflo-metering"),!r.statusCodes)throw new y(`Invalid AmberfloMeterInboundPolicy '${n}': options.statusCodes must be an array of HTTP status code numbers`);let o=Pt(r.statusCodes);return e.addResponseSendingFinalHook(async s=>{if(o.includes(s.status)){let a=mw.get(e),u=r.customerId;if(r.customerIdPropertyPath){if(!t.user)throw new q(`Unable to apply customerIdPropertyPath '${r.customerIdPropertyPath}' as request.user is 'undefined'.`);u=At(t.user,r.customerIdPropertyPath,"customerIdPropertyPath")}let c=a?.customerId??u;if(!c){e.log.error(`Error in AmberfloMeterInboundPolicy '${n}': customerId cannot be undefined`);return}let l=a?.meterApiName??r.meterApiName;if(!l){e.log.error(`Error in AmberfloMeterInboundPolicy '${n}': meterApiName cannot be undefined`);return}let d=a?.meterValue??r.meterValue;if(!d){e.log.error(`Error in AmberfloMeterInboundPolicy '${n}': meterValue cannot be undefined`);return}let p={customerId:c,meterApiName:l,meterValue:d,meterTimeInMillis:Date.now(),dimensions:Object.assign(r.dimensions??{},a?.dimensions)},m=pw[r.apiKey];if(!m){let g=r.apiKey,h=t.headers.get("zm-test-id")??"";m=new ce("amberflo-ingest-meter",10,async v=>{try{let b=r.url??"https://app.amberflo.io/ingest",S=await W.fetch(b,{method:"POST",body:JSON.stringify(v),headers:{"content-type":"application/json","x-api-key":g,"zm-test-id":h}});S.ok||e.log.error(`Unexpected response in AmberfloMeteringInboundPolicy '${n}'. ${S.status}: ${await S.text()}`)}catch(b){throw e.log.error(`Error in AmberfloMeteringInboundPolicy '${n}': ${b.message}`),b}}),pw[g]=m}m.enqueue(p),e.waitUntil(m.waitUntilFlushed())}}),t}i(xE,"AmberfloMeteringInboundPolicy");var fw={},Wm=Symbol("openmeter-meters"),Km=class extends xe{static{i(this,"OpenMeterInboundPolicy")}#e;#t;#n;#r;#o;#i;constructor(e,r){if(super(e,r),w("policy.inbound.openmeter-metering"),ae(this.options,this.policyName).required("apiKey","string").optional("apiUrl","string").optional("eventSource","string").optional("requiredEntitlements","array").optional("subjectPath","string"),this.options.meter!==void 0){if(typeof this.options.meter!="object"||this.options.meter===null)throw new y(`Invalid OpenMeterInboundPolicy '${this.policyName}': options.meter must be an object or array. Received type ${typeof this.options.meter}.`);let n=Array.isArray(this.options.meter)?this.options.meter:[this.options.meter];for(let o of n)if(!o.type)throw new y(`Invalid OpenMeterInboundPolicy '${this.policyName}': meter.type is required`)}if(this.options.meterOnStatusCodes!==void 0&&typeof this.options.meterOnStatusCodes!="string"&&!Array.isArray(this.options.meterOnStatusCodes))throw new y(`Invalid OpenMeterInboundPolicy '${this.policyName}': options.meterOnStatusCodes must be a string or array. Received type ${typeof this.options.meterOnStatusCodes}.`);this.#t=this.options.eventSource||"api-gateway",this.#n=this.options.apiUrl||"https://openmeter.cloud",this.#r=`${this.#n}/api/v1/events`,this.#e=new Headers({"content-type":"application/cloudevents-batch+json",Authorization:`Bearer ${e.apiKey}`}),this.#i=Pt(this.options.meterOnStatusCodes||"200-299"),this.#o=this.options.subjectPath||".sub"}async handler(e,r){if(this.options.requiredEntitlements&&this.options.requiredEntitlements.length>0){let n=this.getSubject(e);if(!n)r.log.error(`Error in OpenMeterInboundPolicy '${this.policyName}': subject cannot be undefined for entitlement checking`);else try{let o=this.options.requiredEntitlements.map(u=>this.checkEntitlement(n,u,r).then(c=>({featureKey:u,result:c}))),s=await Promise.all(o),a=null;for(let{result:u,featureKey:c}of s)!u.hasAccess&&!a&&(a={...u,featureKey:c});if(a)return r.log.warn(`OpenMeterInboundPolicy '${this.policyName}' blocked request due to insufficient entitlements on feature '${a.featureKey}' for subject '${n}'.`),M.tooManyRequests(e,r,{detail:"Your subscription has insufficient entitlements for this request."})}catch(o){let s=o instanceof Error?o.message:String(o);r.log.error(`Error during entitlement checking in OpenMeterInboundPolicy '${this.policyName}': ${s}`)}}return this.setupMetering(e,r),e}getSubject(e){if(!e.user)throw new q(`OpenMeterInboundPolicy '${this.policyName}' requires a user to be authenticated. Ensure you have an authentication policy set before this policy?`);return At(e.user,this.#o,"subjectPath")}async checkEntitlement(e,r,n){let o=`${this.#n}/api/v1/subjects/${encodeURIComponent(e)}/entitlements/${encodeURIComponent(r)}/value`,s={"content-type":"application/json"};this.options.apiKey&&(s.authorization=`Bearer ${this.options.apiKey}`);try{let a=await W.fetch(o,{method:"GET",headers:s});return a.ok?await a.json():(n.log.error(`Error checking entitlements in OpenMeterInboundPolicy '${this.policyName}'. ${a.status}: ${await a.text()}`),{hasAccess:!0})}catch(a){let u=a instanceof Error?a.message:String(a);return n.log.error(`Error in OpenMeterInboundPolicy '${this.policyName}': ${u}`),{hasAccess:!0}}}setupMetering(e,r){r.addResponseSendingFinalHook(async n=>{if(this.#i.includes(n.status)){let o=this.getSubject(e);if(!o){r.log.error(`Error in OpenMeterInboundPolicy '${this.policyName}': subject cannot be undefined for metering`);return}let s=de.get(r,Wm)??(this.options.meter?Array.isArray(this.options.meter)?this.options.meter:[this.options.meter]:[]),a=new Date().toISOString();for(let u of s){let c={specversion:"1.0",id:`${r.requestId}-${u.type}`,time:a,source:this.#t,subject:o,...u},l=this.#r,d=fw[l];d||(d=new ce("openmeter-ingest-event",10,async p=>{try{let m=await W.fetch(this.#r,{method:"POST",body:JSON.stringify(p),headers:this.#e});if(m.status!==204){let g=await m.text().catch(()=>"");r.log.error(`Unexpected response in OpenMeterInboundPolicy '${this.policyName}'. ${m.status}`,g)}}catch(m){let g=m instanceof Error?m.message:String(m);throw r.log.error(`Error in OpenMeterInboundPolicy '${this.policyName}': ${g}`),m}}),fw[l]=d),d.enqueue(c),r.waitUntil(d.waitUntilFlushed())}}})}static setMeters(e,r){let n=de.get(e,Wm)||[];de.set(e,Wm,[...n,...Array.isArray(r)?r:[r]])}};var gw="key-metadata-cache-type";function PE(t,e){return e.authScheme===""?t:t.replace(`${e.authScheme} `,"")}i(PE,"getKeyValue");async function Qm(t,e,r,n){if(w("policy.inbound.api-key"),!r.bucketName)if(Se.ZUPLO_API_KEY_SERVICE_BUCKET_NAME)r.bucketName=Se.ZUPLO_API_KEY_SERVICE_BUCKET_NAME;else throw new y(`ApiKeyInboundPolicy '${n}' - no bucketName property provided`);let o={authHeader:r.authHeader??"authorization",authScheme:r.authScheme??"Bearer",bucketName:r.bucketName,cacheTtlSeconds:r.cacheTtlSeconds??60,allowUnauthenticatedRequests:r.allowUnauthenticatedRequests??!1,disableAutomaticallyAddingKeyHeaderToOpenApi:r.disableAutomaticallyAddingKeyHeaderToOpenApi??!1};if(o.cacheTtlSeconds<60)throw new y(`ApiKeyInboundPolicy '${n}' - minimum cacheTtlSeconds value is 60s, '${o.cacheTtlSeconds}' is invalid`);let s=i(S=>o.allowUnauthenticatedRequests?t:M.unauthorized(t,e,{detail:S}),"unauthorizedResponse"),a=t.headers.get(o.authHeader);if(!a)return s("No Authorization Header");if(!a.toLowerCase().startsWith(o.authScheme.toLowerCase()))return s("Invalid Authorization Scheme");let u=PE(a,o);if(!u||u==="")return s("No key present");let c=await RE(u),l=await Pe(n,void 0,o),d=new be(l,e),p=await d.get(c);if(p&&p.isValid===!0)return t.user=p.user,t;if(p&&!p.isValid)return p.typeId!==gw&&re.getLogger(e).error(`ApiKeyInboundPolicy '${n}' - cached metadata has invalid typeId '${p.typeId}'`,p),s("Authorization Failed");let m={key:u},g=new Headers({"content-type":"application/json"});De(g,e.requestId);let h=await Te({retryDelayMs:5,retries:2,logger:re.getLogger(e)},`${R.instance.apiKeyServiceUrl}/v1/$validate/${o.bucketName}`,{method:"POST",headers:g,body:JSON.stringify(m)});if(h.status===401)return e.log.info(`ApiKeyInboundPolicy '${n}' - 401 response from Key Service`),s("Authorization Failed");if(h.status!==200){try{let S=await h.text(),x=JSON.parse(S);e.log.error("Unexpected response from key service",x)}catch{e.log.error("Invalid response from key service")}throw new q(`ApiKeyInboundPolicy '${n}' - unexpected response from Key Service. Status: ${h.status}`)}let v=await h.json(),b={isValid:!0,typeId:gw,user:{apiKeyId:v.id,sub:v.name,data:v.metadata}};return t.user=b.user,d.put(c,b,o.cacheTtlSeconds),t}i(Qm,"ApiKeyInboundPolicy");async function RE(t){let e=new TextEncoder().encode(t),r=await crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(r)).map(s=>s.toString(16).padStart(2,"0")).join("")}i(RE,"hashValue");var IE=Qm;var Xm="ai-gateway-key-metadata-cache-type";function SE(t,e){return e.authScheme===""?t:t.replace(`${e.authScheme} `,"")}i(SE,"getKeyValue");async function kE(t,e,r,n){w("policy.inbound.ai-gateway");let o=Se.ZUPLO_SERVICE_BUCKET_ID;if(!o)throw new y(`AIGatewayAuthInboundPolicy '${n}' - ZUPLO_SERVICE_BUCKET_ID environment variable is required`);let s={authHeader:r.authHeader??"authorization",authScheme:r.authScheme??"Bearer",cacheTtlSeconds:r.cacheTtlSeconds??10};if(s.cacheTtlSeconds<10)throw new y(`AIGatewayAuthInboundPolicy '${n}' - minimum cacheTtlSeconds value is 10s, '${s.cacheTtlSeconds}' is invalid`);let a=i(O=>M.unauthorized(t,e,{detail:O}),"unauthorizedResponse"),u=t.headers.get(s.authHeader);if(!u)return a("No Authorization Header");if(!u.toLowerCase().startsWith(s.authScheme.toLowerCase()))return a("Invalid Authorization Scheme");let c=SE(u,s);if(!c||c==="")return a("No key present");let l=await _E(c),d=await Pe(n,void 0,s),p=new be(d,e),m=await p.get(l);if(m&&m.isValid===!0)return t.user=m.user,t;if(m&&!m.isValid)return m.typeId!==Xm&&re.getLogger(e).error(`AIGatewayAuthInboundPolicy '${n}' - cached metadata has invalid typeId '${m.typeId}'`,m),a("Authorization Failed");let g={key:c},h=new Headers({"content-type":"application/json"});De(h,e.requestId);let v=re.getLogger(e),b=await Te({retryDelayMs:5,retries:2,logger:v},`${R.instance.zuploEdgeApiUrl}/v1/buckets/${o}/validate`,{method:"POST",headers:h,body:JSON.stringify(g)});if(b.status!==200){try{let O=await b.text(),L=JSON.parse(O);v.error("Unexpected response from Gateway service",L)}catch{v.error("Invalid response from Gateway service")}throw new q(`AIGatewayAuthInboundPolicy '${n}' - unexpected response from Gateway Service. Status: ${b.status}`)}let S=await b.json();if(!S.authorized){let O={isValid:!1,typeId:Xm};return p.put(l,O,s.cacheTtlSeconds),a("Authorization Failed")}let x={data:S.metadata,configuration:S.configuration,sub:S.name},$={isValid:!0,typeId:Xm,user:x};return t.user=x,p.put(l,$,s.cacheTtlSeconds),t}i(kE,"AIGatewayAuthInboundPolicy");async function _E(t){let e=new TextEncoder().encode(t),r=await crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(r)).map(s=>s.toString(16).padStart(2,"0")).join("")}i(_E,"hashValue");async function TE(t,e,r,n,o){let s=re.getLogger(r);if(r.custom.streamingUsageHandled===!0)return s.debug("Streaming usage will be handled in streaming transform, skipping sync usage tracker"),t;let u={requests:1},c=0,l=0,d=0,p="",m="";try{let x=await t.clone().json();if(x.usage){l=x.usage.prompt_tokens||0,d=x.usage.completion_tokens||0;let $=x.usage.total_tokens||0;p=x.model||"",m=x.provider||"";let O=await pt(r);c=Tt(p,m,l,d,O,s),s.info("Usage tracked",{userId:e.user?.sub,requestsIncrement:1,tokensUsed:$,promptTokens:l,completionTokens:d,model:p,provider:m,cost:c})}}catch(S){s.debug("Could not track token usage, tracking request only",{error:S})}u.tokens=l+d,u.costs=c,it.setIncrements(r,u);let g=new Headers(t.headers);u.tokens&&g.set("X-Tokens-Used",u.tokens.toString()),c>0&&(g.set("X-Cost-USD",c.toFixed(10)),g.set("X-Model",p)),g.set("X-Requests-Increment","1");let h=e.user;switch(r.analyticsContext.addAnalyticsEvent(1,Qe.AI_GATEWAY_REQUEST_COUNT,{model:p,provider:m,configId:h.configuration.id}),r.analyticsContext.addAnalyticsEvent(parseFloat(c.toFixed(10)),Qe.AI_GATEWAY_COST_SUM,{model:p,provider:m,configId:h.configuration.id}),new URL(e.url).pathname){case"/v1/chat/completions":r.analyticsContext.addAnalyticsEvent(l,Qe.AI_GATEWAY_TOKEN_SUM,{model:p,provider:m,configId:h.configuration.id,tokenType:"prompt"}),r.analyticsContext.addAnalyticsEvent(d,Qe.AI_GATEWAY_TOKEN_SUM,{model:p,provider:m,configId:h.configuration.id,tokenType:"completion"});break;case"/v1/embeddings":r.analyticsContext.addAnalyticsEvent(l,Qe.AI_GATEWAY_TOKEN_SUM,{model:p,provider:m,configId:h.configuration.id,tokenType:"embedding"});break;default:break}return new Response(t.body,{status:t.status,statusText:t.statusText,headers:g})}i(TE,"AIGatewayUsageTrackerPolicy");import{createRemoteJWKSet as CE,jwtVerify as yw}from"jose";import{createLocalJWKSet as EE}from"jose";var Ym=class{constructor(e,r,n){this.cache=r;if(!(e instanceof URL))throw new TypeError("url must be an instance of URL");this.url=new URL(e.href),this.options={agent:n?.agent,headers:n?.headers},this.timeoutDuration=typeof n?.timeoutDuration=="number"?n?.timeoutDuration:5e3,this.cooldownDuration=typeof n?.cooldownDuration=="number"?n?.cooldownDuration:3e4,this.cacheMaxAge=typeof n?.cacheMaxAge=="number"?n?.cacheMaxAge:6e5}static{i(this,"RemoteJWKSet")}url;timeoutDuration;cooldownDuration;cacheMaxAge;jwksTimestamp;pendingFetch;options;local;coolingDown(){return typeof this.jwksTimestamp=="number"?Date.now()<this.jwksTimestamp+this.cooldownDuration:!1}fresh(){return typeof this.jwksTimestamp=="number"?Date.now()<this.jwksTimestamp+this.cacheMaxAge:!1}async getKey(e,r){(!this.local||!this.fresh())&&await this.reload();try{return await this.local(e,r)}catch(n){if(n instanceof ef&&this.coolingDown()===!1)return await this.reload(),this.local(e,r);throw n}}async reload(){this.pendingFetch&&(this.pendingFetch=void 0);let e=new Headers(this.options.headers);e.has("User-Agent")||(e.set("User-Agent",R.instance.systemUserAgent),this.options.headers=Object.fromEntries(e.entries())),this.pendingFetch||=this.fetchJwks(this.url,this.timeoutDuration,this.options).then(r=>{this.local=EE(r),this.jwksTimestamp=Date.now(),this.pendingFetch=void 0}).catch(r=>{throw this.pendingFetch=void 0,r}),await this.pendingFetch}async fetchJwks(e,r,n){let o=await this.cache.get(this.url.href);if(o)return o;let s,a,u=!1;typeof AbortController=="function"&&(s=new AbortController,a=setTimeout(()=>{u=!0,s.abort()},r));let c=await W.fetch(e.href,{signal:s?s.signal:void 0,redirect:"manual",headers:n.headers}).catch(l=>{throw u?new tf("JWKS fetch timed out"):l});if(a!==void 0&&clearTimeout(a),c.status!==200)throw new en("Expected 200 OK from the JSON Web Key Set HTTP response");try{let l=await c.json();return this.cache.put(this.url.href,l,this.cacheMaxAge),l}catch{throw new en("Failed to parse the JSON Web Key Set HTTP response as JSON")}}};function hw(t,e,r){let n=new Ym(t,e,r);return async(o,s)=>n.getKey(o,s)}i(hw,"createRemoteJWKSet");var en=class extends q{static{i(this,"JWKSError")}},ef=class extends en{static{i(this,"JWKSNoMatchingKey")}},tf=class extends en{static{i(this,"JWKSTimeout")}};var Qs={},$E=i((t,e)=>async(r,n)=>{if(!n.jwkUrl||typeof n.jwkUrl!="string")throw new y("Invalid State - jwkUrl not set");if(!Qs[n.jwkUrl]){let s=!1;if("useExperimentalInMemoryCache"in n&&typeof n.useExperimentalInMemoryCache=="boolean"&&(s=n.useExperimentalInMemoryCache),s){let a=await Pe(t,void 0,n),u=new be(a,e);Qs[n.jwkUrl]=hw(new URL(n.jwkUrl),u,n.headers?{headers:n.headers}:void 0)}else Qs[n.jwkUrl]=CE(new URL(n.jwkUrl),n.headers?{headers:n.headers}:void 0)}let{payload:o}=await yw(r,Qs[n.jwkUrl],{issuer:n.issuer,audience:n.audience});return o},"createJwkVerifier"),OE=i(async(t,e)=>{let r;if(e.secret===void 0)throw new y("secretVerifier requires secret to be defined");if(typeof e.secret=="string"){let s=new TextEncoder().encode(e.secret);r=new Uint8Array(s)}else r=e.secret;let{payload:n}=await yw(t,r,{issuer:e.issuer,audience:e.audience});return n},"secretVerifier");function AE(t){let e=ve.instance,n=`/.well-known/oauth-protected-resource${t.pathname}`;return gt.some(a=>a instanceof $o)?!0:e.routeData.routes.some(a=>{let u=a.pathPattern||a.path;try{return new Ms({pathname:u}).test({pathname:n})}catch{return!1}})}i(AE,"ensureOAuthResourceMetadataRouteExists");var Be=i(async(t,e,r,n)=>{w("policy.inbound.open-id-jwt-auth");let o=r.authHeader??"Authorization",s=t.headers.get(o),a="bearer ",u=i(g=>M.unauthorized(t,e,{detail:g}),"unauthorizedResponse");if(!r.jwkUrl&&!r.secret)throw new y(`OpenIdJwtInboundPolicy policy '${n}': One of 'jwkUrl' or 'secret' options are required.`);if(r.jwkUrl&&r.secret)throw new y(`OpenIdJwtInboundPolicy policy '${n}': Only one of 'jwkUrl' and 'secret' options should be provided.`);let c=r.jwkUrl?$E(n,e):OE,d=await i(async()=>{if(!s){let h=new URL(t.url);if(r.oAuthResourceMetadataEnabled&&AE(h)){let v=new URL(`/.well-known/oauth-protected-resource${h.pathname}`,h.origin);return M.unauthorized(t,e,{detail:"Bearer token required"},{"WWW-Authenticate":`resource_metadata=${v.toString()}`})}return u("No authorization header")}if(s.toLowerCase().indexOf(a)!==0)return u("Invalid bearer token format for authorization header");let g=s.substring(a.length);if(!g||g.length===0)return u("No bearer token on authorization header");try{return await c(g,r)}catch(h){let v=new URL(t.url);return"code"in h&&h.code==="ERR_JWT_EXPIRED"?e.log.warn(`Expired token used on url: ${v.pathname} `,h):e.log.warn(`Invalid token on: ${t.method} ${v.pathname}`,h),u("Invalid token")}},"getJwtOrRejectedResponse")();if(d instanceof Response)return r.allowUnauthenticatedRequests===!0?t:d;let p=r.subPropertyName??"sub",m=d[p];return m?(t.user={sub:m,data:d},t):u(`Token is not valid, no '${p}' property found.`)},"OpenIdJwtInboundPolicy");var NE=i(async(t,e,r,n)=>(w("policy.inbound.auth0-jwt-auth"),Be(t,e,{issuer:`https://${r.auth0Domain}/`,audience:r.audience,jwkUrl:`https://${r.auth0Domain}/.well-known/jwks.json`,allowUnauthenticatedRequests:r.allowUnauthenticatedRequests,oAuthResourceMetadataEnabled:r.oAuthResourceMetadataEnabled},n)),"Auth0JwtInboundPolicy");var bw=new Map;function LE(t){let e=[],r=0;for(;r<t.length;){if(t[r]==="."){r++;continue}if(t[r]==="["){for(r++;r<t.length&&/\s/.test(t[r]);)r++;let n=t[r];if(n!=='"'&&n!=="'"){for(;r<t.length&&t[r]!=="]";)r++;r++;continue}r++;let o=r;for(;r<t.length&&t[r]!==n;)r++;let s=t.substring(o,r);for(e.push(s),r++;r<t.length&&/\s/.test(t[r]);)r++;t[r]==="]"&&r++}else{let n=r;for(;r<t.length&&t[r]!=="."&&t[r]!=="[";)r++;let o=t.substring(n,r).trim();o.length>0&&e.push(o)}}return e}i(LE,"parsePropertyPath");function Xs(t,e){let r="$authzen-prop(";if(!t.startsWith(r)||!t.endsWith(")"))return t;let n=t.slice(r.length,-1),o=bw.get(n);o||(o=LE(n),bw.set(n,o));let s=e;for(let a of o){if(s==null)return;typeof s.get=="function"?s=s.get(a):s=s[a]}return s}i(Xs,"evaluateAuthzenProp");var vw=Symbol("AUTHZEN_CONTEXT_DATA_52a5cf22-d922-4673-9815-6dc3d49071d9"),rf=class t extends xe{static{i(this,"AuthZenInboundPolicy")}#e;#t;constructor(e,r){if(super(e,r),ae(e,r).required("authorizerHostname","string").optional("authorizerAuthorizationHeader","string").optional("subject","object").optional("resource","object").optional("action","object").optional("throwOnError","boolean"),e.subject&&!e.subject.type)throw new y(`${this.policyType} '${this.policyName}' - subject.type is required.`);if(e.subject&&!e.subject.id)throw new y(`${this.policyType} '${this.policyName}' - subject.id is required.`);if(e.resource&&!e.resource.type)throw new y(`${this.policyType} '${this.policyName}' - resource.type is required.`);if(e.resource&&!e.resource.id)throw new y(`${this.policyType} '${this.policyName}' - resource.id is required.`);if(e.action&&!e.action.name)throw new y(`${this.policyType} '${this.policyName}' - action.name is required.`);this.#e=(e.authorizerHostname.startsWith("https://")?e.authorizerHostname:`https://${e.authorizerHostname}`)+"/access/v1/evaluation";try{new URL(this.#e)}catch(n){throw new y(`${this.policyType} '${this.policyName}' - authorizerUrl '${this.#e}' is not valid
135
135
  ${n}`)}}async handler(e,r){let n=this.options.throwOnError!==!1;try{await this.#o(r);let o=this.options.debug===!0,s={subject:Object.assign({},this.options.subject),resource:Object.assign({},this.options.resource),action:Object.assign({},this.options.action)},a={request:e,context:r};s.action?.name!==void 0&&(s.action.name=Xs(s.action.name,a)),s.subject?.id!==void 0&&(s.subject.id=Xs(s.subject.id,a)),s.resource?.id!==void 0&&(s.resource.id=Xs(s.resource.id,a)),o&&r.log.debug(`${this.policyType} '${this.policyName}' - Evaluated payload from options`,s);let u=t.getAuthorizationPayload(r);u&&Object.assign(s,u),o&&r.log.debug(`${this.policyType} '${this.policyName}' - Using context payload to override working payload`,{contextPayload:u,final:s}),this.#n(r,!s.subject?.type||!s.subject?.id,"Missing required subject type or id"),this.#n(r,!s.resource?.type||!s.resource?.id,"Missing required resource type or id"),this.#n(r,!s.action,"Missing required action");let c={"content-type":"application/json"};this.options.authorizerAuthorizationHeader&&(c.authorization=this.options.authorizerAuthorizationHeader);let l=await fetch(this.#e,{method:"POST",body:JSON.stringify(s),headers:c});if(!l.ok){let p=`${this.policyType} '${this.policyName}' - Unexpected response from PDP: ${l.status} - ${l.statusText}:
136
136
  ${await l.text()}`;if(n)throw new Error(p);return r.log.error(p),e}let d=await l.json();if(o&&r.log.debug(`${this.policyType} '${this.policyName}' - PDP response`,d),d.decision!==!0)return this.#r(e,r,d.reason)}catch(o){if(n)throw o;r.log.error(`${this.policyType} '${this.policyName}' - Error in policy: ${o}`)}return e}#n(e,r,n){if(r){let o=`${this.policyType} '${this.policyName}' - ${n}`;if(this.options.throwOnError)throw new y(o);e.log.warn(o)}}async#r(e,r,n){return M.forbidden(e,r,{detail:n})}async#o(e){if(!this.#t){let r=await Pe(this.policyName,void 0,this.options);this.#t=new be(r,e)}}static setAuthorizationPayload(e,r){de.set(e,vw,r)}static getAuthorizationPayload(e){return de.get(e,vw)}};var Ys=class{constructor(e){this.options=e;this.authHeader=`Basic ${btoa(e.pdpUsername+":"+e.pdpPassword)}`,this.authorizationUrl=new URL("/authorize",e.pdpUrl).toString()}static{i(this,"PdpService")}authHeader;authorizationUrl;async makePdpRequest(e){let r=await W.fetch(this.authorizationUrl,{method:"POST",body:JSON.stringify(e),headers:{"Content-Type":"application/xacml+json; charset=UTF-8",[this.options.tokenHeaderName??"Authorization"]:this.authHeader}});if(!r.ok)throw new Error(`Request to PDP service failed with response status ${r.status}.`);return await r.json()}};var nf=class t extends xe{static{i(this,"AxiomaticsAuthZInboundPolicy")}pdpService;static#e;static setAuthAttributes(e,r){t.#e||(t.#e=new WeakMap),t.#e.set(e,{Request:r})}constructor(e,r){super(e,r),w("policy.inbound.axiomatics-authz"),ae(e,r).required("pdpUrl","string").required("pdpUsername","string").required("pdpPassword","string"),this.pdpService=new Ys(e)}async handler(e,r){let n=i(a=>this.options.allowUnauthorizedRequests?e:M.forbidden(e,r,{detail:a}),"forbiddenResponse"),o=new URL(e.url),s=t.#e?.get(r)??{Request:{}};if(this.options.includeDefaultSubjectAttributes!==!1&&e.user){let a=[{AttributeId:"request.user.sub",Value:e.user.sub}];this.addAttributesToCategory(s,"AccessSubject",a)}if(this.options.includeDefaultActionAttributes!==!1){let a=[{AttributeId:"request.method",Value:e.method}];this.addAttributesToCategory(s,"Action",a)}if(this.options.includeDefaultResourceAttributes!==!1){let a=[];a.push({AttributeId:"request.protocol",Value:o.protocol.substring(0,o.protocol.length-1)}),a.push({AttributeId:"request.host",Value:o.host}),a.push({AttributeId:"request.pathname",Value:o.pathname}),Object.entries(e.params).forEach(([u,c])=>{a.push({AttributeId:`request.params.${u}`,Value:c})}),o.searchParams.forEach((u,c)=>{a.push({AttributeId:`request.query.${c}`,Value:u})}),this.addAttributesToCategory(s,"Resource",a)}this.populateOptionAttributes({optionName:"resourceAttributes",authzRequestCategory:"Resource",authzRequest:s,context:r}),this.populateOptionAttributes({optionName:"actionAttributes",authzRequestCategory:"Action",authzRequest:s,context:r}),this.populateOptionAttributes({optionName:"accessSubjectAttributes",authzRequestCategory:"AccessSubject",authzRequest:s,context:r});try{r.log.debug("PDP Request",s);let a=await this.pdpService.makePdpRequest(s);return r.log.debug("PDP Response",a),a.Response.every(u=>u.Decision==="Permit")?e:(r.log.debug(`${this.policyType} '${this.policyName}' - The request was not authorized.`,a),n("The request was not authorized."))}catch(a){return r.log.error(`${this.policyType} '${this.policyName}' - Error calling PDP service`,a),M.internalServerError(e,r)}}populateOptionAttributes({optionName:e,authzRequestCategory:r,authzRequest:n,context:o}){let s=this.options[e];if(s){let a=[];s.forEach(u=>{u.value?a.push({AttributeId:u.attributeId,Value:u.value}):o.log.warn(`${this.policyType} '${this.policyName}' - The attribute ${u.attributeId} has no value. If using a selector, check that the selector is correct.`)}),this.addAttributesToCategory(n,r,a)}}addAttributesToCategory(e,r,n){e.Request[r]||(e.Request[r]=[]),e.Request[r].length===0?e.Request[r].push({Attribute:[]}):e.Request[r][0].Attribute=e.Request[r][0].Attribute??[],e.Request[r][0].Attribute.push(...n)}};var ME=i(async(t,e,r)=>{w("policy.inbound.basic-auth");let n=t.headers.get("Authorization"),o="basic ",s=i(l=>M.unauthorized(t,e,{detail:l}),"unauthorizedResponse"),u=await i(async()=>{if(!n)return await s("No Authorization header");if(n.toLowerCase().indexOf(o)!==0)return await s("Invalid Basic token format for Authorization header");let l=n.substring(o.length);if(!l||l.length===0)return await s("No username:password provided");let d=atob(l).normalize(),p=d.indexOf(":");if(p===-1||/[\0-\x1F\x7F]/.test(d))return await s("Invalid basic token value - see https://tools.ietf.org/html/rfc5234#appendix-B.1");let m=d.substring(0,p),g=d.substring(p+1),h=r.accounts.find(v=>v.username===m&&v.password===g);return h||await s("Invalid username or password")},"getAccountOrRejectedResponse")();if(u instanceof Response)return r.allowUnauthenticatedRequests?t:u;let c=u.username;return t.user={sub:c,data:u.data},t},"BasicAuthInboundPolicy");function ea(t){return{second:t.getSeconds(),minute:t.getMinutes(),hour:t.getHours(),day:t.getDate(),month:t.getMonth(),weekday:t.getDay(),year:t.getFullYear()}}i(ea,"extractDateElements");function ww(t,e){return new Date(t,e+1,0).getDate()}i(ww,"getDaysInMonth");function of(t,e){return t<=e?e-t:6-t+e+1}i(of,"getDaysBetweenWeekdays");var ta=class{static{i(this,"Cron")}seconds;minutes;hours;days;months;weekdays;reversed;constructor({seconds:e,minutes:r,hours:n,days:o,months:s,weekdays:a}){if(!e||e.size===0)throw new Error("There must be at least one allowed second.");if(!r||r.size===0)throw new Error("There must be at least one allowed minute.");if(!n||n.size===0)throw new Error("There must be at least one allowed hour.");if(!s||s.size===0)throw new Error("There must be at least one allowed month.");if((!a||a.size===0)&&(!o||o.size===0))throw new Error("There must be at least one allowed day or weekday.");this.seconds=Array.from(e).sort((c,l)=>c-l),this.minutes=Array.from(r).sort((c,l)=>c-l),this.hours=Array.from(n).sort((c,l)=>c-l),this.days=Array.from(o).sort((c,l)=>c-l),this.months=Array.from(s).sort((c,l)=>c-l),this.weekdays=Array.from(a).sort((c,l)=>c-l);let u=i((c,l,d)=>{if(l.some(p=>typeof p!="number"||p%1!==0||p<d.min||p>d.max))throw new Error(`${c} must only consist of integers which are within the range of ${d.min} and ${d.max}`)},"validateData");u("seconds",this.seconds,{min:0,max:59}),u("minutes",this.minutes,{min:0,max:59}),u("hours",this.hours,{min:0,max:23}),u("days",this.days,{min:1,max:31}),u("months",this.months,{min:0,max:11}),u("weekdays",this.weekdays,{min:0,max:6}),this.reversed={seconds:this.seconds.map(c=>c).reverse(),minutes:this.minutes.map(c=>c).reverse(),hours:this.hours.map(c=>c).reverse(),days:this.days.map(c=>c).reverse(),months:this.months.map(c=>c).reverse(),weekdays:this.weekdays.map(c=>c).reverse()}}findAllowedHour(e,r){return e==="next"?this.hours.find(n=>n>=r):this.reversed.hours.find(n=>n<=r)}findAllowedMinute(e,r){return e==="next"?this.minutes.find(n=>n>=r):this.reversed.minutes.find(n=>n<=r)}findAllowedSecond(e,r){return e==="next"?this.seconds.find(n=>n>r):this.reversed.seconds.find(n=>n<r)}findAllowedTime(e,r){let n=this.findAllowedHour(e,r.hour);if(n!==void 0)if(n===r.hour){let o=this.findAllowedMinute(e,r.minute);if(o!==void 0)if(o===r.minute){let s=this.findAllowedSecond(e,r.second);if(s!==void 0)return{hour:n,minute:o,second:s};if(o=this.findAllowedMinute(e,e==="next"?r.minute+1:r.minute-1),o!==void 0)return{hour:n,minute:o,second:e==="next"?this.seconds[0]:this.reversed.seconds[0]}}else return{hour:n,minute:o,second:e==="next"?this.seconds[0]:this.reversed.seconds[0]};if(n=this.findAllowedHour(e,e==="next"?r.hour+1:r.hour-1),n!==void 0)return{hour:n,minute:e==="next"?this.minutes[0]:this.reversed.minutes[0],second:e==="next"?this.seconds[0]:this.reversed.seconds[0]}}else return{hour:n,minute:e==="next"?this.minutes[0]:this.reversed.minutes[0],second:e==="next"?this.seconds[0]:this.reversed.seconds[0]}}findAllowedDayInMonth(e,r,n,o){if(o<1)throw new Error("startDay must not be smaller than 1.");let s=ww(r,n),a=this.days.length!==31,u=this.weekdays.length!==7;if(!a&&!u)return o>s?e==="next"?void 0:s:o;let c;a&&(c=e==="next"?this.days.find(d=>d>=o):this.reversed.days.find(d=>d<=o),c!==void 0&&c>s&&(c=void 0));let l;if(u){let d=new Date(r,n,o).getDay(),p=e==="next"?this.weekdays.find(m=>m>=d)??this.weekdays[0]:this.reversed.weekdays.find(m=>m<=d)??this.reversed.weekdays[0];if(p!==void 0){let m=e==="next"?of(d,p):of(p,d);l=e==="next"?o+m:o-m,(l>s||l<1)&&(l=void 0)}}if(c!==void 0&&l!==void 0)return e==="next"?Math.min(c,l):Math.max(c,l);if(c!==void 0)return c;if(l!==void 0)return l}getNextDate(e=new Date){let r=ea(e),n=r.year,o=this.months.findIndex(a=>a>=r.month);o===-1&&(o=0,n++);let s=this.months.length*5;for(let a=0;a<s;a++){let u=n+Math.floor((o+a)/this.months.length),c=this.months[(o+a)%this.months.length],l=u===r.year&&c===r.month,d=this.findAllowedDayInMonth("next",u,c,l?r.day:1),p=l&&d===r.day;if(d!==void 0&&p){let m=this.findAllowedTime("next",r);if(m!==void 0)return new Date(u,c,d,m.hour,m.minute,m.second);d=this.findAllowedDayInMonth("next",u,c,d+1),p=!1}if(d!==void 0&&!p)return new Date(u,c,d,this.hours[0],this.minutes[0],this.seconds[0])}throw new Error("No valid next date was found.")}getNextDates(e,r){let n=[],o;for(let s=0;s<e;s++)o=this.getNextDate(o??r),n.push(o);return n}*getNextDatesIterator(e,r){let n;for(;;){if(n=this.getNextDate(e),e=n,r&&r.getTime()<n.getTime())return;yield n}}getPrevDate(e=new Date){let r=ea(e),n=r.year,o=this.reversed.months.findIndex(a=>a<=r.month);o===-1&&(o=0,n--);let s=this.reversed.months.length*5;for(let a=0;a<s;a++){let u=n-Math.floor((o+a)/this.reversed.months.length),c=this.reversed.months[(o+a)%this.reversed.months.length],l=u===r.year&&c===r.month,d=this.findAllowedDayInMonth("prev",u,c,l?r.day:31),p=l&&d===r.day;if(d!==void 0&&p){let m=this.findAllowedTime("prev",r);if(m!==void 0)return new Date(u,c,d,m.hour,m.minute,m.second);d>1&&(d=this.findAllowedDayInMonth("prev",u,c,d-1),p=!1)}if(d!==void 0&&!p)return new Date(u,c,d,this.reversed.hours[0],this.reversed.minutes[0],this.reversed.seconds[0])}throw new Error("No valid previous date was found.")}getPrevDates(e,r){let n=[],o;for(let s=0;s<e;s++)o=this.getPrevDate(o??r),n.push(o);return n}*getPrevDatesIterator(e,r){let n;for(;;){if(n=this.getPrevDate(e),e=n,r&&r.getTime()>n.getTime())return;yield n}}matchDate(e){let{second:r,minute:n,hour:o,day:s,month:a,weekday:u}=ea(e);return this.seconds.indexOf(r)===-1||this.minutes.indexOf(n)===-1||this.hours.indexOf(o)===-1||this.months.indexOf(a)===-1?!1:this.days.length!==31&&this.weekdays.length!==7?this.days.indexOf(s)!==-1||this.weekdays.indexOf(u)!==-1:this.days.indexOf(s)!==-1&&this.weekdays.indexOf(u)!==-1}};var zE={min:0,max:59},UE={min:0,max:59},DE={min:0,max:23},ZE={min:1,max:31},jE={min:1,max:12,aliases:{jan:"1",feb:"2",mar:"3",apr:"4",may:"5",jun:"6",jul:"7",aug:"8",sep:"9",oct:"10",nov:"11",dec:"12"}},qE={min:0,max:7,aliases:{mon:"1",tue:"2",wed:"3",thu:"4",fri:"5",sat:"6",sun:"7"}},FE={"@yearly":"0 0 1 1 *","@annually":"0 0 1 1 *","@monthly":"0 0 1 1 *","@weekly":"0 0 * * 0","@daily":"0 0 * * *","@hourly":"0 * * * *","@minutely":"* * * * *"};function Pr(t,e){let r=new Set;if(t==="*"){for(let d=e.min;d<=e.max;d=d+1)r.add(d);return r}let n=t.split(",");if(n.length>1)return n.forEach(d=>{Pr(d,e).forEach(m=>r.add(m))}),r;let o=i(d=>{d=e.aliases?.[d.toLowerCase()]??d;let p=parseInt(d,10);if(Number.isNaN(p))throw new Error(`Failed to parse ${t}: ${d} is NaN.`);if(p<e.min||p>e.max)throw new Error(`Failed to parse ${t}: ${d} is outside of constraint range of ${e.min} - ${e.max}.`);return p},"parseSingleElement"),s=/^((([0-9a-zA-Z]+)-([0-9a-zA-Z]+))|\*)(\/([0-9]+))?$/.exec(t);if(s===null)return r.add(o(t)),r;let a=s[1]==="*"?e.min:o(s[3]),u=s[1]==="*"?e.max:o(s[4]);if(a>u)throw new Error(`Failed to parse ${t}: Invalid range (start: ${a}, end: ${u}).`);let c=s[6],l=1;if(c!==void 0){if(l=parseInt(c,10),Number.isNaN(l))throw new Error(`Failed to parse step: ${c} is NaN.`);if(l<1)throw new Error(`Failed to parse step: Expected ${c} to be greater than 0.`)}for(let d=a;d<=u;d=d+l)r.add(d);return r}i(Pr,"parseElement");function sf(t){if(typeof t!="string")throw new TypeError("Invalid cron expression: must be of type string.");t=FE[t.toLowerCase()]??t;let e=t.split(" ");if(e.length<5||e.length>6)throw new Error("Invalid cron expression: expected 5 or 6 elements.");let r=e.length===6?e[0]:"0",n=e.length===6?e[1]:e[0],o=e.length===6?e[2]:e[1],s=e.length===6?e[3]:e[2],a=e.length===6?e[4]:e[3],u=e.length===6?e[5]:e[4];return new ta({seconds:Pr(r,zE),minutes:Pr(n,UE),hours:Pr(o,DE),days:Pr(s,ZE),months:new Set(Array.from(Pr(a,jE)).map(c=>c-1)),weekdays:new Set(Array.from(Pr(u,qE)).map(c=>c%7))})}i(sf,"parseCronExpression");var af=class extends xe{static{i(this,"BrownoutInboundPolicy")}crons;constructor(e,r){if(super(e,r),w("policy.inbound.brownout"),ae(e,r).optional("problem","object"),e.problem&&ae(e.problem,r,"policy","problem").optional("detail","string").optional("status","string").optional("title","string"),typeof e.cronSchedule!="string"&&!(typeof e.cronSchedule=="object"&&Array.isArray(e.cronSchedule)&&!e.cronSchedule.some(n=>typeof n!="string")))throw new y(`Value of 'cronSchedule' on policy '${r}' must be of type string or string[]. Received type ${typeof e.cronSchedule}.`);typeof this.options.cronSchedule=="string"?this.crons=[sf(this.options.cronSchedule)]:this.crons=this.options.cronSchedule.map(n=>sf(n))}async handler(e,r){let n=new Date;if(n.setSeconds(0),n.setMilliseconds(0),this.crons.some(s=>s.matchDate(n))){let s=M.getProblemFromStatus(this.options.problem?.status??400,{detail:"This API is performing a scheduled brownout in advance of its pending deprecation. Please upgrade to a later version.",...this.options.problem});return M.format(s,e,r)}return e}};var HE=["cdn-cache-control","cloudflare-cdn-cache-control","surrogate-control","cache-tag","expires"];async function BE(t){let e=new TextEncoder().encode(t),r=await crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(r)).map(s=>s.toString(16).padStart(2,"0")).join("")}i(BE,"digestMessage");var GE=i(async(t,e)=>{let r=[...e.dangerouslyIgnoreAuthorizationHeader===!0?[]:["authorization"],...e.headers??[]],n=[];for(let[d,p]of t.headers.entries())r.includes(d)&&n.push({key:d.toLowerCase(),value:p});n.sort((d,p)=>d.key.localeCompare(p.key));let o=await BE(JSON.stringify(n)),s=new URL(t.url),a=new URLSearchParams(s.searchParams);a.set("_z-hdr-dgst",o);let u=e.cacheHttpMethods?.includes(t.method.toUpperCase())&&t.method.toUpperCase()!=="GET";u&&a.set("_z-original-method",t.method);let c=`${s.origin}${s.pathname}?${a}`;return new Request(c,{method:u?"GET":t.method})},"createCacheKeyRequest");async function VE(t,e,r,n){w("policy.inbound.caching");let o=await Pe(n,r.cacheId,r),s=await caches.open(o),a=r?.cacheHttpMethods?.map(l=>l.toUpperCase())??["GET"],u=await GE(t,r),c=await s.match(u);return c||(e.addEventListener("responseSent",l=>{try{let d=r.statusCodes??[200,206,301,302,303,404,410],p=l.response.clone();if(!d.includes(p.status)||!a.includes(t.method.toUpperCase()))return;let m=r?.expirationSecondsTtl??60,g=new Response(p.body,p);HE.forEach(h=>g.headers.delete(h)),g.headers.set("cache-control",`s-maxage=${m}`),e.waitUntil(s.put(u,g))}catch(d){e.log.error(`Error in caching-inbound-policy '${n}': "${d.message}"`,d)}}),t)}i(VE,"CachingInboundPolicy");var JE=i(async(t,e,r,n)=>{if(w("policy.inbound.change-method"),!r.method)throw new y(`ChangeMethodInboundPolicy '${n}' options.method must be valid HttpMethod`);return new pe(t,{method:r.method})},"ChangeMethodInboundPolicy");var WE=i(async(t,e,r)=>{w("policy.inbound.clear-headers");let n=[...r.exclude??[]],o=new Headers;return n.forEach(a=>{let u=t.headers.get(a);u&&o.set(a,u)}),new pe(t,{headers:o})},"ClearHeadersInboundPolicy");var KE=i(async(t,e,r,n)=>{w("policy.outbound.clear-headers");let o=[...n.exclude??[]],s=new Headers;return o.forEach(u=>{let c=t.headers.get(u);c&&s.set(u,c)}),new Response(t.body,{headers:s,status:t.status,statusText:t.statusText})},"ClearHeadersOutboundPolicy");var QE=i(async(t,e,r,n)=>{w("policy.inbound.clerk-jwt-auth");let o=new URL(r.frontendApiUrl.startsWith("https://")||r.frontendApiUrl.startsWith("http://")?r.frontendApiUrl:`https://${r.frontendApiUrl}`),s=new URL(o);return s.pathname="/.well-known/jwks.json",Be(t,e,{issuer:o.href.slice(0,-1),jwkUrl:s.toString(),allowUnauthenticatedRequests:r.allowUnauthenticatedRequests,oAuthResourceMetadataEnabled:r.oAuthResourceMetadataEnabled},n)},"ClerkJwtInboundPolicy");var XE=Object.defineProperty,YE=Object.getOwnPropertyNames,ne=i((t,e)=>XE(t,"name",{value:e,configurable:!0}),"__name"),uf=i((t,e)=>i(function(){return e||(0,t[YE(t)[0]])((e={exports:{}}).exports,e),e.exports},"__require"),"__commonJS"),xw=uf({"node_modules/http-message-sig/dist/index.js"(t,e){var r=Object.defineProperty,n=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,a=ne((U,B)=>{for(var F in B)r(U,F,{get:B[F],enumerable:!0})},"__export"),u=ne((U,B,F,P)=>{if(B&&typeof B=="object"||typeof B=="function")for(let I of o(B))!s.call(U,I)&&I!==F&&r(U,I,{get:ne(()=>B[I],"get"),enumerable:!(P=n(B,I))||P.enumerable});return U},"__copyProps"),c=ne(U=>u(r({},"__esModule",{value:!0}),U),"__toCommonJS"),l={};a(l,{HTTP_MESSAGE_SIGNATURES_DIRECTORY:ne(()=>x,"HTTP_MESSAGE_SIGNATURES_DIRECTORY"),MediaType:ne(()=>$,"MediaType"),base64:ne(()=>d,"base64"),extractHeader:ne(()=>g,"extractHeader"),parseAcceptSignature:ne(()=>z,"parseAcceptSignature"),signatureHeaders:ne(()=>T,"signatureHeaders"),signatureHeadersSync:ne(()=>H,"signatureHeadersSync"),verify:ne(()=>he,"verify")}),e.exports=c(l);var d={};a(d,{decode:ne(()=>m,"decode"),encode:ne(()=>p,"encode")});function p(U){return btoa(String.fromCharCode(...U))}i(p,"encode"),ne(p,"encode");function m(U){return Uint8Array.from(atob(U),B=>B.charCodeAt(0))}i(m,"decode"),ne(m,"decode");function g({headers:U},B){if(typeof U.get=="function")return U.get(B)??"";let F=B.toLowerCase(),P=Object.keys(U).find(V=>V.toLowerCase()===F),I=P?U[P]??"":"";return Array.isArray(I)&&(I=I.join(", ")),I.toString().replace(/\s+/g," ")}i(g,"extractHeader"),ne(g,"extractHeader");function h(U,B){if("url"in U&&"protocol"in U){let F=g(U,"host"),I=`${U.protocol||"http"}://${F}`;return new URL(U.url,I)}if(!U.url)throw new Error(`${B} is only valid for requests`);return new URL(U.url)}i(h,"getUrl"),ne(h,"getUrl");function v(U,B){switch(B){case"@method":if(!U.method)throw new Error(`${B} is only valid for requests`);return U.method.toUpperCase();case"@target-uri":if(!U.url)throw new Error(`${B} is only valid for requests`);return U.url;case"@authority":{let F=h(U,B),P=F.port?parseInt(F.port,10):null;return`${F.hostname}${P&&![80,443].includes(P)?`:${P}`:""}`}case"@scheme":return h(U,B).protocol.slice(0,-1);case"@request-target":{let{pathname:F,search:P}=h(U,B);return`${F}${P}`}case"@path":return h(U,B).pathname;case"@query":return h(U,B).search;case"@status":if(!U.status)throw new Error(`${B} is only valid for responses`);return U.status.toString();case"@query-params":case"@request-response":throw new Error(`${B} is not implemented yet`);default:throw new Error(`Unknown specialty component ${B}`)}}i(v,"extractComponent"),ne(v,"extractComponent");function b(U,B){let F=U.map(I=>`"${I.toLowerCase()}"`).join(" "),P=Object.entries(B).map(([I,V])=>typeof V=="number"?`;${I}=${V}`:V instanceof Date?`;${I}=${Math.floor(V.getTime()/1e3)}`:`;${I}="${V.toString()}"`).join("");return`(${F})${P}`}i(b,"buildSignatureInputString"),ne(b,"buildSignatureInputString");function S(U,B,F){let P=B.map(I=>{let V=I.startsWith("@")?v(U,I):g(U,I);return`"${I.toLowerCase()}": ${V}`});return P.push(`"@signature-params": ${F}`),P.join(`
137
137
  `)}i(S,"buildSignedData"),ne(S,"buildSignedData");var x="./well-known/http-message-signatures-directory",$=(U=>(U.HTTP_MESSAGE_SIGNATURES_DIRECTORY="application/http-message-signatures-directory",U))($||{});function O(U,B){let F=B.indexOf("=");if(F===-1)return[B.trim(),!0];let P=B.slice(0,F),I=B.slice(F+1).trim();if(P.length===0)throw new Error(`Invalid ${U} header. Invalid value ${B}`);if(I.match(/^".*"$/))return[P.trim(),I.slice(1,-1)];if(I.match(/^\d+$/))return[P.trim(),parseInt(I)];if(I.match(/^\(.*\)$/)){let V=I.slice(1,-1).split(/\s+/).map(se=>{var E;return((E=se.match(/^"(.*)"$/))==null?void 0:E[1])??parseInt(se)});if(V.some(se=>typeof se=="number"&&isNaN(se)))throw new Error(`Invalid ${U} header. Invalid value ${P}=${I}`);return[P.trim(),V]}throw new Error(`Invalid ${U} header. Invalid value ${P}=${I}`)}i(O,"parseEntry"),ne(O,"parseEntry");function L(U,B){var F;let P=(F=B.toString().match(/(?:[^;"]+|"[^"]+")+/g))==null?void 0:F.map(A=>O(U,A.trim()));if(!P)throw new Error(`Invalid ${U} header. Invalid value`);let I=P.findIndex(([,A])=>Array.isArray(A));if(I===-1)throw new Error(`Invalid ${U} header. Missing components`);let[[V,se]]=P.splice(I,1);if(P.some(([,A])=>Array.isArray(A)))throw new Error("Multiple signatures is not supported");let E=Object.fromEntries(P);return typeof E.created=="number"&&(E.created=new Date(E.created*1e3)),typeof E.expires=="number"&&(E.expires=new Date(E.expires*1e3)),{key:V,components:se,parameters:E}}i(L,"parseParametersHeader"),ne(L,"parseParametersHeader");function _(U){return L("Signature-Input",U)}i(_,"parseSignatureInputHeader"),ne(_,"parseSignatureInputHeader");function z(U){return L("Accept-Signature",U)}i(z,"parseAcceptSignatureHeader"),ne(z,"parseAcceptSignatureHeader");function D(U,B){let F=B.toString().match(/^([\w-]+)=:([A-Za-z0-9+/=]+):$/);if(!F)throw new Error("Invalid Signature header");let[,P,I]=F;if(P!==U)throw new Error(`Invalid Signature header. Key mismatch ${P} !== ${U}`);return m(I)}i(D,"parseSignatureHeader"),ne(D,"parseSignatureHeader");var j=["@method","@path","@query","@authority","content-type","digest"],C=["@status","content-type","digest"];async function T(U,B){let{signer:F,components:P,key:I,...V}=B,se=P??("status"in U?C:j),E=I??"sig1",A={created:new Date,keyid:F.keyid,alg:F.alg,...V},G=b(se,A),ie=S(U,se,G),J=await F.sign(ie),Q=p(J);return{Signature:`${E}=:${Q}:`,"Signature-Input":`${E}=${G}`}}i(T,"signatureHeaders2"),ne(T,"signatureHeaders");function H(U,B){let{signer:F,components:P,key:I,...V}=B,se=P??("status"in U?C:j),E=I??"sig1",A={created:new Date,keyid:F.keyid,alg:F.alg,...V},G=b(se,A),ie=S(U,se,G),J=F.signSync(ie),Q=p(J);return{Signature:`${E}=:${Q}:`,"Signature-Input":`${E}=${G}`}}i(H,"signatureHeadersSync2"),ne(H,"signatureHeadersSync");async function he(U,B){let F=g(U,"signature-input");if(!F)throw new Error("Message does not contain Signature-Input header");let{key:P,components:I,parameters:V}=_(F);if(V.expires&&V.expires<new Date)throw new Error("Signature expired");let se=g(U,"signature");if(!se)throw new Error("Message does not contain Signature header");let E=D(P,se),A=F.toString().replace(/^[^=]+=/,""),G=S(U,I,A);return B(G,E,V)}i(he,"verify2"),ne(he,"verify")}}),Pw=uf({"node_modules/jsonwebkey-thumbprint/dist/index.js"(t,e){var r=Object.defineProperty,n=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,a=ne((m,g)=>{for(var h in g)r(m,h,{get:g[h],enumerable:!0})},"__export"),u=ne((m,g,h,v)=>{if(g&&typeof g=="object"||typeof g=="function")for(let b of o(g))!s.call(m,b)&&b!==h&&r(m,b,{get:ne(()=>g[b],"get"),enumerable:!(v=n(g,b))||v.enumerable});return m},"__copyProps"),c=ne(m=>u(r({},"__esModule",{value:!0}),m),"__toCommonJS"),l={};a(l,{jwkThumbprint:ne(()=>p,"jwkThumbprint"),jwkThumbprintPreCompute:ne(()=>d,"jwkThumbprintPreCompute")}),e.exports=c(l);var d=ne(m=>{let g=new TextEncoder;switch(m.kty){case"EC":return g.encode(`{"crv":"${m.crv}","kty":"EC","x":"${m.x}","y":"${m.y}"}`);case"OKP":return g.encode(`{"crv":"${m.crv}","kty":"OKP","x":"${m.x}"}`);case"RSA":return g.encode(`{"e":"${m.e}","kty":"RSA","n":"${m.n}"}`);default:throw new Error("Unsupported key type")}},"jwkThumbprintPreCompute"),p=ne(async(m,g,h)=>{let v=d(m),b=await g(v);return h(b)},"jwkThumbprint")}}),eC=uf({"node_modules/web-bot-auth/dist/index.js"(t,e){var r=Object.create,n=Object.defineProperty,o=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,a=Object.getPrototypeOf,u=Object.prototype.hasOwnProperty,c=ne((F,P)=>{for(var I in P)n(F,I,{get:P[I],enumerable:!0})},"__export"),l=ne((F,P,I,V)=>{if(P&&typeof P=="object"||typeof P=="function")for(let se of s(P))!u.call(F,se)&&se!==I&&n(F,se,{get:ne(()=>P[se],"get"),enumerable:!(V=o(P,se))||V.enumerable});return F},"__copyProps"),d=ne((F,P,I)=>(I=F!=null?r(a(F)):{},l(P||!F||!F.__esModule?n(I,"default",{value:F,enumerable:!0}):I,F)),"__toESM"),p=ne(F=>l(n({},"__esModule",{value:!0}),F),"__toCommonJS"),m={};c(m,{HTTP_MESSAGE_SIGNAGURE_TAG:ne(()=>_,"HTTP_MESSAGE_SIGNAGURE_TAG"),HTTP_MESSAGE_SIGNATURES_DIRECTORY:ne(()=>h.HTTP_MESSAGE_SIGNATURES_DIRECTORY,"HTTP_MESSAGE_SIGNATURES_DIRECTORY"),MediaType:ne(()=>h.MediaType,"MediaType"),NONCE_LENGTH_IN_BYTES:ne(()=>C,"NONCE_LENGTH_IN_BYTES"),REQUEST_COMPONENTS:ne(()=>j,"REQUEST_COMPONENTS"),REQUEST_COMPONENTS_WITHOUT_SIGNATURE_AGENT:ne(()=>D,"REQUEST_COMPONENTS_WITHOUT_SIGNATURE_AGENT"),SIGNATURE_AGENT_HEADER:ne(()=>z,"SIGNATURE_AGENT_HEADER"),generateNonce:ne(()=>T,"generateNonce"),helpers:ne(()=>L,"helpers"),jwkToKeyID:ne(()=>v.jwkThumbprint,"jwkToKeyID"),signatureHeaders:ne(()=>he,"signatureHeaders"),signatureHeadersSync:ne(()=>U,"signatureHeadersSync"),validateNonce:ne(()=>H,"validateNonce"),verify:ne(()=>B,"verify")}),e.exports=p(m);var g=d(xw()),h=xw(),v=Pw();function b(F){return btoa(String.fromCharCode(...F))}i(b,"u8ToB64"),ne(b,"u8ToB64");function S(F){return Uint8Array.from(atob(F),P=>P.charCodeAt(0))}i(S,"b64Tou8"),ne(S,"b64Tou8");function x(F){return F.replace(/\+/g,"-").replace(/\//g,"_")}i(x,"b64ToB64URL"),ne(x,"b64ToB64URL");function $(F){return F.replace(/=/g,"")}i($,"b64ToB64NoPadding"),ne($,"b64ToB64NoPadding");var O=Pw(),L={WEBCRYPTO_SHA256:ne(F=>crypto.subtle.digest("SHA-256",F),"WEBCRYPTO_SHA256"),BASE64URL_DECODE:ne(F=>x($(b(new Uint8Array(F)))),"BASE64URL_DECODE")},_="web-bot-auth",z="signature-agent",D=["@authority"],j=["@authority",z],C=64;function T(){let F=new Uint8Array(C);return crypto.getRandomValues(F),b(F)}i(T,"generateNonce"),ne(T,"generateNonce");function H(F){try{return S(F).length===C}catch{return!1}}i(H,"validateNonce"),ne(H,"validateNonce");function he(F,P,I){if(I.created.getTime()>I.expires.getTime())throw new Error("created should happen before expires");let V=I.nonce;if(!V)V=T();else if(!H(V))throw new Error("nonce is not a valid uint32");let se=g.extractHeader(F,z),E=j;return se||(E=D),g.signatureHeaders(F,{signer:P,components:E,created:I.created,expires:I.expires,nonce:V,keyid:P.keyid,key:I.key,tag:_})}i(he,"signatureHeaders2"),ne(he,"signatureHeaders2");function U(F,P,I){if(I.created.getTime()>I.expires.getTime())throw new Error("created should happen before expires");let V=I.nonce;if(!V)V=T();else if(!H(V))throw new Error("nonce is not a valid uint32");let se=g.extractHeader(F,z),E=j;return se||(E=D),g.signatureHeadersSync(F,{signer:P,components:E,created:I.created,expires:I.expires,nonce:V,keyid:P.keyid,tag:_})}i(U,"signatureHeadersSync2"),ne(U,"signatureHeadersSync2");function B(F,P){let I=ne((V,se,E)=>{if(E.tag!==_)throw new Error(`tag must be '${_}'`);if(E.created.getTime()>Date.now())throw new Error("created in the future");if(E.expires.getTime()<Date.now())throw new Error("signature has expired");if(E.keyid===void 0)throw new Error("keyid MUST be defined");let A={keyid:E.keyid,created:E.created,expires:E.expires,tag:E.tag,nonce:E.nonce};return P(V,se,A)},"v");return g.verify(F,I)}i(B,"verify2"),ne(B,"verify2")}}),Rr=eC();var tC=Rr.verify,wK=Rr.signatureHeaders,xK=Rr.signatureHeadersSync,Rw=tC;var PK=Rr.generateNonce,RK=Rr.validateNonce,IK=Rr.Algorithm;var Ke=class extends Error{constructor(r,n=401,o){super(r);this.status=n;this.botId=o;this.name="BotAuthenticationError"}static{i(this,"BotAuthenticationError")}};async function rC(t,e,r,n,o,s){try{let a=await fetch(n);if(!a.ok)throw new Ke(`Failed to fetch directory: ${a.status}`,500);let c=(await a.json())[t];if(!c)throw new Ke(`Bot ${t} not found in directory`,403,t);o.log.info(`${s}: Bot ${t} found in directory`);let l=await crypto.subtle.importKey("jwk",c,{name:"Ed25519"},!0,["verify"]),d=new TextEncoder().encode(e);if(!await crypto.subtle.verify({name:"Ed25519"},l,r,d))throw new Ke("Invalid signature",401,t)}catch(a){throw a instanceof Ke?a:(o.log.error(`${s}: Error verifying signature: ${a}`),new Ke(`Error verifying signature: ${a.message}`,500,t))}}i(rC,"verifyWithDirectory");async function Iw(t,e,r,n){let o=t.headers.get("Signature"),s=t.headers.get("Signature-Input");if(!o||!s)throw new Ke("Bot authentication required");try{let a;async function u(c,l,d){let p=d.keyid;if(a=p,!e.allowedBots.includes(p)&&e.blockUnknownBots)throw new Ke(`Bot ${p} is not in the allowed list`,403,p);r.log.info(`${n}: Verifying signature for bot ${p}`),e.directoryUrl?await rC(p,c,l,e.directoryUrl,r,n):r.log.info(`${n}: No directory URL provided, using default verification`),r.log.info(`${n}: Bot ${p} authenticated successfully`)}if(i(u,"verifySignature"),await Rw(t,u),!a)throw new Ke("Could not extract bot ID from signature");return a}catch(a){throw a instanceof Ke?a:new Ke(`Bot authentication failed: ${a.message}`)}}i(Iw,"verifyBotSignature");var nC=Symbol("botId"),oC=new de(nC);var iC=i(async(t,e,r,n)=>{w("policy.inbound.web-bot-auth");let o=t.headers.get("Signature"),s=t.headers.get("Signature-Input");if(!o||!s)return r.allowUnauthenticatedRequests?(e.log.info(`${n}: No bot signature found, allowing unauthenticated request`),t):(e.log.warn(`${n}: No bot signature found, rejecting request`),new Response("Bot authentication required",{status:401}));try{let a=await Iw(t,r,e,n);return oC.set(e,a),t}catch(a){return a instanceof Ke?(e.log.error(`${n}: Bot authentication failed: ${a.message}`),new Response(`Bot authentication failed: ${a.message}`,{status:a.status})):(e.log.error(`${n}: Bot authentication failed: ${a}`),new Response(`Bot authentication failed: ${a.message}`,{status:401}))}},"WebBotAuthInboundPolicy");var sC=i(async(t,e,r,n)=>{if(w("policy.inbound.cognito-jwt-auth"),!r.userPoolId)throw new y("userPoolId must be set in the options for CognitoJwtInboundPolicy");if(!r.region)throw new y("region must be set in the options for CognitoJwtInboundPolicy");return Be(t,e,{issuer:`https://cognito-idp.${r.region}.amazonaws.com/${r.userPoolId}`,jwkUrl:`https://cognito-idp.${r.region}.amazonaws.com/${r.userPoolId}/.well-known/jwks.json`,allowUnauthenticatedRequests:r.allowUnauthenticatedRequests,oAuthResourceMetadataEnabled:r.oAuthResourceMetadataEnabled},n)},"CognitoJwtInboundPolicy");var ra=class extends Error{static{i(this,"ValidationError")}constructor(e){super(e)}},cf=class extends ra{static{i(this,"ArgumentUndefinedError")}constructor(e){super(`The argument '${e}' is undefined.`)}},lf=class extends ra{static{i(this,"ArgumentTypeError")}constructor(e,r){super(`The argument '${e}' must be of type '${r}'.`)}};function aC(t,e){if(Cg(t))throw new cf(e)}i(aC,"throwIfUndefinedOrNull");function Sw(t,e){if(aC(t,e),!Xe(t))throw new lf(e,"string")}i(Sw,"throwIfNotString");var uC=250,df=class{static{i(this,"InMemoryRateLimitClient")}keyValueStore;constructor(){this.keyValueStore=new Map}getCountAndUpdateExpiry(e,r){let o=Math.floor(r*60),s=Date.now()+o*1e3,a=this.keyValueStore.get(e);a?Date.now()>a.expiresAt?this.keyValueStore.set(e,{value:1,expiresAt:s}):this.keyValueStore.set(e,{value:a.value+1,expiresAt:a.expiresAt}):this.keyValueStore.set(e,{value:1,expiresAt:s});let u=this.keyValueStore.get(e);return Promise.resolve({count:u.value,ttlSeconds:Math.round((u.expiresAt-Date.now())/1e3)})}multiIncrement(e,r){throw new Error("In memory complex rate limits are not currently supported.")}multiCount(e,r){throw new Error("In memory complex rate limits are not currently supported.")}setQuota(e,r,n){throw new Error("In memory quotas are not currently supported.")}getQuota(e,r){throw new Error("In memory quotas are not currently supported.")}},pf=class{constructor(e,r=R.instance.rateLimitServiceTimeoutMs,n){this.clientUrl=e;this.timeoutMs=r;this.logger=n;this.logger.debug(`Rate limit client timeout set to ${this.timeoutMs}ms`)}static{i(this,"RemoteRateLimitClient")}static instance;async fetch({url:e,body:r,method:n,requestId:o}){Sw(e,"url");let s=new AbortController;setTimeout(()=>{s.abort()},this.timeoutMs);let a,u=new Headers({"content-type":"application/json"});De(u,o);try{a=await W.fetch(`${this.clientUrl}${e}`,{method:n,body:r,signal:s.signal,headers:u})}catch(l){if(l instanceof Error&&l.name==="AbortError"){let d=this.timeoutMs;throw this.timeoutMs+=uC,this.logger.warn({previousRateLimitClientTimeout:d,newRateLimitClientTimeout:this.timeoutMs,requestId:o},`Rate limit client timed out after ${d}ms. Increasing rate limit client timeout from ${d}ms to ${this.timeoutMs}ms.`),new ue("Rate limiting client timed out",{cause:l})}throw new ue("Could not fetch rate limiting client",{cause:l})}let c=a.headers.get("Content-Type")?.includes("application/json")?await a.json():await a.text();if(a.ok)return c;throw a.status===401?new ue("Rate limiting service failed with 401: Unauthorized"):new ue(`Rate limiting service failed with (${a.status})`)}async multiCount(e,r){return(await this.fetch({url:"/rate-limits/check",method:"POST",body:JSON.stringify({limits:e}),requestId:r})).data}async multiIncrement(e,r){return(await this.fetch({url:"/rate-limits/increment",method:"POST",body:JSON.stringify({limits:e}),requestId:r})).data}async getCountAndUpdateExpiry(e,r,n){let o=Math.floor(r*60);return await this.fetch({url:"/rate-limit",method:"POST",body:JSON.stringify({incrBy:1,expire:o,key:e}),requestId:n})}async getQuota(e,r){let n=await wr(e);return await this.fetch({url:`/quota/${n}`,method:"GET",requestId:r})}async setQuota(e,r,n){let o=await wr(e);await this.fetch({url:`/quota/${o}`,method:"POST",body:JSON.stringify(r),requestId:n})}},tn;function ir(t,e,r){let{redisURL:n,authApiJWT:o}=R.instance;if(tn)return tn;if(!o)return e.info("Using in-memory rate limit client for local development."),tn=new df,tn;if(!Xe(n))throw new ue(`RateLimitClient used in policy '${t}' - rate limit service not configured`);if(!Xe(o))throw new ue(`RateLimitClient used in policy '${t}' - rate limit service not configured`);return tn=new pf(n,r?.timeoutMs,e),tn}i(ir,"getRateLimitClient");var cC=i(t=>at(t)??"127.0.0.1","getRealIP");function rn(t,e){return{function:mC(e,"RateLimitInboundPolicy",t),user:dC,ip:lC,all:pC}[e.rateLimitBy??"ip"]}i(rn,"getRateLimitByFunctions");var lC=i(async t=>({key:`ip-${cC(t)}`}),"getIP"),dC=i(async t=>({key:`user-${t.user?.sub??"anonymous"}`}),"getUser"),pC=i(async()=>({key:"all-2d77ce9d-9a3c-4206-9ab2-668cfd271095"}),"getAll");function mC(t,e,r){let n;if(t.rateLimitBy==="function"){if(!t.identifier)throw new y(`${e} '${r}' - If rateLimitBy set to 'function' options.identifier must be specified`);if(!t.identifier.module||typeof t.identifier.module!="object")throw new y(`${e} '${r}' - If rateLimitBy set to 'function' options.identifier.module must be specified`);if(!t.identifier.export)throw new y(`${e} '${r}' - If rateLimitBy set to 'function' options.identifier.export must be specified`);if(n=t.identifier.module[t.identifier.export],!n||typeof n!="function")throw new y(`${e} '${r}' - Custom rate limit function must be a valid function`)}return i(async(s,a,u)=>{let c=await n(s,a,u);if(!c||typeof c!="object"){let l=`${e} '${u}' - Custom rate limit function must return a valid object.`;throw a.log.error(l),new q(l)}if(!("key"in c)){let l=`${e} '${u}' - Custom rate limit function must return a valid key property.`;throw a.log.error(l,c),new q(l)}if(typeof c.key!="string"){let l=`${e} '${u}' - Custom rate limit function must return a valid key property of type string. Received type '${typeof c.key}'`;throw a.log.error(l),new q(l)}return c},"outerFunction")}i(mC,"wrapUserFunction");var nn="Retry-After";var kw=Ze("zuplo:policies:ComplexRateLimitInboundPolicy"),mf=Symbol("complex-rate-limit-counters"),ff=class t extends xe{static{i(this,"ComplexRateLimitInboundPolicy")}static setIncrements(e,r){let n=de.get(e,mf)??{};Object.assign(n,r),de.set(e,mf,n)}static getIncrements(e){return de.get(e,mf)??{}}constructor(e,r){super(e,r),w("policy.inbound.complex-rate-limit-inbound"),ae(e,r).required("rateLimitBy","string").required("timeWindowMinutes","number").required("limits","object").optional("headerMode","string").optional("throwOnFailure","boolean").optional("mode","string").optional("identifier","object"),e.identifier&&ae(e.identifier,r,"policy","identifier").required("export","string").required("module","object");for(let[n,o]of Object.entries(e.limits))if(typeof o!="number")throw new y(`ComplexRateLimitInboundPolicy '${this.policyName}' - The value of the limits must be numbers. The limit ${n} is set to type '${typeof e}'.`)}async handler(e,r){let n=Date.now(),o=re.getLogger(r),s=ir(this.policyName,o),a=i((c,l)=>{if(this.options.throwOnFailure)throw new ue(c,{cause:l});o.error(c,l)},"throwOrLog"),u=i((c,l)=>{let d={};return(!c||c==="retry-after")&&(d[nn]=l.toString()),M.tooManyRequests(e,r,void 0,d)},"rateLimited");try{let l=await rn(this.policyName,this.options)(e,r,this.policyName),d=R.instance.isTestMode||R.instance.isWorkingCopy?R.instance.build.BUILD_ID:"",p=Object.assign({},this.options.limits,l.limits),m=(l.timeWindowMinutes??this.options.timeWindowMinutes??1)*60;r.addResponseSendingFinalHook(async()=>{try{let b=t.getIncrements(r);kw(`ComplexRateLimitInboundPolicy '${this.policyName}' - increments ${JSON.stringify(b)}`);let S=Object.entries(p).map(([$])=>({key:`complex-rate-limit${d}/${this.policyName}/${l.key}/${$}`,ttlSeconds:m,increment:b[$]??0})),x=s.multiIncrement(S,r.requestId);r.waitUntil(x),await x}catch(b){a(b.message,b)}});let g=Object.entries(p).map(([b,S])=>({key:`complex-rate-limit${d}/${this.policyName}/${l.key}/${b}`,ttlSeconds:m,limit:S})),h=await s.multiCount(g,r.requestId);return fC(h,g).length>0?u(this.options.headerMode??"retry-after",m):e}catch(c){return a(c.message,c),e}finally{let c=Date.now()-n;kw(`ComplexRateLimitInboundPolicy '${this.policyName}' - latency ${c}ms`)}}};function fC(t,e){let r=[];for(let n of t){let o=e.find(s=>s.key===n.key)?.limit||0;n.count>=o&&r.push(n)}return r}i(fC,"findOverLimits");var gC=i(async(t,e,r,n)=>{if(w("policy.inbound.composite"),!r.policies||r.policies.length===0)throw new y(`CompositeInboundPolicy '${n}' must have valid policies defined`);let o=ve.instance,s=Pn(r.policies,o?.routeData.policies);return Za(s)(t,e)},"CompositeInboundPolicy");var hC=i(async(t,e,r,n,o)=>{if(w("policy.outbound.composite"),!n.policies||n.policies.length===0)throw new y(`CompositeOutboundPolicy '${o}' must have valid policies defined`);let s=ve.instance,a=Rn(n.policies,s?.routeData.policies);return ja(a)(t,e,r)},"CompositeOutboundPolicy");var yC=i(async(t,e,r,n)=>{w("policy.inbound.curity-phantom-token-auth");let o=t.headers.get("Authorization");if(!o)return M.unauthorized(t,e,{detail:"No authorization header"});let s=bC(o);if(!s)return M.unauthorized(t,e,{detail:"Failed to parse token from Authorization header"});let a=await Pe(n,void 0,r),u=new be(a,e),c=await u.get(s);if(!c){let l=await W.fetch(r.introspectionUrl,{headers:{Authorization:"Basic "+btoa(`${r.clientId}:${r.clientSecret}`),Accept:"application/jwt","Content-Type":"application/x-www-form-urlencoded"},method:"POST",body:"token="+s+"&token_type_hint=access_token"}),d=await l.text();if(l.status===200)c=d,u.put(s,c,r.cacheDurationSeconds??600);else return l.status>=500?(e.log.error(`Error introspecting token - ${l.status}: '${d}'`),M.internalServerError(t,e,{detail:"Problem encountered authorizing the HTTP request"})):M.unauthorized(t,e)}return t.headers.set("Authorization",`Bearer ${c}`),t},"CurityPhantomTokenInboundPolicy");function bC(t){return t.split(" ")[0]==="Bearer"?t.split(" ")[1]:null}i(bC,"getToken");var vC=i(async(t,e,r,n)=>(w("policy.inbound.firebase-jwt-auth"),ae(r,n).required("projectId","string").optional("allowUnauthenticatedRequests","boolean"),Be(t,e,{issuer:`https://securetoken.google.com/${r.projectId}`,audience:r.projectId,jwkUrl:"https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com",allowUnauthenticatedRequests:r.allowUnauthenticatedRequests,oAuthResourceMetadataEnabled:r.oAuthResourceMetadataEnabled},n)),"FirebaseJwtInboundPolicy");var wC=i(async(t,e,r)=>{w("policy.inbound.form-data-to-json");let n="application/x-www-form-urlencoded",o="multipart/form-data",s=t.headers.get("content-type")?.toLowerCase();if(!s||![o,n].some(d=>s.startsWith(d)))return r&&r.badRequestIfNotFormData?new Response(`Bad Request - expected content-type '${n}' or ${o}`,{status:400,statusText:"Bad Request"}):t;let a=await t.formData();if(r&&r.optionalHoneypotName&&a.get(r.optionalHoneypotName)!=="")return new Response("Bad Request",{status:400,statusText:"Bad Request"});let u={};for(let[d,p]of a)u[d]=p.toString();let c=new Headers(t.headers);return c.set("content-type","application/json"),c.delete("content-length"),new pe(t,{body:JSON.stringify(u),headers:c})},"FormDataToJsonInboundPolicy");var on="__unknown__",xC=i(async(t,e,r,n)=>{w("policy.inbound.geo-filter");let o={allow:{countries:an(r.allow?.countries,"allow.countries",n),regionCodes:an(r.allow?.regionCodes,"allow.regionCode",n),asns:an(r.allow?.asns,"allow.asOrganization",n)},block:{countries:an(r.block?.countries,"block.countries",n),regionCodes:an(r.block?.regionCodes,"block.regionCode",n),asns:an(r.block?.asns,"block.asOrganization",n)},ignoreUnknown:r.ignoreUnknown!==!1},s=e.incomingRequestProperties.country?.toLowerCase()??on,a=e.incomingRequestProperties.regionCode?.toLowerCase()??on,u=e.incomingRequestProperties.asn?.toString()??on,c=o.ignoreUnknown&&s===on,l=o.ignoreUnknown&&a===on,d=o.ignoreUnknown&&u===on,p=o.allow.countries,m=o.allow.regionCodes,g=o.allow.asns;if(p.length>0&&!p.includes(s)&&!c||m.length>0&&!m.includes(a)&&!l||g.length>0&&!g.includes(u)&&!d)return sn(t,e,n,s,a,u);let h=o.block.countries,v=o.block.regionCodes,b=o.block.asns;return h.length>0&&h.includes(s)&&!c||v.length>0&&v.includes(a)&&!l||b.length>0&&b.includes(u)&&!d?sn(t,e,n,s,a,u):t},"GeoFilterInboundPolicy");function sn(t,e,r,n,o,s){return e.log.debug(`Request blocked by GeoFilterInboundPolicy '${r}' (country: '${n}', regionCode: '${o}', asn: '${s}')`),M.forbidden(t,e,{geographicContext:{country:n,regionCode:o,asn:s}})}i(sn,"blockedResponse");function an(t,e,r){if(typeof t=="string")return t.split(",").map(n=>n.trim().toLowerCase());if(typeof t>"u")return[];if(Array.isArray(t))return t.map(n=>n.trim().toLowerCase());throw new y(`Invalid '${e}' for GeoFilterInboundPolicy '${r}': '${t}', must be a string or string[]`)}i(an,"toLowerStringArray");var PC=i(async(t,e,r)=>{w("policy.inbound.jwt-scope-validation");let n=t.user?.data?.scope?.split(" ")||[];if(!i((s,a)=>a.every(u=>s.includes(u)),"scopeChecker")(n,r.scopes)){let s={code:"UNAUTHORIZED",help_url:"https://zup.fail/UNAUTHORIZED",message:`JWT must have all the following scopes: ${r.scopes}`};return new Response(JSON.stringify(s),{status:401,statusText:"Unauthorized",headers:{"content-type":"application/json"}})}return t},"JWTScopeValidationInboundPolicy");var RC=i(async(t,e,r,n)=>{w("policy.inbound.mock-api");let o=e.route.raw().responses;if(!o)return gf(n,t,e,"No responses defined in the OpenAPI document. Add some responses with examples to use this policy.");let s=Object.keys(o),a=[];if(s.length===0)return gf(n,t,e,"No response object defined under responses in the OpenAPI document. Add some response objects with examples to use this policy.");if(s.forEach(u=>{o[u].content&&Object.keys(o[u].content).forEach(l=>{let d=o[u].content[l],p=d.examples,m=d.example;p?Object.keys(p).forEach(h=>{a.push({responseName:u,contentName:l,exampleName:h,exampleValue:p[h]})}):m!==void 0&&a.push({responseName:u,contentName:l,exampleName:"example",exampleValue:m})})}),a=a.filter(u=>!(r.responsePrefixFilter&&!u.responseName.startsWith(r.responsePrefixFilter)||r.contentType&&u.contentName!==r.contentType||r.exampleName&&u.exampleName!==r.exampleName)),r.random&&a.length>1){let u=Math.floor(Math.random()*a.length);return _w(a[u])}else return a.length>0?_w(a[0]):gf(n,t,e,"No examples matching the mocking options found in the OpenAPI document. Add examples to the OpenAPI document matching the options for this policy or change the mocking options to match the examples in the OpenAPI document.")},"MockApiInboundPolicy");function _w(t){let e=JSON.stringify(t.exampleValue,null,2),r=new Headers;switch(r.set("Content-Type",t.contentName),t.responseName){case"1XX":return new Response(e,{status:100,headers:r});case"2XX":return new Response(e,{status:200,headers:r});case"3XX":return new Response(e,{status:300,headers:r});case"4XX":return new Response(e,{status:400,headers:r});case"5XX":case"default":return new Response(e,{status:500,headers:r});default:return new Response(e,{status:Number(t.responseName),headers:r})}}i(_w,"generateResponse");var gf=i((t,e,r,n)=>{let o=`Error in policy: ${t} - On route ${e.method} ${r.route.path}. ${n}`;return M.internalServerError(e,r,{detail:o})},"getProblemDetailResponse");var IC="Incoming",SC={logRequestBody:!0,logResponseBody:!0};function Tw(t){let e={};return t.forEach((r,n)=>{e[n]=r}),e}i(Tw,"headersToObject");function Ew(){return new Date().toISOString()}i(Ew,"timestamp");var hf=new WeakMap,kC={};function _C(t,e){let r=hf.get(t);r||(r=kC);let n=Object.assign({...r},e);hf.set(t,n)}i(_C,"setMoesifContext");async function Cw(t,e){let r=t.headers.get("content-type");if(r&&r.indexOf("json")!==-1)try{return await t.clone().json()}catch(o){e.log.error(o)}let n=await t.clone().text();return e.log.debug({textBody:n}),n}i(Cw,"readBody");var TC={},yf;function $w(){if(!yf)throw new q("Invalid State - no _lastLogger");return yf}i($w,"getLastLogger");function EC(t){let e=TC[t];return e||(e=new ce("moesif-inbound",100,async r=>{let n=JSON.stringify(r);$w().debug("posting",n);let o=await W.fetch("https://api.moesif.net/v1/events/batch",{method:"POST",headers:{"content-type":"application/json","X-Moesif-Application-Id":t},body:n});o.ok||$w().error({status:o.status,body:await o.text()})})),e}i(EC,"getDispatcher");async function CC(t,e,r,n){w("policy.inbound.moesif-analytics"),yf=e.log;let o=Ew(),s=Object.assign(SC,r);if(!s.applicationId)throw new y(`Invalid configuration for MoesifInboundPolicy '${n}' - applicationId is required`);let a=s.logRequestBody?await Cw(t,e):void 0;return e.addResponseSendingFinalHook(async(u,c)=>{let l=EC(s.applicationId),d=at(t),p=hf.get(e)??{},m={time:o,uri:t.url,verb:t.method,body:a,ip_address:d??void 0,api_version:p.apiVersion,headers:Tw(t.headers)},g=s.logResponseBody?await Cw(u,e):void 0,h={time:Ew(),status:u.status,headers:Tw(u.headers),body:g},v={request:m,response:h,user_id:p.userId??c.user?.sub,session_token:p.sessionToken,company_id:p.companyId,metadata:p.metadata,direction:IC};l.enqueue(v),e.waitUntil(l.waitUntilFlushed())}),t}i(CC,"MoesifInboundPolicy");async function Ow(t,e,r,n){let o=re.getLogger(t),{authApiJWT:s,meteringServiceUrl:a}=R.instance,u;try{let l=await W.fetch(`${a}/internal/v1/metering/${n}/subscriptions?customerKey=${e}`,{headers:{Authorization:`Bearer ${s}`,"zp-rid":t.requestId},method:"GET"});if(l.ok)u=await l.json();else{let d=await l.json(),p=d.detail??d.title??"Unknown error on quota consumption.";t.log.error(`MonetizationInboundPolicy '${r}' - Error loading subscription. ${l.status} - ${p}`),o.error(`MonetizationInboundPolicy '${r}' - Error loading subscription.${l.status} - ${p}`)}}catch(l){o.error(`MonetizationInboundPolicy '${r}' - Error loading subscription`,l)}let c=u&&u.data&&u.data.length>0?u.data:void 0;return c&&c.length>1?c.sort((d,p)=>d.createdOn>p.createdOn?-1:1)[0]:c&&c[0]}i(Ow,"loadSubscription");async function Aw(t,e,r,n,o){let{authApiJWT:s,meteringServiceUrl:a}=R.instance,u=re.getLogger(t);try{let c=await W.fetch(`${a}/internal/v1/metering/${n}/subscriptions/${e}/quotas/consume`,{headers:{Authorization:`Bearer ${s}`,"zp-rid":t.requestId},method:"POST",body:JSON.stringify({meters:o})});if(!c.ok){let l=await c.json(),d=l.detail??l.title??"Unknown error on quota consumption.";t.log.error(`MonetizationInboundPolicy '${r}' - Error updating subscription quota. ${c.status} - ${d}`),u.error(`MonetizationInboundPolicy '${r}' - Error updating subscription quota. ${c.status} - ${d}`)}}catch(c){t.log.error(`MonetizationInboundPolicy '${r}' - Error updating subscription quota.`),u.error(`MonetizationInboundPolicy '${r}' - Error updating subscription quota.`,c)}}i(Aw,"consumeSubcriptionQuotas");var $C=new Set(["active","inactive","incomplete","incomplete-expired","trialing","past-due","canceled","unpaid"]);function na(t,e){try{let r=[];for(let n in t)typeof t[n]!="number"&&!(Number.isInteger(t[n])&&/^-?\d+$/.test(t[n].toString()))&&r.push(n);if(r.length>0)throw new y(r.length>1?`The values found in these properties are not integers : ${r.join(", ")}`:`The value in property '${r[0]}' is not an integer`)}catch(r){throw r instanceof y?new y(`MonetizationInboundPolicy '${e}' - The property 'meters' is invalid. ${r.message}`):r}}i(na,"validateMeters");function Nw(t,e){if(t)try{if(t.length===0)throw new y("Must set valid subscription statuses");let r=Nt(t),n=[];for(let o of r)$C.has(o)||n.push(o);if(n.length>0)throw new y(`Found the following invalid statuses: ${n.join(", ")}`);return t}catch(r){throw r instanceof y?new y(`MonetizationInboundPolicy '${e}' - The property 'allowedSubscriptionStatuses' is invalid. ${r.message}`):r}else return["active","incomplete","trialing"]}i(Nw,"parseAllowedSubscriptionStatuses");function Lw(t,e){let r={},n={};for(let o in e)t.hasOwnProperty(o)?r[o]=e[o]:n[o]=e[o];return{metersInSubscription:r,metersNotInSubscription:n}}i(Lw,"compareMeters");var bf=class extends xe{static{i(this,"MonetizationInboundPolicy")}static getSubscription(e){return de.get(e,fn)}static setMeters(e,r){na(r,"setMeters");let n=de.get(e,gn)??{};Object.assign(n,r),de.set(e,gn,n)}constructor(e,r){super(e,r),w("policy.inbound.monetization")}async handler(e,r){ae(this.options,this.policyName).optional("allowRequestsWithoutSubscription","boolean").optional("allowRequestsOverQuota","boolean").optional("bucketId","string"),this.options.meterOnStatusCodes||(this.options.meterOnStatusCodes="200-399");let n=this.options.allowRequestsOverQuota??!1,o=Pt(this.options.meterOnStatusCodes),s=de.get(r,gn),a={...this.options.meters,...s};na(a,this.policyName);let u=this.options.allowRequestsWithoutSubscription??!1,c=Nw(this.options.allowedSubscriptionStatuses,this.policyName);r.addResponseSendingFinalHook(async(v,b,S)=>{let x=de.get(S,fn);if((this.options.allowRequestsWithoutSubscription??!1)&&!x){S.log.debug(`MonetizationInboundPolicy '${this.policyName}' - No subscription found and property 'allowRequestsWithoutSubscription' is true`);return}if(!this.options.bucketId)if(Se.ZUPLO_METERING_SERVICE_BUCKET_ID)this.options.bucketId=Se.ZUPLO_METERING_SERVICE_BUCKET_ID;else throw new y(`MonetizationInboundPolicy '${this.policyName}' - No bucketId property provided`);let O=de.get(S,gn),L={...this.options.meters,...O};if(na(L,this.policyName),o.includes(v.status)&&x&&L){S.log.debug(`MonetizationInboundPolicy '${this.policyName}' - Updating subscription '${x.id}' with meters '${JSON.stringify(L)} on response status '${v.status}'`);let{metersInSubscription:_,metersNotInSubscription:z}=Lw(x.meters,L);if(z&&Object.keys(z).length>0){let D=Object.keys(z);S.log.warn(`The following meters cannot be applied since they are not present in the subscription: '${D}'`)}await Aw(S,x.id,this.policyName,this.options.bucketId,_)}});let l=e.user;if(!l)return u?e:M.unauthorized(e,r,{detail:"Unable to check subscription for anonymous user"});if(!this.options.bucketId)if(Se.ZUPLO_METERING_SERVICE_BUCKET_ID)this.options.bucketId=Se.ZUPLO_METERING_SERVICE_BUCKET_ID;else throw new y(`MonetizationInboundPolicy '${this.policyName}' - No bucketId property provided`);let{sub:d}=l,p=await Ow(r,d,this.policyName,this.options.bucketId);if(!p)return r.log.warn("No valid subscription found"),u?e:M.unauthorized(e,r,{detail:"No valid subscription found"});if(!c.includes(p.status)&&!u)return r.log.warn(`Subscription '${p.id}' has status '${p.status}' which is not part of the allowed statuses.`),M.unauthorized(e,r,{detail:"No valid subscription found"});c.includes(p.status)&&(r.log.debug(`Loading subscription '${p.id}' for user sub '${d}' to ContextData`),de.set(r,fn,p));let m=de.get(r,fn);if(!m)return u?e:(r.log.warn("Subscription is not available for user"),M.paymentRequired(e,r,{detail:"Subscription is not available for user",title:"No Subscription"}));if(m&&Object.keys(m.meters).length===0)return r.log.error(`Quota is not set up for subscription '${m.id}'`),M.tooManyRequests(e,r,{detail:"Quota is not set up for the user's subscription",title:"Quota Exceeded"});let h=Object.keys(a).filter(v=>!Object.keys(m.meters).includes(v));if(h.length>0)return r.log.warn(`The following policy meters are not present in the subscription: ${h.join(", ")}`),M.tooManyRequests(e,r,{detail:`The following policy meters are not present in the subscription: ${h.join(", ")}`,title:"Quota Exceeded"});for(let v of Object.keys(a))if(m.meters[v].available<=0&&!n)return M.tooManyRequests(e,r,{detail:`Quota exceeded for meter '${v}'`,title:"Quota Exceeded"});return e}};async function oa(t,e){let r=new URLSearchParams({client_id:t.clientId,client_secret:t.clientSecret,grant_type:"client_credentials"});t.scope&&r.append("scope",t.scope),t.audience&&r.append("audience",t.audience);let n=await Te({retries:t.retries?.maxRetries??3,retryDelayMs:t.retries?.delayMs??10},t.tokenEndpointUrl,{headers:{"content-type":"application/x-www-form-urlencoded"},method:"POST",body:r});if(n.status!==200){try{let s=await n.text();e.log.error(`Error getting token from identity provider. Status: ${n.status}`,s)}catch{}throw new q("Error getting token from identity provider.")}let o=await n.json();if(o&&typeof o=="object"&&"access_token"in o&&typeof o.access_token=="string"&&"expires_in"in o&&typeof o.expires_in=="number")return{access_token:o.access_token,expires_in:o.expires_in};throw new q("Response returned from identity provider is not in the expected format.")}i(oa,"getClientCredentialsAccessToken");var un=class extends Error{constructor(r,n,o){super(n,o);this.code=r}static{i(this,"OpenFGAError")}},ia=class{static{i(this,"BaseOpenFGAClient")}apiUrl;storeId;authorizationModelId;constructor(e){this.apiUrl=e.apiUrl,this.storeId=e.storeId,this.authorizationModelId=e.authorizationModelId}getStoreId(e={},r=!1){let n=e?.storeId||this.storeId;if(!r&&!n)throw new y("storeId is required");return n}getAuthorizationModelId(e={}){return e?.authorizationModelId||this.authorizationModelId}async get(e,r){return this.fetch(e,"GET",r)}async put(e,r,n){return this.fetch(e,"PUT",n,r)}post(e,r,n){return this.fetch(e,"POST",n,r)}async fetch(e,r,n,o){let s=new Headers(n.headers||{});s.set("Content-Type","application/json"),s.set("Accept","application/json"),s.set("User-Agent",R.instance.systemUserAgent);let a=`${this.apiUrl}${e}`,u=new Request(a,{method:r,headers:s,body:o?JSON.stringify(o):void 0}),c=await W.fetch(u);if(c.status!==200){let l;try{l=await c.json()}catch{}throw!l||!l.code||!l.message?new un("unknown",`Unknown error. Status: ${c.status}`):new un(l.code,l.message)}return c.json()}};function Mo(t,e,r){!t[e]&&r&&(t[e]=r)}i(Mo,"setHeaderIfNotSet");var Mw="X-OpenFGA-Client-Method",zw="X-OpenFGA-Client-Bulk-Request-Id",zo=class extends ia{static{i(this,"OpenFGAClient")}async check(e,r={}){return this.post(`/stores/${this.getStoreId(r)}/check`,{tuple_key:{user:e.user,relation:e.relation,object:e.object},context:e.context,contextual_tuples:{tuple_keys:e.contextualTuples||[]},authorization_model_id:this.getAuthorizationModelId(r)},r)}async batchCheck(e,r={}){let{headers:n={}}=r;return Mo(n,Mw,"BatchCheck"),Mo(n,zw,crypto.randomUUID()),{responses:await Promise.all(e.map(async s=>this.check(s,Object.assign({},r,n)).then(a=>(a._request=s,a)).catch(a=>{if(a instanceof un)throw a;return{allowed:void 0,error:a,_request:s}})))}}async expand(e,r={}){return this.post(`/stores/${this.getStoreId(r)}/expand`,{authorization_model_id:this.getAuthorizationModelId(r),tuple_key:e},r)}async listObjects(e,r={}){return this.post(`/stores/${this.getStoreId(r)}/list-objects`,{authorization_model_id:this.getAuthorizationModelId(r),user:e.user,relation:e.relation,type:e.type,context:e.context,contextual_tuples:{tuple_keys:e.contextualTuples||[]}},r)}async listRelations(e,r={}){let{user:n,object:o,relations:s,contextualTuples:a,context:u}=e,{headers:c={}}=r;if(Mo(c,Mw,"ListRelations"),Mo(c,zw,crypto.randomUUID()),!s?.length)throw new Error("When calling listRelations, at least one relation must be passed in the relations field");let l=await this.batchCheck(s.map(p=>({user:n,relation:p,object:o,contextualTuples:a,context:u})),Object.assign({},r,c)),d=l.responses.find(p=>p.error);if(d)throw d.error;return{relations:l.responses.filter(p=>p.allowed).map(p=>p._request.relation)}}async listUsers(e,r={}){return this.post(`/stores/${this.getStoreId(r)}/list-users`,{authorization_model_id:this.getAuthorizationModelId(r),relation:e.relation,object:e.object,user_filters:e.user_filters,context:e.context,contextual_tuples:e.contextualTuples||[]},r)}};var Uw=Symbol("openfga-authz-context-data"),cn=class extends xe{static{i(this,"BaseOpenFGAAuthZInboundPolicy")}client;authorizer;cache;static setContextChecks(e,r){let n=Array.isArray(r)?r:[r];de.set(e,Uw,n)}constructor(e,r){if(super(e,r),ae(e,r).required("apiUrl","string").optional("storeId","string").optional("authorizationModelId","string"),!e.credentials)throw new y(`${this.policyType} '${this.policyName}' - The 'credentials' option is required.`);if(e.credentials.method==="client-credentials")ae(e.credentials,r).required("clientId","string").required("clientSecret","string").required("oauthTokenEndpointUrl","string").optional("apiAudience","string");else if(e.credentials.method==="api-token")ae(e.credentials,r).required("token","string").optional("headerName","string").optional("headerValuePrefix","string");else if(e.credentials.method==="header")ae(e.credentials,r).optional("headerName","string");else if(e.credentials.method!=="none")throw new y(`${this.policyType} '${this.policyName}' - The 'credentials.method' option is invalid. It must be set to either 'none', 'api-token', 'client-credentials', or 'header'.`);this.authorizer=this.getAuthorizer(e.credentials),this.client=new zo({apiUrl:e.apiUrl,storeId:e.storeId,authorizationModelId:e.authorizationModelId})}async handler(e,r){if(!this.cache){let a=await Pe(this.policyName,void 0,this.options);this.cache=new be(a,r)}let n=i(a=>this.options.allowUnauthorizedRequests?e:M.forbidden(e,r,{detail:a}),"forbiddenResponse"),o=de.get(r,Uw);if(!o||o.length===0)throw new q(`${this.policyType} '${this.policyName}' - No checks found in the context.`);let s=await this.authorizer(e,r);try{r.log.debug("OpenFGA checks",o);let a=await this.client.batchCheck(o,{headers:s});return r.log.debug("OpenFGA Response",a),a.responses.every(u=>u.allowed)?e:(r.log.debug(`${this.policyType} '${this.policyName}' - The request was not authorized.`,a),n("The request was not authorized."))}catch(a){return r.log.error(`${this.policyType} '${this.policyName}' - Error calling OpenFGA service`,a),M.internalServerError(e,r)}}getAuthorizer(e){if(e.method==="none")return async()=>({});if(e.method==="header")return async r=>{let n=e.headerName??"Authorization",o=r.headers.get(n);if(!o)throw new ue(`${this.policyType} '${this.policyName}' - The header '${n}' is missing.`);return{[n]:o}};if(e.method==="api-token")return async()=>({[e.headerName??"Authorization"]:`${e.headerValuePrefix??"Bearer "} ${e.token}`});if(e.method==="client-credentials")return async(r,n)=>{let o=await this.cache?.get("client_credentials_token");if(o)return{Authorization:`Bearer ${o}`};let s=await oa({tokenEndpointUrl:e.oauthTokenEndpointUrl,clientId:e.clientId,clientSecret:e.clientSecret,audience:e.apiAudience},n);return this.cache?.put("client_credentials_token",s.access_token,s.expires_in),{Authorization:`Bearer ${s.access_token}`}};throw new q("Invalid state for credentials method is not valid. This should not happen.")}};var Dw=["us1","eu1","au1"],vf=class extends cn{static{i(this,"OktaFGAAuthZInboundPolicy")}constructor(e,r){if(!Dw.includes(e.region))throw new y(`OktaFGAAuthZInboundPolicy '${r}' - The 'region' option is invalid. Must be one of ${Dw.join(", ")}.`);let n={...e,apiUrl:`https://api.${e.region}.fga.dev`,credentials:{method:"client-credentials",oauthTokenEndpointUrl:"https://fga.us.auth0.com/oauth/token",clientId:e.credentials.clientId,clientSecret:e.credentials.clientSecret,apiAudience:`https://api.${e.region}.fga.dev/`}};super(n,r),w("policy.inbound.oktafga-authz")}};import{importJWK as OC,SignJWT as AC}from"jose";var Zw=!1,Uo=class t extends Ee{static{i(this,"JwtServicePlugin")}#e;static#t=void 0;static#n=void 0;static#r=void 0;static#o=void 0;static async signJwt({audience:e,subject:r,expiresIn:n=t.#r,...o}){if(!t.#n){let c=R.instance.authPrivateKey;if(!c)throw new y("JwtServicePlugin - Cannot sign JWT. Private key configured for this Zuplo project.");try{t.#n=await OC(JSON.parse(c),"EdDSA")}catch(l){throw new y("JwtServicePlugin - Failed to import private key. Ensure it is a valid JWK format.",{cause:l})}}if(!t.#t)throw new y("JwtServicePlugin - Cannot sign JWT. The issuer URL is not configured. Ensure the plugin is initialized.");if(!t.#r)throw new y("JwtServicePlugin - Cannot sign JWT. The token expiration is not configured. Ensure the plugin is initialized.");let s=n??t.#r,a=typeof s=="number"?new Date(Date.now()+s*1e3):s,u=new AC(o).setProtectedHeader({alg:"EdDSA"}).setIssuer(t.#t).setIssuedAt(new Date).setExpirationTime(a);return e&&u.setAudience(e),r&&u.setSubject(r),await u.sign(t.#n)}constructor(e){if(super(),Zw)throw new y("JwtServicePlugin - Only one instance of JwtServicePlugin can be created. Ensure you are not creating multiple instances in your code.");Zw=!0,this.#e=e?.basePath??"/__zuplo/issuer",t.#r=e?.expiresIn??"1h",this.#e.endsWith("/")&&(this.#e=this.#e.slice(0,-1))}registerRoutes({runtimeSettings:e,router:r}){let n=e.api.urls?.defaultUrl;if(!n)throw new y("JwtServicePlugin - Cannot determine issuer URL. Ensure the API is properly configured.");let o=new URL(this.#e,n).toString();t.#t=o,r.addPluginRoute({methods:["GET"],path:`${this.#e}/.well-known/openid-configuration`,handler:i(async()=>{let s={issuer:o,jwks_uri:`${o}/.well-known/jwks.json`,id_token_signing_alg_values_supported:["EdDSA"],subject_types_supported:["public"]};return new Response(JSON.stringify(s),{headers:{"Content-Type":"application/json","Cache-Control":"public, max-age=15, stale-while-revalidate=15, stale-if-error=86400"}})},"handler")}),r.addPluginRoute({methods:["GET"],path:`${this.#e}/.well-known/jwks.json`,handler:i(async()=>{if(!t.#o)try{let s=R.instance.authPublicKey;if(!s)throw new y("JwtServicePlugin - Public key is not configured for this Zuplo project");let a={keys:[JSON.parse(s)]};t.#o=JSON.stringify(a)}catch(s){throw new y("JwtServicePlugin - Failed to export public key as JWK.",{cause:s})}return new Response(t.#o,{headers:{"Content-Type":"application/json","Cache-Control":"public, max-age=15, stale-while-revalidate=15, stale-if-error=86400"}})},"handler")})}};var wf=class extends xe{static{i(this,"UpstreamZuploJwtAuthInboundPolicy")}constructor(e,r){super(e,r);let n=ae(e,r);if(n.optional("audience","string"),n.optional("headerName","string"),n.optional("additionalClaims","object"),e.tokenPrefix!==void 0&&typeof e.tokenPrefix!="string")throw new y(`Value of 'tokenPrefix' on UpstreamZuploJwtInboundPolicy must be a string. Received type ${typeof e.tokenPrefix}.`);if(e.expiresIn!==void 0&&typeof e.expiresIn!="number"&&typeof e.expiresIn!="string")throw new y(`Value of 'expiresIn' on UpstreamZuploJwtInboundPolicy must be a number or string. Received type ${typeof e.expiresIn}.`)}async handler(e,r){w("policy.inbound.upstream-zuplo-jwt");let{audience:n,headerName:o="Authorization",tokenPrefix:s="Bearer",additionalClaims:a={},expiresIn:u=3600}=this.options,c={audience:n,expiresIn:u,...a},l=await Uo.signJwt(c),d=s?`${s} ${l}`:l,p=new Headers(e.headers);return p.set(o,d),new pe(e,{headers:p})}};var NC=i(async(t,e,r,n)=>(w("policy.inbound.okta-jwt-auth"),Be(t,e,{issuer:r.issuerUrl,audience:r.audience,jwkUrl:`${r.issuerUrl}/v1/keys`,allowUnauthenticatedRequests:r.allowUnauthenticatedRequests,oAuthResourceMetadataEnabled:r.oAuthResourceMetadataEnabled},n)),"OktaJwtInboundPolicy");var xf=class extends cn{static{i(this,"OpenFGAAuthZInboundPolicy")}constructor(e,r){super(e,r),w("policy.inbound.openfga-authz")}};import{importSPKI as LC}from"jose";var Pf,MC=i(async(t,e,r,n)=>{if(w("policy.inbound.propel-auth-jwt-auth"),!Pf)try{Pf=await LC(r.verifierKey,"RS256")}catch(o){throw e.log.error("Could not import verifier key"),o}return Be(t,e,{issuer:r.authUrl,secret:Pf,allowUnauthenticatedRequests:r.allowUnauthenticatedRequests,subPropertyName:"user_id",oAuthResourceMetadataEnabled:r.oAuthResourceMetadataEnabled},n)},"PropelAuthJwtInboundPolicy");var Rf="quota-inbound-policy-f307056c-8c00-4f2c-b4ac-c0ac7d04eca0",jw="quota-usage-2017e968-4de8-4a63-8951-1e423df0d64b";var If=class t extends xe{static{i(this,"QuotaInboundPolicy")}constructor(e,r){super(e,r),w("policy.inbound.quota")}async handler(e,r){let n=this.options.debug??!1;r.log.debug({debug:n}),ae(this.options,this.policyName).required("period","string").required("quotaBy","string").optional("quotaAnchorMode","string").optional("allowances","object"),t.setMeters(r,{requests:1});let o=re.getLogger(r);try{let s=zC(this.options,this.policyName),a=s.functions.getAnchorDate(e,r,this.policyName),u=s.functions.getQuotaDetail(e,r,this.policyName),[c,l]=await Promise.all([a,u]),d=UC(l.key,this.policyName);n&&r.log.debug(`QuotaInboundPolicy: key - '${d}'`);let p=ir(this.policyName,o),m=await p.getQuota(d,r.requestId);t.#e(r,this.policyName,m),n&&r.log.debug("QuotaInboundPolicy: quotaResult",m),c&&new Date(m.anchorDate).getTime()!==c.getTime()&&r.log.warn(`QuotaInboundPolicy '${this.policyName}' provided anchorDate ('${c}') did not match the stored, immutable anchorDate ('${m.anchorDate}')`);let g=Object.assign({},s.defaultAllowances);Object.assign(g,l.allowances);let h=[],v="";if(Object.entries(g).forEach(([b,S])=>{n&&(v+=`${b} - allowed: ${S} value: ${m.meters[b]??0}