@zuplo/runtime 6.64.21 → 6.64.24
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 +1 -1
- package/out/esm/index.js.map +1 -1
- package/package.json +1 -1
package/out/esm/index.js
CHANGED
|
@@ -278,7 +278,7 @@ data: [DONE]
|
|
|
278
278
|
|
|
279
279
|
`)}return{text:m,model:f,chatId:g,events:b}}return s(p,"processSSEBuffer"),new TransformStream({async transform(m,f){if(u.isBlocked)return;let g=o.decode(m,{stream:!0});u.sseBuffer+=g;let{text:b,model:h,chatId:x,events:v}=p();if(b&&(u.accumulatedText+=b),h&&!u.model&&(u.model=h),x&&!u.chatId&&(u.chatId=x),v.length>0&&(u.pendingEvents.push(...v),u.chunkCount+=v.length),(a&&u.pendingEvents.length>=a||c&&Date.now()-u.lastCheckTime>=c)&&u.accumulatedText){let A=await d();if(u.lastCheckTime=Date.now(),A){u.isBlocked=!0,n.warn("Block detected, discarding pending events",{provider:r,requestId:t.requestId,chunkCount:u.chunkCount,isBlocked:u.isBlocked,discardedEvents:u.pendingEvents.length}),u.pendingEvents=[l()];return}for(let C of u.pendingEvents)f.enqueue(i.encode(C));u.sentEvents.push(...u.pendingEvents),u.pendingEvents=[],n.debug("Events sent status",{totalEventsSent:u.sentEvents.length,pendingEvents:0,provider:r})}},async flush(m){if(u.sseBuffer.length>0&&!u.isBlocked){let{text:f,model:g,chatId:b,events:h}=p();f&&(u.accumulatedText+=f),g&&!u.model&&(u.model=g),b&&!u.chatId&&(u.chatId=b),h.length>0&&u.pendingEvents.push(...h)}if(u.isBlocked){if(u.pendingEvents.length>0){n.warn("Sending error events from flush",{provider:r,requestId:t.requestId,eventsCount:u.pendingEvents.length});for(let f of u.pendingEvents)m.enqueue(i.encode(f));u.pendingEvents=[]}return}if(u.pendingEvents.length>0){u.accumulatedText&&await d()&&(u.isBlocked=!0,n.warn("Flush: Block detected, content_filter event sent",{provider:r,requestId:t.requestId,previousPendingEvents:u.pendingEvents.length}),u.pendingEvents=[l()]);for(let f of u.pendingEvents)m.enqueue(i.encode(f));u.sentEvents.push(...u.pendingEvents),u.pendingEvents=[]}n.info("Akamai streaming accumulator completed",{provider:r,requestId:t.requestId,totalChunks:u.chunkCount,wasBlocked:u.isBlocked,accumulatedLength:u.accumulatedText.length})}})}s(Vv,"createAkamaiStreamingAccumulator");function Jv(t){return!t||!Array.isArray(t)?"":t.map(e=>typeof e.content=="string"?e.content:Array.isArray(e.content)?e.content.filter(r=>r.type==="text"&&typeof r.text=="string").map(r=>r.text).join(" "):"").filter(Boolean).join(`
|
|
280
280
|
`)}s(Jv,"extractTextFromMessages");function Wv(t){if(!t)return"";let e=t;return e.choices&&Array.isArray(e.choices)?e.choices.map(r=>{let n=r,o=n.message;return o?.content&&typeof o.content=="string"?o.content:n.text&&typeof n.text=="string"?n.text:""}).filter(Boolean).join(`
|
|
281
|
-
`):(e.data&&e.object==="list"||e.error,"")}s(Wv,"extractTextFromResponse");async function yf(t,e,r,n,o){if(!t)return o.debug(`No text content to analyze for ${e}`),null;try{let i=`https://aisec.akamai.com/fai/v1/fai-configurations/${n.configurationId}/detect`,a={clientRequestId:r.requestId};n.applicationId&&(a.userApplicationId=n.applicationId),e==="input"?a.llmInput=t:a.llmOutput=t,o.debug(`Calling Akamai API for ${e}`,{contentLength:t.length});let c=await z.fetch(i,{method:"POST",headers:{"Content-Type":"application/json","Fai-Api-Key":n["api-key"]},body:JSON.stringify(a)});if(!c.ok)throw new Error(`Akamai API call failed: ${c.status} ${c.statusText}`);let u=await c.json();return o.debug(`Akamai response for ${e}`,{overallRiskScore:u.overallRiskScore,rulesTriggered:u.rulesTriggered.length}),u.rulesTriggered.find(d=>d.action==="deny")||null}catch(i){return o.error(i,`Failed to check with Akamai for ${e}`),null}}s(yf,"checkWithAkamai");function bf(t,e){let r={error:{message:`Request blocked by AI Firewall during ${e}. ${t.message} (Rule: ${t.ruleId})`,code:t.ruleId}};return new Response(JSON.stringify(r),{status:400,headers:{"Content-Type":"application/json"}})}s(bf,"createBlockedResponse");var mn=Ne("zuplo:policies:AkamaiAIFirewallPolicy");async function O_(t,e,r,n){R("policy.inbound.akamai-ai-firewall");let o=K.getLogger(e),i=Date.now();try{let a=t.user,c=a?.configuration?.policies?.["akamai-ai-firewall"];if(!c?.enabled)return mn("Akamai AI Firewall not enabled for this user, passing through"),t;let u=c;mn("Using dynamic configuration from AI Gateway");let l,d,p=!1;try{l=await t.clone().json(),p=l?.stream===!0,d=Jv(l?.messages)}catch{o.warn("Could not parse request body for Akamai AI Firewall")}if(d){mn("Checking LLM input with Akamai");let m=await yf(d,"input",e,u,o);if(m){let f=a?.configuration?.id;return e.analyticsContext.addAnalyticsEvent(1,Oe.AI_GATEWAY_BLOCKED_COUNT,{type:"akamai-firewall-input",configId:f??null}),bf(m,"completion request")}}return e.addResponseSendingHook(async(m,f,g)=>{try{if(p&&m.body){if(u.streamingAccumulation?.enabled!==!1){mn("Setting up streaming accumulator for response validation");let x=Vv(g,u,"ai-gateway"),v=m.body.pipeThrough(x);return new Response(v,{status:m.status,statusText:m.statusText,headers:m.headers})}return m}if(!p){mn("Checking non-streaming LLM output with Akamai");let b;try{let x=await m.clone().json();b=Wv(x)}catch{o.warn("Could not parse response body for Akamai AI Firewall")}if(b){let h=await yf(b,"output",g,u,o);if(h){let x=a?.configuration?.id;return g.analyticsContext.addAnalyticsEvent(1,Oe.AI_GATEWAY_BLOCKED_COUNT,{type:"akamai-firewall-output",configId:x??null}),bf(h,"completion response")}}}return m}catch(b){return o.error(b,"Failed to check LLM output"),m}}),t}catch(a){return o.error(a,"Error in AkamaiAIFirewallInboundPolicy"),t}finally{let a=Date.now()-i;mn(`AkamaiAIFirewallInboundPolicy completed - latency ${a}ms`)}}s(O_,"AkamaiAIFirewallInboundPolicy");var Qv=new WeakMap,Kv={},wf=class{static{s(this,"AmberfloMeteringPolicy")}static setRequestProperties(e,r){Qv.set(e,r)}};async function $_(t,e,r,n){if(R("policy.inbound.amberflo-metering"),!r.statusCodes)throw new w(`Invalid AmberfloMeterInboundPolicy '${n}': options.statusCodes must be an array of HTTP status code numbers`);let o=It(r.statusCodes);return e.addResponseSendingFinalHook(async i=>{if(o.includes(i.status)){let a=Qv.get(e),c=r.customerId;if(r.customerIdPropertyPath){if(!t.user)throw new F(`Unable to apply customerIdPropertyPath '${r.customerIdPropertyPath}' as request.user is 'undefined'.`);c=Mt(t.user,r.customerIdPropertyPath,"customerIdPropertyPath")}let u=a?.customerId??c;if(!u){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:u,meterApiName:l,meterValue:d,meterTimeInMillis:Date.now(),dimensions:Object.assign(r.dimensions??{},a?.dimensions)},m=Kv[r.apiKey];if(!m){let f=r.apiKey,g=t.headers.get("zm-test-id")??"";m=new ce("amberflo-ingest-meter",10,async b=>{try{let h=r.url??"https://app.amberflo.io/ingest",x=await z.fetch(h,{method:"POST",body:JSON.stringify(b),headers:{"content-type":"application/json","x-api-key":f,"zm-test-id":g}});x.ok||e.log.error(`Unexpected response in AmberfloMeteringInboundPolicy '${n}'. ${x.status}: ${await x.text()}`)}catch(h){throw e.log.error(`Error in AmberfloMeteringInboundPolicy '${n}': ${h.message}`),h}}),Kv[f]=m}m.enqueue(p),e.waitUntil(m.waitUntilFlushed())}}),t}s($_,"AmberfloMeteringInboundPolicy");var Xv="key-metadata-cache-type";function A_(t,e){return e.authScheme===""?t:t.replace(`${e.authScheme} `,"")}s(A_,"getKeyValue");async function vf(t,e,r,n){if(R("policy.inbound.api-key"),!r.bucketName)if(Ie.ZUPLO_API_KEY_SERVICE_BUCKET_NAME)r.bucketName=Ie.ZUPLO_API_KEY_SERVICE_BUCKET_NAME;else throw new w(`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 w(`ApiKeyInboundPolicy '${n}' - minimum cacheTtlSeconds value is 60s, '${o.cacheTtlSeconds}' is invalid`);let i=s(x=>o.allowUnauthenticatedRequests?t:D.unauthorized(t,e,{detail:x}),"unauthorizedResponse"),a=t.headers.get(o.authHeader);if(!a)return i("No Authorization Header");if(!a.toLowerCase().startsWith(o.authScheme.toLowerCase()))return i("Invalid Authorization Scheme");let c=A_(a,o);if(!c||c==="")return i("No key present");let u=await N_(c),l=await xe(n,void 0,o),d=new be(l,e),p=await d.get(u);if(p&&p.isValid===!0)return t.user=p.user,t;if(p&&!p.isValid)return p.typeId!==Xv&&K.getLogger(e).error(`ApiKeyInboundPolicy '${n}' - cached metadata has invalid typeId '${p.typeId}'`,p),i("Authorization Failed");let m={key:c},f=new Headers({"content-type":"application/json"});je(f,e.requestId);let g=await Te({retryDelayMs:5,retries:2,logger:K.getLogger(e)},`${P.instance.apiKeyServiceUrl}/v1/$validate/${o.bucketName}`,{method:"POST",headers:f,body:JSON.stringify(m)});if(g.status===401)return e.log.info(`ApiKeyInboundPolicy '${n}' - 401 response from Key Service`),i("Authorization Failed");if(g.status!==200){try{let x=await g.text(),v=JSON.parse(x);e.log.error("Unexpected response from key service",v)}catch{e.log.error("Invalid response from key service")}throw new F(`ApiKeyInboundPolicy '${n}' - unexpected response from Key Service. Status: ${g.status}`)}let b=await g.json(),h={isValid:!0,typeId:Xv,user:{apiKeyId:b.id,sub:b.name,data:b.metadata}};return t.user=h.user,d.put(u,h,o.cacheTtlSeconds),t}s(vf,"ApiKeyInboundPolicy");async function N_(t){let e=new TextEncoder().encode(t),r=await crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(r)).map(i=>i.toString(16).padStart(2,"0")).join("")}s(N_,"hashValue");var L_=vf;import{createRemoteJWKSet as D_,jwtVerify as ex}from"jose";import{createLocalJWKSet as M_}from"jose";var xf=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{s(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 Rf&&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",P.instance.systemUserAgent),this.options.headers=Object.fromEntries(e.entries())),this.pendingFetch||=this.fetchJwks(this.url,this.timeoutDuration,this.options).then(r=>{this.local=M_(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 i,a,c=!1;typeof AbortController=="function"&&(i=new AbortController,a=setTimeout(()=>{c=!0,i.abort()},r));let u=await z.fetch(e.href,{signal:i?i.signal:void 0,redirect:"manual",headers:n.headers}).catch(l=>{throw c?new Pf("JWKS fetch timed out"):l});if(a!==void 0&&clearTimeout(a),u.status!==200)throw new fn("Expected 200 OK from the JSON Web Key Set HTTP response");try{let l=await u.json();return this.cache.put(this.url.href,l,this.cacheMaxAge),l}catch{throw new fn("Failed to parse the JSON Web Key Set HTTP response as JSON")}}};function Yv(t,e,r){let n=new xf(t,e,r);return async(o,i)=>n.getKey(o,i)}s(Yv,"createRemoteJWKSet");var fn=class extends F{static{s(this,"JWKSError")}},Rf=class extends fn{static{s(this,"JWKSNoMatchingKey")}},Pf=class extends fn{static{s(this,"JWKSTimeout")}};var ha={},U_=s((t,e)=>async(r,n)=>{if(!n.jwkUrl||typeof n.jwkUrl!="string")throw new w("Invalid State - jwkUrl not set");if(!ha[n.jwkUrl]){let i=!1;if("useExperimentalInMemoryCache"in n&&typeof n.useExperimentalInMemoryCache=="boolean"&&(i=n.useExperimentalInMemoryCache),i){let a=await xe(t,void 0,n),c=new be(a,e);ha[n.jwkUrl]=Yv(new URL(n.jwkUrl),c,n.headers?{headers:n.headers}:void 0)}else ha[n.jwkUrl]=D_(new URL(n.jwkUrl),n.headers?{headers:n.headers}:void 0)}let{payload:o}=await ex(r,ha[n.jwkUrl],{issuer:n.issuer,audience:n.audience});return o},"createJwkVerifier"),z_=s(async(t,e)=>{let r;if(e.secret===void 0)throw new w("secretVerifier requires secret to be defined");if(typeof e.secret=="string"){let i=new TextEncoder().encode(e.secret);r=new Uint8Array(i)}else r=e.secret;let{payload:n}=await ex(t,r,{issuer:e.issuer,audience:e.audience});return n},"secretVerifier");function j_(t){let e=we.instance,n=`/.well-known/oauth-protected-resource${t.pathname}`;return bt.some(a=>a instanceof Go)?!0:e.routeData.routes.some(a=>{let c=a.pathPattern||a.path;try{return new sa({pathname:c}).test({pathname:n})}catch{return!1}})}s(j_,"ensureOAuthResourceMetadataRouteExists");var Je=s(async(t,e,r,n)=>{R("policy.inbound.open-id-jwt-auth");let o=r.authHeader??"Authorization",i=t.headers.get(o),a="bearer ",c=s(f=>D.unauthorized(t,e,{detail:f}),"unauthorizedResponse");if(!r.jwkUrl&&!r.secret)throw new w(`OpenIdJwtInboundPolicy policy '${n}': One of 'jwkUrl' or 'secret' options are required.`);if(r.jwkUrl&&r.secret)throw new w(`OpenIdJwtInboundPolicy policy '${n}': Only one of 'jwkUrl' and 'secret' options should be provided.`);let u=r.jwkUrl?U_(n,e):z_,d=await s(async()=>{if(!i){let g=new URL(t.url);if(r.oAuthResourceMetadataEnabled&&j_(g)){let b=new URL(`/.well-known/oauth-protected-resource${g.pathname}`,g.origin);return D.unauthorized(t,e,{detail:"Bearer token required"},{"WWW-Authenticate":`resource_metadata=${b.toString()}`})}return c("No authorization header")}if(i.toLowerCase().indexOf(a)!==0)return c("Invalid bearer token format for authorization header");let f=i.substring(a.length);if(!f||f.length===0)return c("No bearer token on authorization header");try{return await u(f,r)}catch(g){let b=new URL(t.url);return"code"in g&&g.code==="ERR_JWT_EXPIRED"?e.log.warn(`Expired token used on url: ${b.pathname} `,g):e.log.warn(`Invalid token on: ${t.method} ${b.pathname}`,g),c("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):c(`Token is not valid, no '${p}' property found.`)},"OpenIdJwtInboundPolicy");var Z_=s(async(t,e,r,n)=>(R("policy.inbound.auth0-jwt-auth"),Je(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 tx=new Map;function q_(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 i=t.substring(o,r);for(e.push(i),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}s(q_,"parsePropertyPath");function ya(t,e){let r="$authzen-prop(";if(!t.startsWith(r)||!t.endsWith(")"))return t;let n=t.slice(r.length,-1),o=tx.get(n);o||(o=q_(n),tx.set(n,o));let i=e;for(let a of o){if(i==null)return;typeof i.get=="function"?i=i.get(a):i=i[a]}return i}s(ya,"evaluateAuthzenProp");var rx=Symbol("AUTHZEN_CONTEXT_DATA_52a5cf22-d922-4673-9815-6dc3d49071d9"),If=class t extends Re{static{s(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 w(`${this.policyType} '${this.policyName}' - subject.type is required.`);if(e.subject&&!e.subject.id)throw new w(`${this.policyType} '${this.policyName}' - subject.id is required.`);if(e.resource&&!e.resource.type)throw new w(`${this.policyType} '${this.policyName}' - resource.type is required.`);if(e.resource&&!e.resource.id)throw new w(`${this.policyType} '${this.policyName}' - resource.id is required.`);if(e.action&&!e.action.name)throw new w(`${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 w(`${this.policyType} '${this.policyName}' - authorizerUrl '${this.#e}' is not valid
|
|
281
|
+
`):(e.data&&e.object==="list"||e.error,"")}s(Wv,"extractTextFromResponse");async function yf(t,e,r,n,o){if(!t)return o.debug(`No text content to analyze for ${e}`),null;try{let i=`https://aisec.akamai.com/fai/v1/fai-configurations/${n.configurationId}/detect`,a={clientRequestId:r.requestId};n.applicationId&&(a.userApplicationId=n.applicationId),e==="input"?a.llmInput=t:a.llmOutput=t,o.debug(`Calling Akamai API for ${e}`,{contentLength:t.length});let c=await z.fetch(i,{method:"POST",headers:{"Content-Type":"application/json","Fai-Api-Key":n["api-key"]},body:JSON.stringify(a)});if(!c.ok)throw c.status===401?r.log.warn("Akamai AI Firewall API key is invalid. Please check the Application ID and API key in your policy configuration."):c.status===429?r.log.warn("Akamai AI Firewall rate limit exceeded. Please contact Akamai support."):r.log.warn(`Request to Akamai AI Firewall failed with ${c.status} ${c.statusText}`),new Error(`Akamai API call failed: ${c.status} ${c.statusText}`);let u=await c.json();return o.debug(`Akamai response for ${e}`,{overallRiskScore:u.overallRiskScore,rulesTriggered:u.rulesTriggered.length}),u.rulesTriggered.find(d=>d.action==="deny")||null}catch(i){return o.error(i,`Failed to check with Akamai for ${e}`),null}}s(yf,"checkWithAkamai");function bf(t,e){let r={error:{message:`Request blocked by AI Firewall during ${e}. ${t.message} (Rule: ${t.ruleId})`,code:t.ruleId}};return new Response(JSON.stringify(r),{status:400,headers:{"Content-Type":"application/json"}})}s(bf,"createBlockedResponse");var mn=Ne("zuplo:policies:AkamaiAIFirewallPolicy");async function O_(t,e,r,n){R("policy.inbound.akamai-ai-firewall");let o=K.getLogger(e),i=Date.now();try{let a=t.user,c=a?.configuration?.policies?.["akamai-ai-firewall"];if(!c?.enabled)return mn("Akamai AI Firewall not enabled for this user, passing through"),t;let u=c;mn("Using dynamic configuration from AI Gateway");let l,d,p=!1;try{l=await t.clone().json(),p=l?.stream===!0,d=Jv(l?.messages)}catch{o.warn("Could not parse request body for Akamai AI Firewall")}if(d){mn("Checking LLM input with Akamai");let m=await yf(d,"input",e,u,o);if(m){let f=a?.configuration?.id;return e.analyticsContext.addAnalyticsEvent(1,Oe.AI_GATEWAY_BLOCKED_COUNT,{type:"akamai-firewall-input",configId:f??null}),bf(m,"completion request")}}return e.addResponseSendingHook(async(m,f,g)=>{try{if(p&&m.body){if(u.streamingAccumulation?.enabled!==!1){mn("Setting up streaming accumulator for response validation");let x=Vv(g,u,"ai-gateway"),v=m.body.pipeThrough(x);return new Response(v,{status:m.status,statusText:m.statusText,headers:m.headers})}return m}if(!p){mn("Checking non-streaming LLM output with Akamai");let b;try{let x=await m.clone().json();b=Wv(x)}catch{o.warn("Could not parse response body for Akamai AI Firewall")}if(b){let h=await yf(b,"output",g,u,o);if(h){let x=a?.configuration?.id;return g.analyticsContext.addAnalyticsEvent(1,Oe.AI_GATEWAY_BLOCKED_COUNT,{type:"akamai-firewall-output",configId:x??null}),bf(h,"completion response")}}}return m}catch(b){return o.error(b,"Failed to check LLM output"),m}}),t}catch(a){return o.error(a,"Error in AkamaiAIFirewallInboundPolicy"),t}finally{let a=Date.now()-i;mn(`AkamaiAIFirewallInboundPolicy completed - latency ${a}ms`)}}s(O_,"AkamaiAIFirewallInboundPolicy");var Qv=new WeakMap,Kv={},wf=class{static{s(this,"AmberfloMeteringPolicy")}static setRequestProperties(e,r){Qv.set(e,r)}};async function $_(t,e,r,n){if(R("policy.inbound.amberflo-metering"),!r.statusCodes)throw new w(`Invalid AmberfloMeterInboundPolicy '${n}': options.statusCodes must be an array of HTTP status code numbers`);let o=It(r.statusCodes);return e.addResponseSendingFinalHook(async i=>{if(o.includes(i.status)){let a=Qv.get(e),c=r.customerId;if(r.customerIdPropertyPath){if(!t.user)throw new F(`Unable to apply customerIdPropertyPath '${r.customerIdPropertyPath}' as request.user is 'undefined'.`);c=Mt(t.user,r.customerIdPropertyPath,"customerIdPropertyPath")}let u=a?.customerId??c;if(!u){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:u,meterApiName:l,meterValue:d,meterTimeInMillis:Date.now(),dimensions:Object.assign(r.dimensions??{},a?.dimensions)},m=Kv[r.apiKey];if(!m){let f=r.apiKey,g=t.headers.get("zm-test-id")??"";m=new ce("amberflo-ingest-meter",10,async b=>{try{let h=r.url??"https://app.amberflo.io/ingest",x=await z.fetch(h,{method:"POST",body:JSON.stringify(b),headers:{"content-type":"application/json","x-api-key":f,"zm-test-id":g}});x.ok||e.log.error(`Unexpected response in AmberfloMeteringInboundPolicy '${n}'. ${x.status}: ${await x.text()}`)}catch(h){throw e.log.error(`Error in AmberfloMeteringInboundPolicy '${n}': ${h.message}`),h}}),Kv[f]=m}m.enqueue(p),e.waitUntil(m.waitUntilFlushed())}}),t}s($_,"AmberfloMeteringInboundPolicy");var Xv="key-metadata-cache-type";function A_(t,e){return e.authScheme===""?t:t.replace(`${e.authScheme} `,"")}s(A_,"getKeyValue");async function vf(t,e,r,n){if(R("policy.inbound.api-key"),!r.bucketName)if(Ie.ZUPLO_API_KEY_SERVICE_BUCKET_NAME)r.bucketName=Ie.ZUPLO_API_KEY_SERVICE_BUCKET_NAME;else throw new w(`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 w(`ApiKeyInboundPolicy '${n}' - minimum cacheTtlSeconds value is 60s, '${o.cacheTtlSeconds}' is invalid`);let i=s(x=>o.allowUnauthenticatedRequests?t:D.unauthorized(t,e,{detail:x}),"unauthorizedResponse"),a=t.headers.get(o.authHeader);if(!a)return i("No Authorization Header");if(!a.toLowerCase().startsWith(o.authScheme.toLowerCase()))return i("Invalid Authorization Scheme");let c=A_(a,o);if(!c||c==="")return i("No key present");let u=await N_(c),l=await xe(n,void 0,o),d=new be(l,e),p=await d.get(u);if(p&&p.isValid===!0)return t.user=p.user,t;if(p&&!p.isValid)return p.typeId!==Xv&&K.getLogger(e).error(`ApiKeyInboundPolicy '${n}' - cached metadata has invalid typeId '${p.typeId}'`,p),i("Authorization Failed");let m={key:c},f=new Headers({"content-type":"application/json"});je(f,e.requestId);let g=await Te({retryDelayMs:5,retries:2,logger:K.getLogger(e)},`${P.instance.apiKeyServiceUrl}/v1/$validate/${o.bucketName}`,{method:"POST",headers:f,body:JSON.stringify(m)});if(g.status===401)return e.log.info(`ApiKeyInboundPolicy '${n}' - 401 response from Key Service`),i("Authorization Failed");if(g.status!==200){try{let x=await g.text(),v=JSON.parse(x);e.log.error("Unexpected response from key service",v)}catch{e.log.error("Invalid response from key service")}throw new F(`ApiKeyInboundPolicy '${n}' - unexpected response from Key Service. Status: ${g.status}`)}let b=await g.json(),h={isValid:!0,typeId:Xv,user:{apiKeyId:b.id,sub:b.name,data:b.metadata}};return t.user=h.user,d.put(u,h,o.cacheTtlSeconds),t}s(vf,"ApiKeyInboundPolicy");async function N_(t){let e=new TextEncoder().encode(t),r=await crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(r)).map(i=>i.toString(16).padStart(2,"0")).join("")}s(N_,"hashValue");var L_=vf;import{createRemoteJWKSet as D_,jwtVerify as ex}from"jose";import{createLocalJWKSet as M_}from"jose";var xf=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{s(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 Rf&&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",P.instance.systemUserAgent),this.options.headers=Object.fromEntries(e.entries())),this.pendingFetch||=this.fetchJwks(this.url,this.timeoutDuration,this.options).then(r=>{this.local=M_(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 i,a,c=!1;typeof AbortController=="function"&&(i=new AbortController,a=setTimeout(()=>{c=!0,i.abort()},r));let u=await z.fetch(e.href,{signal:i?i.signal:void 0,redirect:"manual",headers:n.headers}).catch(l=>{throw c?new Pf("JWKS fetch timed out"):l});if(a!==void 0&&clearTimeout(a),u.status!==200)throw new fn("Expected 200 OK from the JSON Web Key Set HTTP response");try{let l=await u.json();return this.cache.put(this.url.href,l,this.cacheMaxAge),l}catch{throw new fn("Failed to parse the JSON Web Key Set HTTP response as JSON")}}};function Yv(t,e,r){let n=new xf(t,e,r);return async(o,i)=>n.getKey(o,i)}s(Yv,"createRemoteJWKSet");var fn=class extends F{static{s(this,"JWKSError")}},Rf=class extends fn{static{s(this,"JWKSNoMatchingKey")}},Pf=class extends fn{static{s(this,"JWKSTimeout")}};var ha={},U_=s((t,e)=>async(r,n)=>{if(!n.jwkUrl||typeof n.jwkUrl!="string")throw new w("Invalid State - jwkUrl not set");if(!ha[n.jwkUrl]){let i=!1;if("useExperimentalInMemoryCache"in n&&typeof n.useExperimentalInMemoryCache=="boolean"&&(i=n.useExperimentalInMemoryCache),i){let a=await xe(t,void 0,n),c=new be(a,e);ha[n.jwkUrl]=Yv(new URL(n.jwkUrl),c,n.headers?{headers:n.headers}:void 0)}else ha[n.jwkUrl]=D_(new URL(n.jwkUrl),n.headers?{headers:n.headers}:void 0)}let{payload:o}=await ex(r,ha[n.jwkUrl],{issuer:n.issuer,audience:n.audience});return o},"createJwkVerifier"),z_=s(async(t,e)=>{let r;if(e.secret===void 0)throw new w("secretVerifier requires secret to be defined");if(typeof e.secret=="string"){let i=new TextEncoder().encode(e.secret);r=new Uint8Array(i)}else r=e.secret;let{payload:n}=await ex(t,r,{issuer:e.issuer,audience:e.audience});return n},"secretVerifier");function j_(t){let e=we.instance,n=`/.well-known/oauth-protected-resource${t.pathname}`;return bt.some(a=>a instanceof Go)?!0:e.routeData.routes.some(a=>{let c=a.pathPattern||a.path;try{return new sa({pathname:c}).test({pathname:n})}catch{return!1}})}s(j_,"ensureOAuthResourceMetadataRouteExists");var Je=s(async(t,e,r,n)=>{R("policy.inbound.open-id-jwt-auth");let o=r.authHeader??"Authorization",i=t.headers.get(o),a="bearer ",c=s(f=>D.unauthorized(t,e,{detail:f}),"unauthorizedResponse");if(!r.jwkUrl&&!r.secret)throw new w(`OpenIdJwtInboundPolicy policy '${n}': One of 'jwkUrl' or 'secret' options are required.`);if(r.jwkUrl&&r.secret)throw new w(`OpenIdJwtInboundPolicy policy '${n}': Only one of 'jwkUrl' and 'secret' options should be provided.`);let u=r.jwkUrl?U_(n,e):z_,d=await s(async()=>{if(!i){let g=new URL(t.url);if(r.oAuthResourceMetadataEnabled&&j_(g)){let b=new URL(`/.well-known/oauth-protected-resource${g.pathname}`,g.origin);return D.unauthorized(t,e,{detail:"Bearer token required"},{"WWW-Authenticate":`resource_metadata=${b.toString()}`})}return c("No authorization header")}if(i.toLowerCase().indexOf(a)!==0)return c("Invalid bearer token format for authorization header");let f=i.substring(a.length);if(!f||f.length===0)return c("No bearer token on authorization header");try{return await u(f,r)}catch(g){let b=new URL(t.url);return"code"in g&&g.code==="ERR_JWT_EXPIRED"?e.log.warn(`Expired token used on url: ${b.pathname} `,g):e.log.warn(`Invalid token on: ${t.method} ${b.pathname}`,g),c("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):c(`Token is not valid, no '${p}' property found.`)},"OpenIdJwtInboundPolicy");var Z_=s(async(t,e,r,n)=>(R("policy.inbound.auth0-jwt-auth"),Je(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 tx=new Map;function q_(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 i=t.substring(o,r);for(e.push(i),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}s(q_,"parsePropertyPath");function ya(t,e){let r="$authzen-prop(";if(!t.startsWith(r)||!t.endsWith(")"))return t;let n=t.slice(r.length,-1),o=tx.get(n);o||(o=q_(n),tx.set(n,o));let i=e;for(let a of o){if(i==null)return;typeof i.get=="function"?i=i.get(a):i=i[a]}return i}s(ya,"evaluateAuthzenProp");var rx=Symbol("AUTHZEN_CONTEXT_DATA_52a5cf22-d922-4673-9815-6dc3d49071d9"),If=class t extends Re{static{s(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 w(`${this.policyType} '${this.policyName}' - subject.type is required.`);if(e.subject&&!e.subject.id)throw new w(`${this.policyType} '${this.policyName}' - subject.id is required.`);if(e.resource&&!e.resource.type)throw new w(`${this.policyType} '${this.policyName}' - resource.type is required.`);if(e.resource&&!e.resource.id)throw new w(`${this.policyType} '${this.policyName}' - resource.id is required.`);if(e.action&&!e.action.name)throw new w(`${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 w(`${this.policyType} '${this.policyName}' - authorizerUrl '${this.#e}' is not valid
|
|
282
282
|
${n}`)}}async handler(e,r){let n=this.options.throwOnError!==!1;try{await this.#o(r);let o=this.options.debug===!0,i={subject:Object.assign({},this.options.subject),resource:Object.assign({},this.options.resource),action:Object.assign({},this.options.action)},a={request:e,context:r};i.action?.name!==void 0&&(i.action.name=ya(i.action.name,a)),i.subject?.id!==void 0&&(i.subject.id=ya(i.subject.id,a)),i.resource?.id!==void 0&&(i.resource.id=ya(i.resource.id,a)),o&&r.log.debug(`${this.policyType} '${this.policyName}' - Evaluated payload from options`,i);let c=t.getAuthorizationPayload(r);c&&Object.assign(i,c),o&&r.log.debug(`${this.policyType} '${this.policyName}' - Using context payload to override working payload`,{contextPayload:c,final:i}),this.#n(r,!i.subject?.type||!i.subject?.id,"Missing required subject type or id"),this.#n(r,!i.resource?.type||!i.resource?.id,"Missing required resource type or id"),this.#n(r,!i.action,"Missing required action");let u={"content-type":"application/json"};this.options.authorizerAuthorizationHeader&&(u.authorization=this.options.authorizerAuthorizationHeader);let l=await z.fetch(this.#e,{method:"POST",body:JSON.stringify(i),headers:u});if(!l.ok){let p=`${this.policyType} '${this.policyName}' - Unexpected response from PDP: ${l.status} - ${l.statusText}:
|
|
283
283
|
${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 w(o);e.log.warn(o)}}async#r(e,r,n){return D.forbidden(e,r,{detail:n})}async#o(e){if(!this.#t){let r=await xe(this.policyName,void 0,this.options);this.#t=new be(r,e)}}static setAuthorizationPayload(e,r){pe.set(e,rx,r)}static getAuthorizationPayload(e){return pe.get(e,rx)}};var ba=class{constructor(e){this.options=e;this.authHeader=`Basic ${btoa(`${e.pdpUsername}:${e.pdpPassword}`)}`,this.authorizationUrl=new URL("/authorize",e.pdpUrl).toString()}static{s(this,"PdpService")}authHeader;authorizationUrl;async makePdpRequest(e){let r=await z.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 Sf=class t extends Re{static{s(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),R("policy.inbound.axiomatics-authz"),ae(e,r).required("pdpUrl","string").required("pdpUsername","string").required("pdpPassword","string"),this.pdpService=new ba(e)}async handler(e,r){let n=s(a=>this.options.allowUnauthorizedRequests?e:D.forbidden(e,r,{detail:a}),"forbiddenResponse"),o=new URL(e.url),i=t.#e?.get(r)??{Request:{}};if(this.options.includeDefaultSubjectAttributes!==!1&&e.user){let a=[{AttributeId:"request.user.sub",Value:e.user.sub}];this.addAttributesToCategory(i,"AccessSubject",a)}if(this.options.includeDefaultActionAttributes!==!1){let a=[{AttributeId:"request.method",Value:e.method}];this.addAttributesToCategory(i,"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(([c,u])=>{a.push({AttributeId:`request.params.${c}`,Value:u})}),o.searchParams.forEach((c,u)=>{a.push({AttributeId:`request.query.${u}`,Value:c})}),this.addAttributesToCategory(i,"Resource",a)}this.populateOptionAttributes({optionName:"resourceAttributes",authzRequestCategory:"Resource",authzRequest:i,context:r}),this.populateOptionAttributes({optionName:"actionAttributes",authzRequestCategory:"Action",authzRequest:i,context:r}),this.populateOptionAttributes({optionName:"accessSubjectAttributes",authzRequestCategory:"AccessSubject",authzRequest:i,context:r});try{r.log.debug("PDP Request",i);let a=await this.pdpService.makePdpRequest(i);return r.log.debug("PDP Response",a),a.Response.every(c=>c.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),D.internalServerError(e,r)}}populateOptionAttributes({optionName:e,authzRequestCategory:r,authzRequest:n,context:o}){let i=this.options[e];if(i){let a=[];i.forEach(c=>{c.value?a.push({AttributeId:c.attributeId,Value:c.value}):o.log.warn(`${this.policyType} '${this.policyName}' - The attribute ${c.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 F_=s(async(t,e,r)=>{R("policy.inbound.basic-auth");let n=t.headers.get("Authorization"),o="basic ",i=s(l=>D.unauthorized(t,e,{detail:l}),"unauthorizedResponse"),c=await s(async()=>{if(!n)return await i("No Authorization header");if(n.toLowerCase().indexOf(o)!==0)return await i("Invalid Basic token format for Authorization header");let l=n.substring(o.length);if(!l||l.length===0)return await i("No username:password provided");let d=atob(l).normalize(),p=d.indexOf(":");if(p===-1||/[\0-\x1F\x7F]/.test(d))return await i("Invalid basic token value - see https://tools.ietf.org/html/rfc5234#appendix-B.1");let m=d.substring(0,p),f=d.substring(p+1),g=r.accounts.find(b=>b.username===m&&b.password===f);return g||await i("Invalid username or password")},"getAccountOrRejectedResponse")();if(c instanceof Response)return r.allowUnauthenticatedRequests?t:c;let u=c.username;return t.user={sub:u,data:c.data},t},"BasicAuthInboundPolicy");function wa(t){return{second:t.getSeconds(),minute:t.getMinutes(),hour:t.getHours(),day:t.getDate(),month:t.getMonth(),weekday:t.getDay(),year:t.getFullYear()}}s(wa,"extractDateElements");function nx(t,e){return new Date(t,e+1,0).getDate()}s(nx,"getDaysInMonth");function kf(t,e){return t<=e?e-t:6-t+e+1}s(kf,"getDaysBetweenWeekdays");var va=class{static{s(this,"Cron")}seconds;minutes;hours;days;months;weekdays;reversed;constructor({seconds:e,minutes:r,hours:n,days:o,months:i,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(!i||i.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((u,l)=>u-l),this.minutes=Array.from(r).sort((u,l)=>u-l),this.hours=Array.from(n).sort((u,l)=>u-l),this.days=Array.from(o).sort((u,l)=>u-l),this.months=Array.from(i).sort((u,l)=>u-l),this.weekdays=Array.from(a).sort((u,l)=>u-l);let c=s((u,l,d)=>{if(l.some(p=>typeof p!="number"||p%1!==0||p<d.min||p>d.max))throw new Error(`${u} must only consist of integers which are within the range of ${d.min} and ${d.max}`)},"validateData");c("seconds",this.seconds,{min:0,max:59}),c("minutes",this.minutes,{min:0,max:59}),c("hours",this.hours,{min:0,max:23}),c("days",this.days,{min:1,max:31}),c("months",this.months,{min:0,max:11}),c("weekdays",this.weekdays,{min:0,max:6}),this.reversed={seconds:this.seconds.map(u=>u).reverse(),minutes:this.minutes.map(u=>u).reverse(),hours:this.hours.map(u=>u).reverse(),days:this.days.map(u=>u).reverse(),months:this.months.map(u=>u).reverse(),weekdays:this.weekdays.map(u=>u).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 i=this.findAllowedSecond(e,r.second);if(i!==void 0)return{hour:n,minute:o,second:i};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 i=nx(r,n),a=this.days.length!==31,c=this.weekdays.length!==7;if(!a&&!c)return o>i?e==="next"?void 0:i:o;let u;a&&(u=e==="next"?this.days.find(d=>d>=o):this.reversed.days.find(d=>d<=o),u!==void 0&&u>i&&(u=void 0));let l;if(c){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"?kf(d,p):kf(p,d);l=e==="next"?o+m:o-m,(l>i||l<1)&&(l=void 0)}}if(u!==void 0&&l!==void 0)return e==="next"?Math.min(u,l):Math.max(u,l);if(u!==void 0)return u;if(l!==void 0)return l}getNextDate(e=new Date){let r=wa(e),n=r.year,o=this.months.findIndex(a=>a>=r.month);o===-1&&(o=0,n++);let i=this.months.length*5;for(let a=0;a<i;a++){let c=n+Math.floor((o+a)/this.months.length),u=this.months[(o+a)%this.months.length],l=c===r.year&&u===r.month,d=this.findAllowedDayInMonth("next",c,u,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(c,u,d,m.hour,m.minute,m.second);d=this.findAllowedDayInMonth("next",c,u,d+1),p=!1}if(d!==void 0&&!p)return new Date(c,u,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 i=0;i<e;i++)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=wa(e),n=r.year,o=this.reversed.months.findIndex(a=>a<=r.month);o===-1&&(o=0,n--);let i=this.reversed.months.length*5;for(let a=0;a<i;a++){let c=n-Math.floor((o+a)/this.reversed.months.length),u=this.reversed.months[(o+a)%this.reversed.months.length],l=c===r.year&&u===r.month,d=this.findAllowedDayInMonth("prev",c,u,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(c,u,d,m.hour,m.minute,m.second);d>1&&(d=this.findAllowedDayInMonth("prev",c,u,d-1),p=!1)}if(d!==void 0&&!p)return new Date(c,u,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 i=0;i<e;i++)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:i,month:a,weekday:c}=wa(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(i)!==-1||this.weekdays.indexOf(c)!==-1:this.days.indexOf(i)!==-1&&this.weekdays.indexOf(c)!==-1}};var H_={min:0,max:59},G_={min:0,max:59},B_={min:0,max:23},V_={min:1,max:31},J_={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"}},W_={min:0,max:7,aliases:{mon:"1",tue:"2",wed:"3",thu:"4",fri:"5",sat:"6",sun:"7"}},K_={"@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 Ar(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=>{Ar(d,e).forEach(m=>r.add(m))}),r;let o=s(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"),i=/^((([0-9a-zA-Z]+)-([0-9a-zA-Z]+))|\*)(\/([0-9]+))?$/.exec(t);if(i===null)return r.add(o(t)),r;let a=i[1]==="*"?e.min:o(i[3]),c=i[1]==="*"?e.max:o(i[4]);if(a>c)throw new Error(`Failed to parse ${t}: Invalid range (start: ${a}, end: ${c}).`);let u=i[6],l=1;if(u!==void 0){if(l=parseInt(u,10),Number.isNaN(l))throw new Error(`Failed to parse step: ${u} is NaN.`);if(l<1)throw new Error(`Failed to parse step: Expected ${u} to be greater than 0.`)}for(let d=a;d<=c;d=d+l)r.add(d);return r}s(Ar,"parseElement");function Tf(t){if(typeof t!="string")throw new TypeError("Invalid cron expression: must be of type string.");t=K_[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],i=e.length===6?e[3]:e[2],a=e.length===6?e[4]:e[3],c=e.length===6?e[5]:e[4];return new va({seconds:Ar(r,H_),minutes:Ar(n,G_),hours:Ar(o,B_),days:Ar(i,V_),months:new Set(Array.from(Ar(a,J_)).map(u=>u-1)),weekdays:new Set(Array.from(Ar(c,W_)).map(u=>u%7))})}s(Tf,"parseCronExpression");var Ef=class extends Re{static{s(this,"BrownoutInboundPolicy")}crons;constructor(e,r){if(super(e,r),R("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 w(`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=[Tf(this.options.cronSchedule)]:this.crons=this.options.cronSchedule.map(n=>Tf(n))}async handler(e,r){let n=new Date;if(n.setSeconds(0),n.setMilliseconds(0),this.crons.some(i=>i.matchDate(n))){let i=D.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 D.format(i,e,r)}return e}};var Q_=["cdn-cache-control","cloudflare-cdn-cache-control","surrogate-control","cache-tag","expires"];async function X_(t){let e=new TextEncoder().encode(t),r=await crypto.subtle.digest("SHA-256",e);return Array.from(new Uint8Array(r)).map(i=>i.toString(16).padStart(2,"0")).join("")}s(X_,"digestMessage");var Y_=s(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 X_(JSON.stringify(n)),i=new URL(t.url),a=new URLSearchParams(i.searchParams);a.set("_z-hdr-dgst",o);let c=e.cacheHttpMethods?.includes(t.method.toUpperCase())&&t.method.toUpperCase()!=="GET";c&&a.set("_z-original-method",t.method);let u=`${i.origin}${i.pathname}?${a}`;return new Request(u,{method:c?"GET":t.method})},"createCacheKeyRequest");async function eO(t,e,r,n){R("policy.inbound.caching");let o=await xe(n,r.cacheId,r),i=await caches.open(o),a=r?.cacheHttpMethods?.map(l=>l.toUpperCase())??["GET"],c=await Y_(t,r),u=await i.match(c);return u||(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,f=new Response(p.body,p);Q_.forEach(g=>f.headers.delete(g)),f.headers.set("cache-control",`s-maxage=${m}`),e.waitUntil(i.put(c,f))}catch(d){e.log.error(`Error in caching-inbound-policy '${n}': "${d.message}"`,d)}}),t)}s(eO,"CachingInboundPolicy");var tO=s(async(t,e,r,n)=>{if(R("policy.inbound.change-method"),!r.method)throw new w(`ChangeMethodInboundPolicy '${n}' options.method must be valid HttpMethod`);return new de(t,{method:r.method})},"ChangeMethodInboundPolicy");var rO=s(async(t,e,r)=>{R("policy.inbound.clear-headers");let n=[...r.exclude??[]],o=new Headers;return n.forEach(a=>{let c=t.headers.get(a);c&&o.set(a,c)}),new de(t,{headers:o})},"ClearHeadersInboundPolicy");var nO=s(async(t,e,r,n)=>{R("policy.outbound.clear-headers");let o=[...n.exclude??[]],i=new Headers;return o.forEach(c=>{let u=t.headers.get(c);u&&i.set(c,u)}),new Response(t.body,{headers:i,status:t.status,statusText:t.statusText})},"ClearHeadersOutboundPolicy");var oO=s(async(t,e,r,n)=>{R("policy.inbound.clerk-jwt-auth");let o=new URL(r.frontendApiUrl.startsWith("https://")||r.frontendApiUrl.startsWith("http://")?r.frontendApiUrl:`https://${r.frontendApiUrl}`),i=new URL(o);return i.pathname="/.well-known/jwks.json",Je(t,e,{issuer:o.href.slice(0,-1),jwkUrl:i.toString(),allowUnauthenticatedRequests:r.allowUnauthenticatedRequests,oAuthResourceMetadataEnabled:r.oAuthResourceMetadataEnabled},n)},"ClerkJwtInboundPolicy");var iO=s(async(t,e,r,n)=>{if(R("policy.inbound.cognito-jwt-auth"),!r.userPoolId)throw new w("userPoolId must be set in the options for CognitoJwtInboundPolicy");if(!r.region)throw new w("region must be set in the options for CognitoJwtInboundPolicy");return Je(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 Fe=[];for(let t=0;t<256;++t)Fe.push((t+256).toString(16).slice(1));function ox(t,e=0){return(Fe[t[e+0]]+Fe[t[e+1]]+Fe[t[e+2]]+Fe[t[e+3]]+"-"+Fe[t[e+4]]+Fe[t[e+5]]+"-"+Fe[t[e+6]]+Fe[t[e+7]]+"-"+Fe[t[e+8]]+Fe[t[e+9]]+"-"+Fe[t[e+10]]+Fe[t[e+11]]+Fe[t[e+12]]+Fe[t[e+13]]+Fe[t[e+14]]+Fe[t[e+15]]).toLowerCase()}s(ox,"unsafeStringify");var Cf,sO=new Uint8Array(16);function xa(){if(!Cf){if(typeof crypto>"u"||!crypto.getRandomValues)throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");Cf=crypto.getRandomValues.bind(crypto)}return Cf(sO)}s(xa,"rng");var _f={};function aO(t,e,r){let n;if(t)n=ix(t.random??t.rng?.()??xa(),t.msecs,t.seq,e,r);else{let o=Date.now(),i=xa();cO(_f,o,i),n=ix(i,_f.msecs,_f.seq,e,r)}return e??ox(n)}s(aO,"v7");function cO(t,e,r){return t.msecs??=-1/0,t.seq??=0,e>t.msecs?(t.seq=r[6]<<23|r[7]<<16|r[8]<<8|r[9],t.msecs=e):(t.seq=t.seq+1|0,t.seq===0&&t.msecs++),t}s(cO,"updateV7State");function ix(t,e,r,n,o=0){if(t.length<16)throw new Error("Random bytes length must be >= 16");if(!n)n=new Uint8Array(16),o=0;else if(o<0||o+16>n.length)throw new RangeError(`UUID byte range ${o}:${o+15} is out of buffer bounds`);return e??=Date.now(),r??=t[6]*127<<24|t[7]<<16|t[8]<<8|t[9],n[o++]=e/1099511627776&255,n[o++]=e/4294967296&255,n[o++]=e/16777216&255,n[o++]=e/65536&255,n[o++]=e/256&255,n[o++]=e&255,n[o++]=112|r>>>28&15,n[o++]=r>>>20&255,n[o++]=128|r>>>14&63,n[o++]=r>>>6&255,n[o++]=r<<2&255|t[10]&3,n[o++]=t[11],n[o++]=t[12],n[o++]=t[13],n[o++]=t[14],n[o++]=t[15],n}s(ix,"v7Bytes");var Ra=aO;function sx(t,e,r,n){return Jn(t,async o=>{e.traceId&&await n(e.traceId,e.input,o,e.startTime,t,r)})}s(sx,"createOpikStreamingAccumulator");var gn=Ne("zuplo:policies:CometOpikTracingPolicy"),cx=Symbol("comet-opik-tracing");function uO(t,e){pe.set(t,cx,e)}s(uO,"setTracingContext");function lO(t){return pe.get(t,cx)}s(lO,"getTracingContext");async function dO(t,e,r){let n=r.baseUrl||"https://www.comet.com/opik/api",o=r.workspace,i=new Date().toISOString(),a=Ra(),c={id:a,project_name:r.projectName,name:"AI Gateway Request",start_time:i,input:t,metadata:{request_id:e.requestId,route:e.route.path},tags:["zuplo-ai-gateway"]};try{let u={"Content-Type":"application/json","Comet-Workspace":o};r.apiKey&&(u.authorization=r.apiKey);let l=await z.fetch(`${n}/v1/private/traces/batch`,{method:"POST",headers:u,body:JSON.stringify({traces:[c]})});if(!l.ok){let d=await l.text();gn("Failed to create Opik trace:",l.status,d);return}return gn("Created Opik trace with ID:",a),a}catch(u){gn("Error creating Opik trace:",u);return}}s(dO,"createTrace");async function ax(t,e,r,n,o,i){let a=i.baseUrl||"https://www.comet.com/opik/api",c=i.workspace,u=new Date().toISOString(),l=Ra(),d,p=r;if(p?.usage&&typeof p.usage=="object"){let g=p.usage;d={prompt_tokens:typeof g.prompt_tokens=="number"?g.prompt_tokens:void 0,completion_tokens:typeof g.completion_tokens=="number"?g.completion_tokens:void 0,total_tokens:typeof g.total_tokens=="number"?g.total_tokens:void 0}}let m="";p?.choices&&Array.isArray(p.choices)&&(m=p.choices.map(g=>g.message?.content).filter(g=>typeof g=="string").join(" "));let f={id:l,trace_id:t,project_name:i.projectName,name:"LLM API Call",type:"llm",start_time:n,end_time:u,model:e?.model,provider:"ai-gateway",usage:d,input:{messages:e?.messages||[]},output:{content:m},metadata:{request_id:o.requestId,temperature:e?.temperature,max_tokens:e?.max_tokens},tags:["llm-call","ai-gateway"]};try{let g={"Content-Type":"application/json","Comet-Workspace":c};i.apiKey&&(g.authorization=i.apiKey);let b={spans:[f]},h=await z.fetch(`${a}/v1/private/spans/batch`,{method:"POST",headers:g,body:JSON.stringify(b)});if(h.ok)gn("Created Opik span for trace:",t);else{let x=await h.text();gn("Failed to create Opik span:",h.status,x)}}catch(g){gn("Error creating Opik span:",g)}}s(ax,"createSpan");async function pO(t,e,r,n){R("policy.comet-opik-tracing");let o=t.user,i=o?.configuration?.policies?.["comet-opik-tracing"];if(!i?.enabled)return t;let a={apiKey:i.apiKey,projectName:i.projectName,workspace:i.workspace,baseUrl:i.baseUrl},u=o?.configuration?.models?.completions?.[0]?.model,l,d,p=!1;try{l=await t.clone().json(),p=l?.stream===!0,l?.messages&&(d={messages:l.messages,model:u||l.model,temperature:l.temperature,max_tokens:l.max_tokens})}catch{e.log.error("Could not parse request body for Opik tracing")}if(d){let m=new Date().toISOString(),f=await dO(d,e,a);f&&(uO(e,{traceId:f,startTime:m,input:d}),e.addResponseSendingFinalHook(async b=>{let h=lO(e);if(h?.traceId)if(p&&b.body){let x=b.clone(),v=sx(e,h,a,ax);x.body&&e.waitUntil(x.body.pipeThrough(v).pipeTo(new WritableStream({write(){},close(){},abort(T){e.log.error("Opik streaming accumulation aborted",{error:T})}})).catch(T=>{e.log.error("Error in Opik streaming accumulation",{error:T})}))}else{let x;try{x=await b.clone().json()}catch{e.log.error("Could not parse response body for Opik tracing")}e.waitUntil(ax(h.traceId,h.input,x,h.startTime,e,a))}}))}return t}s(pO,"CometOpikTracingInboundPolicy");var Pa=class extends Error{static{s(this,"ValidationError")}},Of=class extends Pa{static{s(this,"ArgumentUndefinedError")}constructor(e){super(`The argument '${e}' is undefined.`)}},$f=class extends Pa{static{s(this,"ArgumentTypeError")}constructor(e,r){super(`The argument '${e}' must be of type '${r}'.`)}};function mO(t,e){if(Vg(t))throw new Of(e)}s(mO,"throwIfUndefinedOrNull");function ux(t,e){if(mO(t,e),!tt(t))throw new $f(e,"string")}s(ux,"throwIfNotString");var fO=250,Af=class{static{s(this,"InMemoryRateLimitClient")}keyValueStore;constructor(){this.keyValueStore=new Map}getCountAndUpdateExpiry(e,r){let o=Math.floor(r*60),i=Date.now()+o*1e3,a=this.keyValueStore.get(e);a?Date.now()>a.expiresAt?this.keyValueStore.set(e,{value:1,expiresAt:i}):this.keyValueStore.set(e,{value:a.value+1,expiresAt:a.expiresAt}):this.keyValueStore.set(e,{value:1,expiresAt:i});let c=this.keyValueStore.get(e);return Promise.resolve({count:c.value,ttlSeconds:Math.round((c.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.")}},Nf=class{constructor(e,r=P.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{s(this,"RemoteRateLimitClient")}static instance;async fetch({url:e,body:r,method:n,requestId:o}){ux(e,"url");let i=new AbortController;setTimeout(()=>{i.abort()},this.timeoutMs);let a,c=new Headers({"content-type":"application/json"});je(c,o);try{a=await z.fetch(`${this.clientUrl}${e}`,{method:n,body:r,signal:i.signal,headers:c})}catch(l){if(l instanceof Error&&l.name==="AbortError"){let d=this.timeoutMs;throw this.timeoutMs+=fO,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 le("Rate limiting client timed out",{cause:l})}throw new le("Could not fetch rate limiting client",{cause:l})}let u=a.headers.get("Content-Type")?.includes("application/json")?await a.json():await a.text();if(a.ok)return u;throw a.status===401?new le("Rate limiting service failed with 401: Unauthorized"):new le(`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 br(e);return await this.fetch({url:`/quota/${n}`,method:"GET",requestId:r})}async setQuota(e,r,n){let o=await br(e);await this.fetch({url:`/quota/${o}`,method:"POST",body:JSON.stringify(r),requestId:n})}},hn;function mr(t,e,r){let{redisURL:n,authApiJWT:o}=P.instance;if(hn)return hn;if(!o)return e.info("Using in-memory rate limit client for local development."),hn=new Af,hn;if(!tt(n))throw new le(`RateLimitClient used in policy '${t}' - rate limit service not configured`);if(!tt(o))throw new le(`RateLimitClient used in policy '${t}' - rate limit service not configured`);return hn=new Nf(n,r?.timeoutMs,e),hn}s(mr,"getRateLimitClient");var gO=s(t=>ut(t)??"127.0.0.1","getRealIP");function yn(t,e){return{function:wO(e,"RateLimitInboundPolicy",t),user:yO,ip:hO,all:bO}[e.rateLimitBy??"ip"]}s(yn,"getRateLimitByFunctions");var hO=s(async t=>({key:`ip-${gO(t)}`}),"getIP"),yO=s(async t=>({key:`user-${t.user?.sub??"anonymous"}`}),"getUser"),bO=s(async()=>({key:"all-2d77ce9d-9a3c-4206-9ab2-668cfd271095"}),"getAll");function wO(t,e,r){let n;if(t.rateLimitBy==="function"){if(!t.identifier)throw new w(`${e} '${r}' - If rateLimitBy set to 'function' options.identifier must be specified`);if(!t.identifier.module||typeof t.identifier.module!="object")throw new w(`${e} '${r}' - If rateLimitBy set to 'function' options.identifier.module must be specified`);if(!t.identifier.export)throw new w(`${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 w(`${e} '${r}' - Custom rate limit function must be a valid function`)}return s(async(i,a,c)=>{let u=await n(i,a,c);if(!u||typeof u!="object"){let l=`${e} '${c}' - Custom rate limit function must return a valid object.`;throw a.log.error(l),new F(l)}if(!("key"in u)){let l=`${e} '${c}' - Custom rate limit function must return a valid key property.`;throw a.log.error(l,u),new F(l)}if(typeof u.key!="string"){let l=`${e} '${c}' - Custom rate limit function must return a valid key property of type string. Received type '${typeof u.key}'`;throw a.log.error(l),new F(l)}return u},"outerFunction")}s(wO,"wrapUserFunction");var bn="Retry-After";var lx=Ne("zuplo:policies:ComplexRateLimitInboundPolicy"),Lf=Symbol("complex-rate-limit-counters"),Mf=class t extends Re{static{s(this,"ComplexRateLimitInboundPolicy")}static setIncrements(e,r){let n=pe.get(e,Lf)??{};Object.assign(n,r),pe.set(e,Lf,n)}static getIncrements(e){return pe.get(e,Lf)??{}}constructor(e,r){super(e,r),R("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 w(`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=K.getLogger(r),i=mr(this.policyName,o),a=s((u,l)=>{if(this.options.throwOnFailure)throw new le(u,{cause:l});o.error(u,l)},"throwOrLog"),c=s((u,l)=>{let d={};return(!u||u==="retry-after")&&(d[bn]=l.toString()),D.tooManyRequests(e,r,void 0,d)},"rateLimited");try{let l=await yn(this.policyName,this.options)(e,r,this.policyName),d=P.instance.isTestMode||P.instance.isWorkingCopy?P.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 h=t.getIncrements(r);lx(`ComplexRateLimitInboundPolicy '${this.policyName}' - increments ${JSON.stringify(h)}`);let x=Object.entries(p).map(([T])=>({key:`complex-rate-limit${d}/${this.policyName}/${l.key}/${T}`,ttlSeconds:m,increment:h[T]??0})),v=i.multiIncrement(x,r.requestId);r.waitUntil(v),await v}catch(h){a(h.message,h)}});let f=Object.entries(p).map(([h,x])=>({key:`complex-rate-limit${d}/${this.policyName}/${l.key}/${h}`,ttlSeconds:m,limit:x})),g=await i.multiCount(f,r.requestId);return vO(g,f).length>0?c(this.options.headerMode??"retry-after",m):e}catch(u){return a(u.message,u),e}finally{let u=Date.now()-n;lx(`ComplexRateLimitInboundPolicy '${this.policyName}' - latency ${u}ms`)}}};function vO(t,e){let r=[];for(let n of t){let o=e.find(i=>i.key===n.key)?.limit||0;n.count>=o&&r.push(n)}return r}s(vO,"findOverLimits");var xO=s(async(t,e,r,n)=>{if(R("policy.inbound.composite"),!r.policies||r.policies.length===0)throw new w(`CompositeInboundPolicy '${n}' must have valid policies defined`);let o=we.instance,i=Mn(r.policies,o?.routeData.policies);return ac(i)(t,e)},"CompositeInboundPolicy");var RO=s(async(t,e,r,n,o)=>{if(R("policy.outbound.composite"),!n.policies||n.policies.length===0)throw new w(`CompositeOutboundPolicy '${o}' must have valid policies defined`);let i=we.instance,a=Dn(n.policies,i?.routeData.policies);return cc(a)(t,e,r)},"CompositeOutboundPolicy");var PO=s(async(t,e,r,n)=>{R("policy.inbound.curity-phantom-token-auth");let o=t.headers.get("Authorization");if(!o)return D.unauthorized(t,e,{detail:"No authorization header"});let i=IO(o);if(!i)return D.unauthorized(t,e,{detail:"Failed to parse token from Authorization header"});let a=await xe(n,void 0,r),c=new be(a,e),u=await c.get(i);if(!u){let l=await z.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=${i}&token_type_hint=access_token`}),d=await l.text();if(l.status===200)u=d,c.put(i,u,r.cacheDurationSeconds??600);else return l.status>=500?(e.log.error(`Error introspecting token - ${l.status}: '${d}'`),D.internalServerError(t,e,{detail:"Problem encountered authorizing the HTTP request"})):D.unauthorized(t,e)}return t.headers.set("Authorization",`Bearer ${u}`),t},"CurityPhantomTokenInboundPolicy");function IO(t){return t.split(" ")[0]==="Bearer"?t.split(" ")[1]:null}s(IO,"getToken");var SO=s(async(t,e,r,n)=>(R("policy.inbound.firebase-jwt-auth"),ae(r,n).required("projectId","string").optional("allowUnauthenticatedRequests","boolean"),Je(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 kO=s(async(t,e,r)=>{R("policy.inbound.form-data-to-json");let n="application/x-www-form-urlencoded",o="multipart/form-data",i=t.headers.get("content-type")?.toLowerCase();if(!i||![o,n].some(d=>i.startsWith(d)))return 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?.optionalHoneypotName&&a.get(r.optionalHoneypotName)!=="")return new Response("Bad Request",{status:400,statusText:"Bad Request"});let c={};for(let[d,p]of a)c[d]=p.toString();let u=new Headers(t.headers);return u.set("content-type","application/json"),u.delete("content-length"),new de(t,{body:JSON.stringify(c),headers:u})},"FormDataToJsonInboundPolicy");function dx(t,e,r,n){return Jn(t,async o=>{await n(e.input,o,e.traceStartTime,t,r)})}s(dx,"createGalileoStreamingAccumulator");var Df=Ne("zuplo:policies:GalileoTracingPolicy"),fx=Symbol("galileo-tracing");function TO(t,e){pe.set(t,fx,e)}s(TO,"setTracingContext");function EO(t){return pe.get(t,fx)}s(EO,"getTracingContext");function px(t){let e=new Date(t).getTime();return(Date.now()-e)*1e6}s(px,"getDurationNs");async function mx(t,e,r,n,o){let i=o.baseUrl||"https://api.galileo.ai",a=new Date().toISOString(),c,u=e;if(u?.usage&&typeof u.usage=="object"){let h=u.usage;c={num_input_tokens:typeof h.prompt_tokens=="number"?h.prompt_tokens:void 0,num_output_tokens:typeof h.completion_tokens=="number"?h.completion_tokens:void 0,num_total_tokens:typeof h.total_tokens=="number"?h.total_tokens:void 0,duration_ns:px(r)}}let l="",d;u?.choices&&Array.isArray(u.choices)&&(l=u.choices.map(h=>{let x=h,v=x.message;return x.finish_reason&&(d=String(x.finish_reason)),v?.content}).filter(h=>typeof h=="string").join(" "));let p=t?.messages?.map(h=>({role:h.role,content:h.content}))||[],m={type:"llm",input:p,output:{role:"assistant",content:l},name:"LLM API Call",model:t?.model||"unknown",temperature:t?.temperature,finish_reason:d,created_at:r,user_metadata:{request_id:n.requestId,route:n.route.path},tags:["llm-call","ai-gateway"],metrics:c},f={type:"workflow",input:p.map(h=>`${h.role}: ${h.content}`).join(`
|
|
284
284
|
`),output:l,name:"AI Gateway Workflow",created_at:r,user_metadata:{request_id:n.requestId},tags:["ai-gateway"],spans:[m]},g={type:"trace",input:p.find(h=>h.role==="user")?.content||"",output:l,name:"AI Gateway Request",created_at:r,user_metadata:{request_id:n.requestId,route:n.route.path},tags:["zuplo-ai-gateway"],metrics:{duration_ns:px(r)},spans:[f]},b={log_stream_id:o.logStreamId,traces:[g]};try{let h={"Content-Type":"application/json","Galileo-API-Key":o.apiKey},x=await z.fetch(`${i}/projects/${o.projectId}/traces`,{method:"POST",headers:h,body:JSON.stringify(b)});if(x.ok)Df("Successfully sent Galileo trace");else{let v=await x.text();n.log.error("Failed to send Galileo trace",{status:x.status,error:v}),Df("Failed to send Galileo trace:",x.status,v)}}catch(h){n.log.error(h,"Error sending Galileo trace"),Df("Error sending Galileo trace:",h)}}s(mx,"sendTrace");async function CO(t,e,r,n){R("policy.galileo-tracing");let o=t.user,i=o?.configuration?.policies?.["galileo-tracing"];if(!i?.enabled)return t;let a={apiKey:i.apiKey,projectId:i.projectId,logStreamId:i.logStreamId,baseUrl:i.baseUrl},u=o?.configuration?.models?.completions?.[0]?.model,l,d,p=!1;try{l=await t.clone().json(),p=l?.stream===!0,l?.messages&&(d={messages:l.messages,model:u||l.model,temperature:l.temperature,max_tokens:l.max_tokens})}catch{e.log.error("Could not parse request body for Galileo tracing")}if(d){let f={traceStartTime:new Date().toISOString(),input:d};TO(e,f),e.addResponseSendingFinalHook(async g=>{let b=EO(e);if(b)if(p&&g.body){let h=g.clone(),x=dx(e,b,a,mx);h.body&&e.waitUntil(h.body.pipeThrough(x).pipeTo(new WritableStream({write(){},close(){},abort(v){e.log.error("Galileo streaming accumulation aborted",{error:v})}})).catch(v=>{e.log.error("Error in Galileo streaming accumulation",{error:v})}))}else{let h;try{h=await g.clone().json()}catch{e.log.error("Could not parse response body for Galileo tracing")}e.waitUntil(mx(b.input,h,b.traceStartTime,e,a))}})}return t}s(CO,"GalileoTracingInboundPolicy");var wn="__unknown__",_O=s(async(t,e,r,n)=>{R("policy.inbound.geo-filter");let o={allow:{countries:xn(r.allow?.countries,"allow.countries",n),regionCodes:xn(r.allow?.regionCodes,"allow.regionCode",n),asns:xn(r.allow?.asns,"allow.asOrganization",n)},block:{countries:xn(r.block?.countries,"block.countries",n),regionCodes:xn(r.block?.regionCodes,"block.regionCode",n),asns:xn(r.block?.asns,"block.asOrganization",n)},ignoreUnknown:r.ignoreUnknown!==!1},i=e.incomingRequestProperties.country?.toLowerCase()??wn,a=e.incomingRequestProperties.regionCode?.toLowerCase()??wn,c=e.incomingRequestProperties.asn?.toString()??wn,u=o.ignoreUnknown&&i===wn,l=o.ignoreUnknown&&a===wn,d=o.ignoreUnknown&&c===wn,p=o.allow.countries,m=o.allow.regionCodes,f=o.allow.asns;if(p.length>0&&!p.includes(i)&&!u||m.length>0&&!m.includes(a)&&!l||f.length>0&&!f.includes(c)&&!d)return vn(t,e,n,i,a,c);let g=o.block.countries,b=o.block.regionCodes,h=o.block.asns;return g.length>0&&g.includes(i)&&!u||b.length>0&&b.includes(a)&&!l||h.length>0&&h.includes(c)&&!d?vn(t,e,n,i,a,c):t},"GeoFilterInboundPolicy");function vn(t,e,r,n,o,i){return e.log.debug(`Request blocked by GeoFilterInboundPolicy '${r}' (country: '${n}', regionCode: '${o}', asn: '${i}')`),D.forbidden(t,e,{geographicContext:{country:n,regionCode:o,asn:i}})}s(vn,"blockedResponse");function xn(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 w(`Invalid '${e}' for GeoFilterInboundPolicy '${r}': '${t}', must be a string or string[]`)}s(xn,"toLowerStringArray");var OO=s(async(t,e,r)=>{R("policy.inbound.jwt-scope-validation");let n=t.user?.data?.scope?.split(" ")||[];if(!s((i,a)=>a.every(c=>i.includes(c)),"scopeChecker")(n,r.scopes)){let i={code:"UNAUTHORIZED",help_url:"https://zup.fail/UNAUTHORIZED",message:`JWT must have all the following scopes: ${r.scopes}`};return new Response(JSON.stringify(i),{status:401,statusText:"Unauthorized",headers:{"content-type":"application/json"}})}return t},"JWTScopeValidationInboundPolicy");var $O=s(async(t,e,r,n)=>{R("policy.inbound.mock-api");let o=e.route.raw().responses;if(!o)return Uf(n,t,e,"No responses defined in the OpenAPI document. Add some responses with examples to use this policy.");let i=Object.keys(o),a=[];if(i.length===0)return Uf(n,t,e,"No response object defined under responses in the OpenAPI document. Add some response objects with examples to use this policy.");if(i.forEach(c=>{o[c].content&&Object.keys(o[c].content).forEach(l=>{let d=o[c].content[l],p=d.examples,m=d.example;p?Object.keys(p).forEach(g=>{a.push({responseName:c,contentName:l,exampleName:g,exampleValue:p[g]})}):m!==void 0&&a.push({responseName:c,contentName:l,exampleName:"example",exampleValue:m})})}),a=a.filter(c=>!(r.responsePrefixFilter&&!c.responseName.startsWith(r.responsePrefixFilter)||r.contentType&&c.contentName!==r.contentType||r.exampleName&&c.exampleName!==r.exampleName)),r.random&&a.length>1){let c=Math.floor(Math.random()*a.length);return gx(a[c])}else return a.length>0?gx(a[0]):Uf(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 gx(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})}}s(gx,"generateResponse");var Uf=s((t,e,r,n)=>{let o=`Error in policy: ${t} - On route ${e.method} ${r.route.path}. ${n}`;return D.internalServerError(e,r,{detail:o})},"getProblemDetailResponse");var AO="Incoming",NO={logRequestBody:!0,logResponseBody:!0};function hx(t){let e={};return t.forEach((r,n)=>{e[n]=r}),e}s(hx,"headersToObject");function yx(){return new Date().toISOString()}s(yx,"timestamp");var zf=new WeakMap,LO={};function MO(t,e){let r=zf.get(t);r||(r=LO);let n=Object.assign({...r},e);zf.set(t,n)}s(MO,"setMoesifContext");async function bx(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}s(bx,"readBody");var DO={},jf;function wx(){if(!jf)throw new F("Invalid State - no _lastLogger");return jf}s(wx,"getLastLogger");function UO(t){let e=DO[t];return e||(e=new ce("moesif-inbound",100,async r=>{let n=JSON.stringify(r);wx().debug("posting",n);let o=await z.fetch("https://api.moesif.net/v1/events/batch",{method:"POST",headers:{"content-type":"application/json","X-Moesif-Application-Id":t},body:n});o.ok||wx().error({status:o.status,body:await o.text()})})),e}s(UO,"getDispatcher");async function zO(t,e,r,n){R("policy.inbound.moesif-analytics"),jf=e.log;let o=yx(),i=Object.assign(NO,r);if(!i.applicationId)throw new w(`Invalid configuration for MoesifInboundPolicy '${n}' - applicationId is required`);let a=i.logRequestBody?await bx(t,e):void 0;return e.addResponseSendingFinalHook(async(c,u)=>{let l=UO(i.applicationId),d=ut(t),p=zf.get(e)??{},m={time:o,uri:t.url,verb:t.method,body:a,ip_address:d??void 0,api_version:p.apiVersion,headers:hx(t.headers)},f=i.logResponseBody?await bx(c,e):void 0,g={time:yx(),status:c.status,headers:hx(c.headers),body:f},b={request:m,response:g,user_id:p.userId??u.user?.sub,session_token:p.sessionToken,company_id:p.companyId,metadata:p.metadata,direction:AO};l.enqueue(b),e.waitUntil(l.waitUntilFlushed())}),t}s(zO,"MoesifInboundPolicy");async function vx(t,e,r,n){let o=K.getLogger(t),{authApiJWT:i,meteringServiceUrl:a}=P.instance,c;try{let l=await z.fetch(`${a}/internal/v1/metering/${n}/subscriptions?customerKey=${e}`,{headers:{Authorization:`Bearer ${i}`,"zp-rid":t.requestId},method:"GET"});if(l.ok)c=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 u=c?.data&&c.data.length>0?c.data:void 0;return u&&u.length>1?u.sort((d,p)=>d.createdOn>p.createdOn?-1:1)[0]:u&&u[0]}s(vx,"loadSubscription");async function xx(t,e,r,n,o){let{authApiJWT:i,meteringServiceUrl:a}=P.instance,c=K.getLogger(t);try{let u=await z.fetch(`${a}/internal/v1/metering/${n}/subscriptions/${e}/quotas/consume`,{headers:{Authorization:`Bearer ${i}`,"zp-rid":t.requestId},method:"POST",body:JSON.stringify({meters:o})});if(!u.ok){let l=await u.json(),d=l.detail??l.title??"Unknown error on quota consumption.";t.log.error(`MonetizationInboundPolicy '${r}' - Error updating subscription quota. ${u.status} - ${d}`),c.error(`MonetizationInboundPolicy '${r}' - Error updating subscription quota. ${u.status} - ${d}`)}}catch(u){t.log.error(`MonetizationInboundPolicy '${r}' - Error updating subscription quota.`),c.error(`MonetizationInboundPolicy '${r}' - Error updating subscription quota.`,u)}}s(xx,"consumeSubcriptionQuotas");var jO=new Set(["active","inactive","incomplete","incomplete-expired","trialing","past-due","canceled","unpaid"]);function Ia(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 w(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 w?new w(`MonetizationInboundPolicy '${e}' - The property 'meters' is invalid. ${r.message}`):r}}s(Ia,"validateMeters");function Rx(t,e){if(t)try{if(t.length===0)throw new w("Must set valid subscription statuses");let r=Dt(t),n=[];for(let o of r)jO.has(o)||n.push(o);if(n.length>0)throw new w(`Found the following invalid statuses: ${n.join(", ")}`);return t}catch(r){throw r instanceof w?new w(`MonetizationInboundPolicy '${e}' - The property 'allowedSubscriptionStatuses' is invalid. ${r.message}`):r}else return["active","incomplete","trialing"]}s(Rx,"parseAllowedSubscriptionStatuses");function Px(t,e){let r={},n={};for(let o in e)Object.hasOwn(t,o)?r[o]=e[o]:n[o]=e[o];return{metersInSubscription:r,metersNotInSubscription:n}}s(Px,"compareMeters");var Zf=class extends Re{static{s(this,"MonetizationInboundPolicy")}static getSubscription(e){return pe.get(e,En)}static setMeters(e,r){Ia(r,"setMeters");let n=pe.get(e,Cn)??{};Object.assign(n,r),pe.set(e,Cn,n)}constructor(e,r){super(e,r),R("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=It(this.options.meterOnStatusCodes),i=pe.get(r,Cn),a={...this.options.meters,...i};Ia(a,this.policyName);let c=this.options.allowRequestsWithoutSubscription??!1,u=Rx(this.options.allowedSubscriptionStatuses,this.policyName);r.addResponseSendingFinalHook(async(b,h,x)=>{let v=pe.get(x,En);if((this.options.allowRequestsWithoutSubscription??!1)&&!v){x.log.debug(`MonetizationInboundPolicy '${this.policyName}' - No subscription found and property 'allowRequestsWithoutSubscription' is true`);return}if(!this.options.bucketId)if(Ie.ZUPLO_METERING_SERVICE_BUCKET_ID)this.options.bucketId=Ie.ZUPLO_METERING_SERVICE_BUCKET_ID;else throw new w(`MonetizationInboundPolicy '${this.policyName}' - No bucketId property provided`);let A=pe.get(x,Cn),C={...this.options.meters,...A};if(Ia(C,this.policyName),o.includes(b.status)&&v&&C){x.log.debug(`MonetizationInboundPolicy '${this.policyName}' - Updating subscription '${v.id}' with meters '${JSON.stringify(C)} on response status '${b.status}'`);let{metersInSubscription:S,metersNotInSubscription:N}=Px(v.meters,C);if(N&&Object.keys(N).length>0){let j=Object.keys(N);x.log.warn(`The following meters cannot be applied since they are not present in the subscription: '${j}'`)}await xx(x,v.id,this.policyName,this.options.bucketId,S)}});let l=e.user;if(!l)return c?e:D.unauthorized(e,r,{detail:"Unable to check subscription for anonymous user"});if(!this.options.bucketId)if(Ie.ZUPLO_METERING_SERVICE_BUCKET_ID)this.options.bucketId=Ie.ZUPLO_METERING_SERVICE_BUCKET_ID;else throw new w(`MonetizationInboundPolicy '${this.policyName}' - No bucketId property provided`);let{sub:d}=l,p=await vx(r,d,this.policyName,this.options.bucketId);if(!p)return r.log.warn("No valid subscription found"),c?e:D.unauthorized(e,r,{detail:"No valid subscription found"});if(!u.includes(p.status)&&!c)return r.log.warn(`Subscription '${p.id}' has status '${p.status}' which is not part of the allowed statuses.`),D.unauthorized(e,r,{detail:"No valid subscription found"});u.includes(p.status)&&(r.log.debug(`Loading subscription '${p.id}' for user sub '${d}' to ContextData`),pe.set(r,En,p));let m=pe.get(r,En);if(!m)return c?e:(r.log.warn("Subscription is not available for user"),D.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}'`),D.tooManyRequests(e,r,{detail:"Quota is not set up for the user's subscription",title:"Quota Exceeded"});let g=Object.keys(a).filter(b=>!Object.keys(m.meters).includes(b));if(g.length>0)return r.log.warn(`The following policy meters are not present in the subscription: ${g.join(", ")}`),D.tooManyRequests(e,r,{detail:`The following policy meters are not present in the subscription: ${g.join(", ")}`,title:"Quota Exceeded"});for(let b of Object.keys(a))if(m.meters[b].available<=0&&!n)return D.tooManyRequests(e,r,{detail:`Quota exceeded for meter '${b}'`,title:"Quota Exceeded"});return e}};async function Sa(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 i=await n.text();e.log.error(`Error getting token from identity provider. Status: ${n.status}`,i)}catch{}throw new F("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 F("Response returned from identity provider is not in the expected format.")}s(Sa,"getClientCredentialsAccessToken");var Rn=class extends Error{constructor(r,n,o){super(n,o);this.code=r}static{s(this,"OpenFGAError")}},ka=class{static{s(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 w("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 i=new Headers(n.headers||{});i.set("Content-Type","application/json"),i.set("Accept","application/json"),i.set("User-Agent",P.instance.systemUserAgent);let a=`${this.apiUrl}${e}`,c=new Request(a,{method:r,headers:i,body:o?JSON.stringify(o):void 0}),u=await z.fetch(c);if(u.status!==200){let l;try{l=await u.json()}catch{}throw!l||!l.code||!l.message?new Rn("unknown",`Unknown error. Status: ${u.status}`):new Rn(l.code,l.message)}return u.json()}};function Wo(t,e,r){!t[e]&&r&&(t[e]=r)}s(Wo,"setHeaderIfNotSet");var Ix="X-OpenFGA-Client-Method",Sx="X-OpenFGA-Client-Bulk-Request-Id",Ko=class extends ka{static{s(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 Wo(n,Ix,"BatchCheck"),Wo(n,Sx,crypto.randomUUID()),{responses:await Promise.all(e.map(async i=>this.check(i,Object.assign({},r,n)).then(a=>(a._request=i,a)).catch(a=>{if(a instanceof Rn)throw a;return{allowed:void 0,error:a,_request:i}})))}}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:i,contextualTuples:a,context:c}=e,{headers:u={}}=r;if(Wo(u,Ix,"ListRelations"),Wo(u,Sx,crypto.randomUUID()),!i?.length)throw new Error("When calling listRelations, at least one relation must be passed in the relations field");let l=await this.batchCheck(i.map(p=>({user:n,relation:p,object:o,contextualTuples:a,context:c})),Object.assign({},r,u)),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 kx=Symbol("openfga-authz-context-data"),Pn=class extends Re{static{s(this,"BaseOpenFGAAuthZInboundPolicy")}client;authorizer;cache;static setContextChecks(e,r){let n=Array.isArray(r)?r:[r];pe.set(e,kx,n)}constructor(e,r){if(super(e,r),ae(e,r).required("apiUrl","string").optional("storeId","string").optional("authorizationModelId","string"),!e.credentials)throw new w(`${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 w(`${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 Ko({apiUrl:e.apiUrl,storeId:e.storeId,authorizationModelId:e.authorizationModelId})}async handler(e,r){if(!this.cache){let a=await xe(this.policyName,void 0,this.options);this.cache=new be(a,r)}let n=s(a=>this.options.allowUnauthorizedRequests?e:D.forbidden(e,r,{detail:a}),"forbiddenResponse"),o=pe.get(r,kx);if(!o||o.length===0)throw new F(`${this.policyType} '${this.policyName}' - No checks found in the context.`);let i=await this.authorizer(e,r);try{r.log.debug("OpenFGA checks",o);let a=await this.client.batchCheck(o,{headers:i});return r.log.debug("OpenFGA Response",a),a.responses.every(c=>c.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),D.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 le(`${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 i=await Sa({tokenEndpointUrl:e.oauthTokenEndpointUrl,clientId:e.clientId,clientSecret:e.clientSecret,audience:e.apiAudience},n);return this.cache?.put("client_credentials_token",i.access_token,i.expires_in),{Authorization:`Bearer ${i.access_token}`}};throw new F("Invalid state for credentials method is not valid. This should not happen.")}};var Tx=["us1","eu1","au1"],qf=class extends Pn{static{s(this,"OktaFGAAuthZInboundPolicy")}constructor(e,r){if(!Tx.includes(e.region))throw new w(`OktaFGAAuthZInboundPolicy '${r}' - The 'region' option is invalid. Must be one of ${Tx.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),R("policy.inbound.oktafga-authz")}};var ZO=s(async(t,e,r,n)=>(R("policy.inbound.okta-jwt-auth"),Je(t,e,{issuer:r.issuerUrl,audience:r.audience,jwkUrl:`${r.issuerUrl}/v1/keys`,allowUnauthenticatedRequests:r.allowUnauthenticatedRequests,oAuthResourceMetadataEnabled:r.oAuthResourceMetadataEnabled},n)),"OktaJwtInboundPolicy");var Ff=class extends Pn{static{s(this,"OpenFGAAuthZInboundPolicy")}constructor(e,r){super(e,r),R("policy.inbound.openfga-authz")}};var Ex={},Hf=Symbol("openmeter-meters"),Gf=class extends Re{static{s(this,"OpenMeterInboundPolicy")}#e;#t;#n;#r;#o;#i;constructor(e,r){if(super(e,r),R("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 w(`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 w(`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 w(`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=It(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(c=>this.checkEntitlement(n,c,r).then(u=>({featureKey:c,result:u}))),i=await Promise.all(o),a=null;for(let{result:c,featureKey:u}of i)!c.hasAccess&&!a&&(a={...c,featureKey:u});if(a)return r.log.warn(`OpenMeterInboundPolicy '${this.policyName}' blocked request due to insufficient entitlements on feature '${a.featureKey}' for subject '${n}'.`),D.tooManyRequests(e,r,{detail:"Your subscription has insufficient entitlements for this request."})}catch(o){let i=o instanceof Error?o.message:String(o);r.log.error(`Error during entitlement checking in OpenMeterInboundPolicy '${this.policyName}': ${i}`)}}return this.setupMetering(e,r),e}getSubject(e){if(!e.user)throw new F(`OpenMeterInboundPolicy '${this.policyName}' requires a user to be authenticated. Ensure you have an authentication policy set before this policy?`);return Mt(e.user,this.#o,"subjectPath")}async checkEntitlement(e,r,n){let o=`${this.#n}/api/v1/subjects/${encodeURIComponent(e)}/entitlements/${encodeURIComponent(r)}/value`,i={"content-type":"application/json"};this.options.apiKey&&(i.authorization=`Bearer ${this.options.apiKey}`);try{let a=await z.fetch(o,{method:"GET",headers:i});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 c=a instanceof Error?a.message:String(a);return n.log.error(`Error in OpenMeterInboundPolicy '${this.policyName}': ${c}`),{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 i=pe.get(r,Hf)??(this.options.meter?Array.isArray(this.options.meter)?this.options.meter:[this.options.meter]:[]),a=new Date().toISOString();for(let c of i){let u={specversion:"1.0",id:`${r.requestId}-${c.type}`,time:a,source:this.#t,subject:o,...c},l=this.#r,d=Ex[l];d||(d=new ce("openmeter-ingest-event",10,async p=>{try{let m=await z.fetch(this.#r,{method:"POST",body:JSON.stringify(p),headers:this.#e});if(m.status!==204){let f=await m.text().catch(()=>"");r.log.error(`Unexpected response in OpenMeterInboundPolicy '${this.policyName}'. ${m.status}`,f)}}catch(m){let f=m instanceof Error?m.message:String(m);throw r.log.error(`Error in OpenMeterInboundPolicy '${this.policyName}': ${f}`),m}}),Ex[l]=d),d.enqueue(u),r.waitUntil(d.waitUntilFlushed())}}})}static setMeters(e,r){let n=pe.get(e,Hf)||[];pe.set(e,Hf,[...n,...Array.isArray(r)?r:[r]])}};var qO=s(async(t,e,r,n)=>{R("policy.outbound.prompt-injection");let o=n.apiKey,i=n.model??"gpt-3.5-turbo",a=n.baseUrl??"https://api.openai.com/v1",c=n.strict??!1,u=await t.text(),l=s(x=>c?(r.log.error(`${x}, strict mode enabled - blocking request`),new Response("Service temporarily unavailable",{status:503})):(r.log.error(`${x}, failing open`),new Response(u,{status:t.status,headers:t.headers})),"handleClassifierFailure"),d=[{role:"system",content:`You are a security filter for LLMs and AI agents.
|