@zuplo/runtime 6.68.24 → 6.68.26
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 +2 -2
- package/out/esm/index.js.map +1 -1
- package/package.json +1 -1
package/out/esm/index.js
CHANGED
|
@@ -330,9 +330,9 @@ data: [DONE]
|
|
|
330
330
|
`)}return{text:p,model:f,chatId:y,events:v}}return s(m,"processSSEBuffer"),new TransformStream({async transform(p,f){if(u.isBlocked)return;let y=o.decode(p,{stream:!0});u.sseBuffer+=y;let{text:v,model:w,chatId:x,events:P}=m();if(v&&(u.accumulatedText+=v),w&&!u.model&&(u.model=w),x&&!u.chatId&&(u.chatId=x),P.length>0&&(u.pendingEvents.push(...P),u.chunkCount+=P.length),(a&&u.pendingEvents.length>=a||c&&Date.now()-u.lastCheckTime>=c)&&u.accumulatedText){let O=await d();if(u.lastCheckTime=Date.now(),O){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 $ of u.pendingEvents)f.enqueue(i.encode($));u.sentEvents.push(...u.pendingEvents),u.pendingEvents=[],n.debug("Events sent status",{totalEventsSent:u.sentEvents.length,pendingEvents:0,provider:r})}},async flush(p){if(u.sseBuffer.length>0&&!u.isBlocked){let{text:f,model:y,chatId:v,events:w}=m();f&&(u.accumulatedText+=f),y&&!u.model&&(u.model=y),v&&!u.chatId&&(u.chatId=v),w.length>0&&u.pendingEvents.push(...w)}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)p.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)p.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(hR,"createAkamaiStreamingAccumulator");function yR(t,e){if(e){if(typeof e=="string")return e;if(Array.isArray(e))return e.map(r=>typeof r.content=="string"?r.content:Array.isArray(r.content)?r.content.filter(n=>(n.type==="text"||n.type==="input_text")&&(n.text||n.input_text)).map(n=>n.text||n.input_text).join(" "):"").filter(Boolean).join(`
|
|
331
331
|
`)}return!t||!Array.isArray(t)?"":t.map(r=>typeof r.content=="string"?r.content:Array.isArray(r.content)?r.content.filter(n=>n.type==="text"&&typeof n.text=="string").map(n=>n.text).join(" "):"").filter(Boolean).join(`
|
|
332
332
|
`)}s(yR,"extractTextFromMessages");function bR(t){if(!t)return"";let e=t,r=e.output||e.choices;return r&&Array.isArray(r)?r.map(n=>{let o=n,i=o.message;return i?.content&&typeof i.content=="string"?i.content:o.text&&typeof o.text=="string"?o.text:""}).filter(Boolean).join(`
|
|
333
|
-
`):(e.data&&e.object==="list"||e.error,"")}s(bR,"extractTextFromResponse");async function rg(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 N.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(rg,"checkWithAkamai");function ng(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(ng,"createBlockedResponse");var On=De("zuplo:policies:AkamaiAIFirewallPolicy");async function O$(t,e,r,n){I("policy.inbound.akamai-ai-firewall");let o=J.getLogger(e),i=Date.now();try{let a=t.user,c=a?.configuration?.policies?.["akamai-ai-firewall"];if(!c?.enabled)return On("Akamai AI Firewall not enabled for this user, passing through"),t;let u=c;On("Using dynamic configuration from AI Gateway");let l,d,m=!1;try{l=await t.clone().json(),m=l?.stream===!0,d=yR(l?.messages,l?.input)}catch{o.warn("Could not parse request body for Akamai AI Firewall")}if(d){On("Checking LLM input with Akamai");let p=await rg(d,"input",e,u,o);if(p){let f=a?.configuration?.id;return e.analyticsContext.addAnalyticsEvent(1,Ae.AI_GATEWAY_BLOCKED_COUNT,{type:"akamai-firewall-input",configId:f??null}),ng(p,"completion request")}}return e.addResponseSendingHook(async(p,f,y)=>{try{if(m&&p.body){if(u.streamingAccumulation?.enabled!==!1){On("Setting up streaming accumulator for response validation");let x=hR(y,u,"ai-gateway"),P=p.body.pipeThrough(x);return new Response(P,{status:p.status,statusText:p.statusText,headers:p.headers})}return p}if(!m){On("Checking non-streaming LLM output with Akamai");let v;try{let x=await p.clone().json();v=bR(x)}catch{o.warn("Could not parse response body for Akamai AI Firewall")}if(v){let w=await rg(v,"output",y,u,o);if(w){let x=a?.configuration?.id;return y.analyticsContext.addAnalyticsEvent(1,Ae.AI_GATEWAY_BLOCKED_COUNT,{type:"akamai-firewall-output",configId:x??null}),ng(w,"completion response")}}}return p}catch(v){return o.error(v,"Failed to check LLM output"),p}}),t}catch(a){return o.error(a,"Error in AkamaiAIFirewallInboundPolicy"),t}finally{let a=Date.now()-i;On(`AkamaiAIFirewallInboundPolicy completed - latency ${a}ms`)}}s(O$,"AkamaiAIFirewallInboundPolicy");var vR=new WeakMap,wR={},og=class{static{s(this,"AmberfloMeteringPolicy")}static setRequestProperties(e,r){vR.set(e,r)}};async function $$(t,e,r,n){if(I("policy.inbound.amberflo-metering"),!r.statusCodes)throw new R(`Invalid AmberfloMeterInboundPolicy '${n}': options.statusCodes must be an array of HTTP status code numbers`);let o=Dt(r.statusCodes);return e.addResponseSendingFinalHook(async i=>{if(o.includes(i.status)){let a=vR.get(e),c=r.customerId;if(r.customerIdPropertyPath){if(!t.user)throw new q(`Unable to apply customerIdPropertyPath '${r.customerIdPropertyPath}' as request.user is 'undefined'.`);c=Wt(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 m={customerId:u,meterApiName:l,meterValue:d,meterTimeInMillis:Date.now(),dimensions:Object.assign(r.dimensions??{},a?.dimensions)},p=wR[r.apiKey];if(!p){let f=r.apiKey,y=t.headers.get("zm-test-id")??"";p=new ae("amberflo-ingest-meter",10,async v=>{try{let w=r.url??"https://app.amberflo.io/ingest",x=await N.fetch(w,{method:"POST",body:JSON.stringify(v),headers:{"content-type":"application/json","x-api-key":f,"zm-test-id":y}});x.ok||e.log.error(`Unexpected response in AmberfloMeteringInboundPolicy '${n}'. ${x.status}: ${await x.text()}`)}catch(w){throw e.log.error(`Error in AmberfloMeteringInboundPolicy '${n}': ${w.message}`),w}}),wR[f]=p}p.enqueue(m),e.waitUntil(p.waitUntilFlushed())}}),t}s($$,"AmberfloMeteringInboundPolicy");var xR="key-metadata-cache-type";function A$(t,e){return e.authScheme===""?t:t.replace(`${e.authScheme} `,"")}s(A$,"getKeyValue");async function ig(t,e,r,n){if(I("policy.inbound.api-key"),!r.bucketName)if(Fe.ZUPLO_API_KEY_SERVICE_BUCKET_NAME)r.bucketName=Fe.ZUPLO_API_KEY_SERVICE_BUCKET_NAME;else throw new R(`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 R(`ApiKeyInboundPolicy '${n}' - minimum cacheTtlSeconds value is 60s, '${o.cacheTtlSeconds}' is invalid`);let i=s(x=>o.allowUnauthenticatedRequests?t:U.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 L$(c),l=await ve(n,void 0,o),d=new be(l,e),m=await d.get(u);if(m&&m.isValid===!0)return t.user=m.user,t;if(m&&!m.isValid)return m.typeId!==xR&&J.getLogger(e).error(`ApiKeyInboundPolicy '${n}' - cached metadata has invalid typeId '${m.typeId}'`,m),i("Authorization Failed");let p={key:c},f=new Headers({"content-type":"application/json"});Le(f,e.requestId);let y=await He({retryDelayMs:5,retries:2,logger:J.getLogger(e)},`${S.instance.apiKeyServiceUrl}/v1/$validate/${o.bucketName}`,{method:"POST",headers:f,body:JSON.stringify(p)});if(y.status===401)return e.log.info(`ApiKeyInboundPolicy '${n}' - 401 response from Key Service`),i("Authorization Failed");if(y.status!==200){try{let x=await y.text(),P=JSON.parse(x);e.log.error("Unexpected response from key service",P)}catch{e.log.error("Invalid response from key service")}throw new q(`ApiKeyInboundPolicy '${n}' - unexpected response from Key Service. Status: ${y.status}`)}let v=await y.json(),w={isValid:!0,typeId:xR,user:{apiKeyId:v.id,sub:v.name,data:v.metadata}};return t.user=w.user,d.put(u,w,o.cacheTtlSeconds),t}s(ig,"ApiKeyInboundPolicy");async function L$(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(L$,"hashValue");var N$=ig;import{createRemoteJWKSet as U$,jwtVerify as PR}from"jose";import{createLocalJWKSet as M$}from"jose";var sg=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 ag&&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",S.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 N.fetch(e.href,{signal:i?i.signal:void 0,redirect:"manual",headers:n.headers}).catch(l=>{throw c?new cg("JWKS fetch timed out"):l});if(a!==void 0&&clearTimeout(a),u.status!==200)throw new $n("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 $n("Failed to parse the JSON Web Key Set HTTP response as JSON")}}};function RR(t,e,r){let n=new sg(t,e,r);return async(o,i)=>n.getKey(o,i)}s(RR,"createRemoteJWKSet");var $n=class extends q{static{s(this,"JWKSError")}},ag=class extends $n{static{s(this,"JWKSNoMatchingKey")}},cg=class extends $n{static{s(this,"JWKSTimeout")}};var Fa={},D$=s((t,e)=>async(r,n)=>{if(!n.jwkUrl||typeof n.jwkUrl!="string")throw new R("Invalid State - jwkUrl not set");if(!Fa[n.jwkUrl]){let i=!1;if("useExperimentalInMemoryCache"in n&&typeof n.useExperimentalInMemoryCache=="boolean"&&(i=n.useExperimentalInMemoryCache),i){let a=await ve(t,void 0,n),c=new be(a,e);Fa[n.jwkUrl]=RR(new URL(n.jwkUrl),c,n.headers?{headers:n.headers}:void 0)}else Fa[n.jwkUrl]=U$(new URL(n.jwkUrl),n.headers?{headers:n.headers}:void 0)}let{payload:o}=await PR(r,Fa[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 R("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 PR(t,r,{issuer:e.issuer,audience:e.audience});return n},"secretVerifier");function j$(t){let e=Re.instance,n=`/.well-known/oauth-protected-resource${t.pathname}`;return kt.some(a=>a instanceof hi||a instanceof gi)?!0:e.routeData.routes.some(a=>{let c=a.pathPattern||a.path;try{return new _a({pathname:c}).test({pathname:n})}catch{return!1}})}s(j$,"ensureOAuthResourceMetadataRouteExists");var it=s(async(t,e,r,n)=>{I("policy.inbound.open-id-jwt-auth");let o=r.authHeader??"Authorization",i=t.headers.get(o),a="bearer ",c=s(f=>U.unauthorized(t,e,{detail:f}),"unauthorizedResponse");if(!r.jwkUrl&&!r.secret)throw new R(`OpenIdJwtInboundPolicy policy '${n}': One of 'jwkUrl' or 'secret' options are required.`);if(r.jwkUrl&&r.secret)throw new R(`OpenIdJwtInboundPolicy policy '${n}': Only one of 'jwkUrl' and 'secret' options should be provided.`);let u=r.jwkUrl?D$(n,e):z$,d=await s(async()=>{if(!i){let y=new URL(t.url);if(r.oAuthResourceMetadataEnabled&&j$(y)){let v=new URL(`/.well-known/oauth-protected-resource${y.pathname}`,y.origin);return U.unauthorized(t,e,{detail:"Bearer token required"},{"WWW-Authenticate":`Bearer resource_metadata="${v.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(y){let v=new URL(t.url);return"code"in y&&y.code==="ERR_JWT_EXPIRED"?e.log.warn(`Expired token used on url: ${v.pathname} `,y):e.log.warn(`Invalid token on: ${t.method} ${v.pathname}`,y),c("Invalid token")}},"getJwtOrRejectedResponse")();if(d instanceof Response)return r.allowUnauthenticatedRequests===!0?t:d;let m=r.subPropertyName??"sub",p=d[m];return p?(t.user={sub:p,data:d},t):c(`Token is not valid, no '${m}' property found.`)},"OpenIdJwtInboundPolicy");var Z$=s(async(t,e,r,n)=>(I("policy.inbound.auth0-jwt-auth"),it(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");function pe(t,e,r="policy",n){let o=`${r} '${e}'`;if(!_r(t))throw new R(`Options on ${o} is expected to be an object. Received the type '${typeof t}'.`);let i=s((u,l,d)=>{let m=t[u],p=n?`${n}.${String(u)}`:String(u);if(!(d&&m===void 0)){if(m===void 0)throw new R(`Value of '${p}' on ${o} is required, but no value was set. If using an environment variable, check that it is set correctly.`);if(l==="array"){if(!Array.isArray(m))throw new R(`Value of '${p}' on ${o} must be an array. Received type ${typeof m}.`)}else if(typeof m!==l)throw new R(`Value of '${p}' on ${o} must be of type ${l}. Received type ${typeof m}.`);if(typeof m=="string"&&m.length===0)throw new R(`Value of '${p}' on ${o} must be a non-empty string. The value received is empty. If using an environment variable, check that it is set correctly.`);if(typeof m=="number"&&Number.isNaN(m))throw new R(`Value of '${p}' on ${o} must be valid number. If using an environment variable, check that it is set correctly.`)}},"validate"),a=s((u,l)=>(i(u,l,!0),{optional:a,required:c}),"optional"),c=s((u,l)=>(i(u,l,!1),{optional:a,required:c}),"required");return{optional:a,required:c}}s(pe,"optionValidator");var IR=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 Ha(t,e){let r="$authzen-prop(";if(!t.startsWith(r)||!t.endsWith(")"))return t;let n=t.slice(r.length,-1),o=IR.get(n);o||(o=q$(n),IR.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(Ha,"evaluateAuthzenProp");var SR=Symbol("AUTHZEN_CONTEXT_DATA_52a5cf22-d922-4673-9815-6dc3d49071d9"),ug=class t extends Ie{static{s(this,"AuthZenInboundPolicy")}#e;#t;constructor(e,r){if(super(e,r),pe(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 R(`${this.policyType} '${this.policyName}' - subject.type is required.`);if(e.subject&&!e.subject.id)throw new R(`${this.policyType} '${this.policyName}' - subject.id is required.`);if(e.resource&&!e.resource.type)throw new R(`${this.policyType} '${this.policyName}' - resource.type is required.`);if(e.resource&&!e.resource.id)throw new R(`${this.policyType} '${this.policyName}' - resource.id is required.`);if(e.action&&!e.action.name)throw new R(`${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 R(`${this.policyType} '${this.policyName}' - authorizerUrl '${this.#e}' is not valid
|
|
333
|
+
`):(e.data&&e.object==="list"||e.error,"")}s(bR,"extractTextFromResponse");async function rg(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 N.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(rg,"checkWithAkamai");function ng(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(ng,"createBlockedResponse");var On=De("zuplo:policies:AkamaiAIFirewallPolicy");async function O$(t,e,r,n){I("policy.inbound.akamai-ai-firewall");let o=J.getLogger(e),i=Date.now();try{let a=t.user,c=a?.configuration?.policies?.["akamai-ai-firewall"];if(!c?.enabled)return On("Akamai AI Firewall not enabled for this user, passing through"),t;let u=c;On("Using dynamic configuration from AI Gateway");let l,d,m=!1;try{l=await t.clone().json(),m=l?.stream===!0,d=yR(l?.messages,l?.input)}catch{o.warn("Could not parse request body for Akamai AI Firewall")}if(d){On("Checking LLM input with Akamai");let p=await rg(d,"input",e,u,o);if(p){let f=a?.configuration?.id;return e.analyticsContext.addAnalyticsEvent(1,Ae.AI_GATEWAY_BLOCKED_COUNT,{type:"akamai-firewall-input",configId:f??null}),ng(p,"completion request")}}return e.addResponseSendingHook(async(p,f,y)=>{try{if(m&&p.body){if(u.streamingAccumulation?.enabled!==!1){On("Setting up streaming accumulator for response validation");let x=hR(y,u,"ai-gateway"),P=p.body.pipeThrough(x);return new Response(P,{status:p.status,statusText:p.statusText,headers:p.headers})}return p}if(!m){On("Checking non-streaming LLM output with Akamai");let v;try{let x=await p.clone().json();v=bR(x)}catch{o.warn("Could not parse response body for Akamai AI Firewall")}if(v){let w=await rg(v,"output",y,u,o);if(w){let x=a?.configuration?.id;return y.analyticsContext.addAnalyticsEvent(1,Ae.AI_GATEWAY_BLOCKED_COUNT,{type:"akamai-firewall-output",configId:x??null}),ng(w,"completion response")}}}return p}catch(v){return o.error(v,"Failed to check LLM output"),p}}),t}catch(a){return o.error(a,"Error in AkamaiAIFirewallInboundPolicy"),t}finally{let a=Date.now()-i;On(`AkamaiAIFirewallInboundPolicy completed - latency ${a}ms`)}}s(O$,"AkamaiAIFirewallInboundPolicy");var vR=new WeakMap,wR={},og=class{static{s(this,"AmberfloMeteringPolicy")}static setRequestProperties(e,r){vR.set(e,r)}};async function $$(t,e,r,n){if(I("policy.inbound.amberflo-metering"),!r.statusCodes)throw new R(`Invalid AmberfloMeterInboundPolicy '${n}': options.statusCodes must be an array of HTTP status code numbers`);let o=Dt(r.statusCodes);return e.addResponseSendingFinalHook(async i=>{if(o.includes(i.status)){let a=vR.get(e),c=r.customerId;if(r.customerIdPropertyPath){if(!t.user)throw new q(`Unable to apply customerIdPropertyPath '${r.customerIdPropertyPath}' as request.user is 'undefined'.`);c=Wt(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 m={customerId:u,meterApiName:l,meterValue:d,meterTimeInMillis:Date.now(),dimensions:Object.assign(r.dimensions??{},a?.dimensions)},p=wR[r.apiKey];if(!p){let f=r.apiKey,y=t.headers.get("zm-test-id")??"";p=new ae("amberflo-ingest-meter",10,async v=>{try{let w=r.url??"https://app.amberflo.io/ingest",x=await N.fetch(w,{method:"POST",body:JSON.stringify(v),headers:{"content-type":"application/json","x-api-key":f,"zm-test-id":y}});x.ok||e.log.error(`Unexpected response in AmberfloMeteringInboundPolicy '${n}'. ${x.status}: ${await x.text()}`)}catch(w){throw e.log.error(`Error in AmberfloMeteringInboundPolicy '${n}': ${w.message}`),w}}),wR[f]=p}p.enqueue(m),e.waitUntil(p.waitUntilFlushed())}}),t}s($$,"AmberfloMeteringInboundPolicy");var xR="key-metadata-cache-type";function A$(t,e){return e.authScheme===""?t:t.replace(`${e.authScheme} `,"")}s(A$,"getKeyValue");async function ig(t,e,r,n){if(I("policy.inbound.api-key"),!r.bucketName)if(Fe.ZUPLO_API_KEY_SERVICE_BUCKET_NAME)r.bucketName=Fe.ZUPLO_API_KEY_SERVICE_BUCKET_NAME;else throw new R(`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 R(`ApiKeyInboundPolicy '${n}' - minimum cacheTtlSeconds value is 60s, '${o.cacheTtlSeconds}' is invalid`);let i=s(x=>o.allowUnauthenticatedRequests?t:U.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 L$(c),l=await ve(n,void 0,o),d=new be(l,e),m=await d.get(u);if(m&&m.isValid===!0)return t.user=m.user,t;if(m&&!m.isValid)return m.typeId!==xR&&J.getLogger(e).error(`ApiKeyInboundPolicy '${n}' - cached metadata has invalid typeId '${m.typeId}'`,m),i("Authorization Failed");let p={key:c},f=new Headers({"content-type":"application/json"});Le(f,e.requestId);let y=await He({retryDelayMs:5,retries:2,logger:J.getLogger(e)},`${S.instance.apiKeyServiceUrl}/v1/$validate/${o.bucketName}`,{method:"POST",headers:f,body:JSON.stringify(p)});if(y.status===401)return e.log.info(`ApiKeyInboundPolicy '${n}' - 401 response from Key Service`),i("Authorization Failed");if(y.status!==200){try{let x=await y.text(),P=JSON.parse(x);e.log.error("Unexpected response from key service",P)}catch{e.log.error("Invalid response from key service")}throw new q(`ApiKeyInboundPolicy '${n}' - unexpected response from Key Service. Status: ${y.status}`)}let v=await y.json(),w={isValid:!0,typeId:xR,user:{apiKeyId:v.id,sub:v.name,data:v.metadata}};return t.user=w.user,d.put(u,w,o.cacheTtlSeconds),t}s(ig,"ApiKeyInboundPolicy");async function L$(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(L$,"hashValue");var N$=ig;import{createRemoteJWKSet as U$,jwtVerify as PR}from"jose";import{createLocalJWKSet as M$}from"jose";var sg=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 ag&&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",S.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;try{u=await N.fetch(e.href,{signal:i?i.signal:void 0,redirect:"manual",headers:n.headers})}catch(l){throw c?new cg("JWKS fetch timed out"):l}finally{a!==void 0&&clearTimeout(a)}if(u.status!==200)throw new $n("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 $n("Failed to parse the JSON Web Key Set HTTP response as JSON")}}};function RR(t,e,r){let n=new sg(t,e,r);return async(o,i)=>n.getKey(o,i)}s(RR,"createRemoteJWKSet");var $n=class extends q{static{s(this,"JWKSError")}},ag=class extends $n{static{s(this,"JWKSNoMatchingKey")}},cg=class extends $n{static{s(this,"JWKSTimeout")}};var Fa={},D$=s((t,e)=>async(r,n)=>{if(!n.jwkUrl||typeof n.jwkUrl!="string")throw new R("Invalid State - jwkUrl not set");if(!Fa[n.jwkUrl]){let i=!1;if("useExperimentalInMemoryCache"in n&&typeof n.useExperimentalInMemoryCache=="boolean"&&(i=n.useExperimentalInMemoryCache),i){let a=await ve(t,void 0,n),c=new be(a,e);Fa[n.jwkUrl]=RR(new URL(n.jwkUrl),c,n.headers?{headers:n.headers}:void 0)}else Fa[n.jwkUrl]=U$(new URL(n.jwkUrl),n.headers?{headers:n.headers}:void 0)}let{payload:o}=await PR(r,Fa[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 R("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 PR(t,r,{issuer:e.issuer,audience:e.audience});return n},"secretVerifier");function j$(t){let e=Re.instance,n=`/.well-known/oauth-protected-resource${t.pathname}`;return kt.some(a=>a instanceof hi||a instanceof gi)?!0:e.routeData.routes.some(a=>{let c=a.pathPattern||a.path;try{return new _a({pathname:c}).test({pathname:n})}catch{return!1}})}s(j$,"ensureOAuthResourceMetadataRouteExists");var it=s(async(t,e,r,n)=>{I("policy.inbound.open-id-jwt-auth");let o=r.authHeader??"Authorization",i=t.headers.get(o),a="bearer ",c=s(f=>U.unauthorized(t,e,{detail:f}),"unauthorizedResponse");if(!r.jwkUrl&&!r.secret)throw new R(`OpenIdJwtInboundPolicy policy '${n}': One of 'jwkUrl' or 'secret' options are required.`);if(r.jwkUrl&&r.secret)throw new R(`OpenIdJwtInboundPolicy policy '${n}': Only one of 'jwkUrl' and 'secret' options should be provided.`);let u=r.jwkUrl?D$(n,e):z$,d=await s(async()=>{if(!i){let y=new URL(t.url);if(r.oAuthResourceMetadataEnabled&&j$(y)){let v=new URL(`/.well-known/oauth-protected-resource${y.pathname}`,y.origin);return U.unauthorized(t,e,{detail:"Bearer token required"},{"WWW-Authenticate":`Bearer resource_metadata="${v.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(y){let v=new URL(t.url);return"code"in y&&y.code==="ERR_JWT_EXPIRED"?e.log.warn(`Expired token used on url: ${v.pathname} `,y):e.log.warn(`Invalid token on: ${t.method} ${v.pathname}`,y),c("Invalid token")}},"getJwtOrRejectedResponse")();if(d instanceof Response)return r.allowUnauthenticatedRequests===!0?t:d;let m=r.subPropertyName??"sub",p=d[m];return p?(t.user={sub:p,data:d},t):c(`Token is not valid, no '${m}' property found.`)},"OpenIdJwtInboundPolicy");var Z$=s(async(t,e,r,n)=>(I("policy.inbound.auth0-jwt-auth"),it(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");function pe(t,e,r="policy",n){let o=`${r} '${e}'`;if(!_r(t))throw new R(`Options on ${o} is expected to be an object. Received the type '${typeof t}'.`);let i=s((u,l,d)=>{let m=t[u],p=n?`${n}.${String(u)}`:String(u);if(!(d&&m===void 0)){if(m===void 0)throw new R(`Value of '${p}' on ${o} is required, but no value was set. If using an environment variable, check that it is set correctly.`);if(l==="array"){if(!Array.isArray(m))throw new R(`Value of '${p}' on ${o} must be an array. Received type ${typeof m}.`)}else if(typeof m!==l)throw new R(`Value of '${p}' on ${o} must be of type ${l}. Received type ${typeof m}.`);if(typeof m=="string"&&m.length===0)throw new R(`Value of '${p}' on ${o} must be a non-empty string. The value received is empty. If using an environment variable, check that it is set correctly.`);if(typeof m=="number"&&Number.isNaN(m))throw new R(`Value of '${p}' on ${o} must be valid number. If using an environment variable, check that it is set correctly.`)}},"validate"),a=s((u,l)=>(i(u,l,!0),{optional:a,required:c}),"optional"),c=s((u,l)=>(i(u,l,!1),{optional:a,required:c}),"required");return{optional:a,required:c}}s(pe,"optionValidator");var IR=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 Ha(t,e){let r="$authzen-prop(";if(!t.startsWith(r)||!t.endsWith(")"))return t;let n=t.slice(r.length,-1),o=IR.get(n);o||(o=q$(n),IR.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(Ha,"evaluateAuthzenProp");var SR=Symbol("AUTHZEN_CONTEXT_DATA_52a5cf22-d922-4673-9815-6dc3d49071d9"),ug=class t extends Ie{static{s(this,"AuthZenInboundPolicy")}#e;#t;constructor(e,r){if(super(e,r),pe(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 R(`${this.policyType} '${this.policyName}' - subject.type is required.`);if(e.subject&&!e.subject.id)throw new R(`${this.policyType} '${this.policyName}' - subject.id is required.`);if(e.resource&&!e.resource.type)throw new R(`${this.policyType} '${this.policyName}' - resource.type is required.`);if(e.resource&&!e.resource.id)throw new R(`${this.policyType} '${this.policyName}' - resource.id is required.`);if(e.action&&!e.action.name)throw new R(`${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 R(`${this.policyType} '${this.policyName}' - authorizerUrl '${this.#e}' is not valid
|
|
334
334
|
${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=Ha(i.action.name,a)),i.subject?.id!==void 0&&(i.subject.id=Ha(i.subject.id,a)),i.resource?.id!==void 0&&(i.resource.id=Ha(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 N.fetch(this.#e,{method:"POST",body:JSON.stringify(i),headers:u});if(!l.ok){let m=`${this.policyType} '${this.policyName}' - Unexpected response from PDP: ${l.status} - ${l.statusText}:
|
|
335
|
-
${await l.text()}`;if(n)throw new Error(m);return r.log.error(m),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 R(o);e.log.warn(o)}}async#r(e,r,n){return U.forbidden(e,r,{detail:n})}async#o(e){if(!this.#t){let r=await ve(this.policyName,void 0,this.options);this.#t=new be(r,e)}}static setAuthorizationPayload(e,r){de.set(e,SR,r)}static getAuthorizationPayload(e){return de.get(e,SR)}};var Ga=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 N.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 lg=class t extends Ie{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),I("policy.inbound.axiomatics-authz"),pe(e,r).required("pdpUrl","string").required("pdpUsername","string").required("pdpPassword","string"),this.pdpService=new Ga(e)}async handler(e,r){let n=s(a=>this.options.allowUnauthorizedRequests?e:U.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),U.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)=>{I("policy.inbound.basic-auth");let n=t.headers.get("Authorization"),o="basic ",i=s(l=>U.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(),m=d.indexOf(":");if(m===-1||/[\0-\x1F\x7F]/.test(d))return await i("Invalid basic token value - see https://tools.ietf.org/html/rfc5234#appendix-B.1");let p=d.substring(0,m),f=d.substring(m+1),y=r.accounts.find(v=>v.username===p&&v.password===f);return y||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 Ba(t){return{second:t.getSeconds(),minute:t.getMinutes(),hour:t.getHours(),day:t.getDate(),month:t.getMonth(),weekday:t.getDay(),year:t.getFullYear()}}s(Ba,"extractDateElements");function TR(t,e){return new Date(t,e+1,0).getDate()}s(TR,"getDaysInMonth");function dg(t,e){return t<=e?e-t:6-t+e+1}s(dg,"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(m=>typeof m!="number"||m%1!==0||m<d.min||m>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=TR(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(),m=e==="next"?this.weekdays.find(p=>p>=d)??this.weekdays[0]:this.reversed.weekdays.find(p=>p<=d)??this.reversed.weekdays[0];if(m!==void 0){let p=e==="next"?dg(d,m):dg(m,d);l=e==="next"?o+p:o-p,(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=Ba(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),m=l&&d===r.day;if(d!==void 0&&m){let p=this.findAllowedTime("next",r);if(p!==void 0)return new Date(c,u,d,p.hour,p.minute,p.second);d=this.findAllowedDayInMonth("next",c,u,d+1),m=!1}if(d!==void 0&&!m)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=Ba(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),m=l&&d===r.day;if(d!==void 0&&m){let p=this.findAllowedTime("prev",r);if(p!==void 0)return new Date(c,u,d,p.hour,p.minute,p.second);d>1&&(d=this.findAllowedDayInMonth("prev",c,u,d-1),m=!1)}if(d!==void 0&&!m)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}=Ba(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 Vr(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=>{Vr(d,e).forEach(p=>r.add(p))}),r;let o=s(d=>{d=e.aliases?.[d.toLowerCase()]??d;let m=parseInt(d,10);if(Number.isNaN(m))throw new Error(`Failed to parse ${t}: ${d} is NaN.`);if(m<e.min||m>e.max)throw new Error(`Failed to parse ${t}: ${d} is outside of constraint range of ${e.min} - ${e.max}.`);return m},"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(Vr,"parseElement");function pg(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:Vr(r,H$),minutes:Vr(n,G$),hours:Vr(o,B$),days:Vr(i,V$),months:new Set(Array.from(Vr(a,J$)).map(u=>u-1)),weekdays:new Set(Array.from(Vr(c,W$)).map(u=>u%7))})}s(pg,"parseCronExpression");var mg=class extends Ie{static{s(this,"BrownoutInboundPolicy")}crons;constructor(e,r){if(super(e,r),I("policy.inbound.brownout"),pe(e,r).optional("problem","object"),e.problem&&pe(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 R(`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=[pg(this.options.cronSchedule)]:this.crons=this.options.cronSchedule.map(n=>pg(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=U.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 U.format(i,e,r)}return e}};var Q$=["cdn-cache-control","cloudflare-cdn-cache-control","surrogate-control","cache-tag","expires"];async function Y$(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(Y$,"digestMessage");var X$=s(async(t,e)=>{let r=[...e.dangerouslyIgnoreAuthorizationHeader===!0?[]:["authorization"],...e.headers??[]],n=[];for(let[d,m]of t.headers.entries())r.includes(d)&&n.push({key:d.toLowerCase(),value:m});n.sort((d,m)=>d.key.localeCompare(m.key));let o=await Y$(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 eA(t,e,r,n){I("policy.inbound.caching");let o=await ve(n,r.cacheId,r),i=await caches.open(o),a=r?.cacheHttpMethods?.map(l=>l.toUpperCase())??["GET"],c=await X$(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],m=l.response.clone();if(!d.includes(m.status)||!a.includes(t.method.toUpperCase()))return;let p=r?.expirationSecondsTtl??60,f=new Response(m.body,m);Q$.forEach(y=>f.headers.delete(y)),f.headers.set("cache-control",`s-maxage=${p}`),e.waitUntil(i.put(c,f))}catch(d){e.log.error(`Error in caching-inbound-policy '${n}': "${d.message}"`,d)}}),t)}s(eA,"CachingInboundPolicy");var tA=s(async(t,e,r,n)=>{if(I("policy.inbound.change-method"),!r.method)throw new R(`ChangeMethodInboundPolicy '${n}' options.method must be valid HttpMethod`);return new le(t,{method:r.method})},"ChangeMethodInboundPolicy");var rA=s(async(t,e,r)=>{I("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 le(t,{headers:o})},"ClearHeadersInboundPolicy");var nA=s(async(t,e,r,n)=>{I("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 oA=s(async(t,e,r,n)=>{I("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",it(t,e,{issuer:o.href.slice(0,-1),jwkUrl:i.toString(),allowUnauthenticatedRequests:r.allowUnauthenticatedRequests,oAuthResourceMetadataEnabled:r.oAuthResourceMetadataEnabled},n)},"ClerkJwtInboundPolicy");var iA=s(async(t,e,r,n)=>{if(I("policy.inbound.cognito-jwt-auth"),!r.userPoolId)throw new R("userPoolId must be set in the options for CognitoJwtInboundPolicy");if(!r.region)throw new R("region must be set in the options for CognitoJwtInboundPolicy");return it(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 Ke=[];for(let t=0;t<256;++t)Ke.push((t+256).toString(16).slice(1));function kR(t,e=0){return(Ke[t[e+0]]+Ke[t[e+1]]+Ke[t[e+2]]+Ke[t[e+3]]+"-"+Ke[t[e+4]]+Ke[t[e+5]]+"-"+Ke[t[e+6]]+Ke[t[e+7]]+"-"+Ke[t[e+8]]+Ke[t[e+9]]+"-"+Ke[t[e+10]]+Ke[t[e+11]]+Ke[t[e+12]]+Ke[t[e+13]]+Ke[t[e+14]]+Ke[t[e+15]]).toLowerCase()}s(kR,"unsafeStringify");var fg,sA=new Uint8Array(16);function Ja(){if(!fg){if(typeof crypto>"u"||!crypto.getRandomValues)throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");fg=crypto.getRandomValues.bind(crypto)}return fg(sA)}s(Ja,"rng");var gg={};function aA(t,e,r){let n;if(t)n=CR(t.random??t.rng?.()??Ja(),t.msecs,t.seq,e,r);else{let o=Date.now(),i=Ja();cA(gg,o,i),n=CR(i,gg.msecs,gg.seq,e,r)}return e??kR(n)}s(aA,"v7");function cA(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(cA,"updateV7State");function CR(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(CR,"v7Bytes");var Wa=aA;function ER(t,e,r,n,o){return o?po(async i=>{e.traceId&&await n(e.traceId,e.input,i,e.startTime,t,r)}):lo(t,async i=>{e.traceId&&await n(e.traceId,e.input,i,e.startTime,t,r)})}s(ER,"createOpikStreamingAccumulator");var An=De("zuplo:policies:CometOpikTracingPolicy"),OR=Symbol("comet-opik-tracing");function uA(t,e){de.set(t,OR,e)}s(uA,"setTracingContext");function lA(t){return de.get(t,OR)}s(lA,"getTracingContext");async function dA(t,e,r){let n=r.baseUrl||"https://www.comet.com/opik/api",o=r.workspace,i=new Date().toISOString(),a=Wa(),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 N.fetch(`${n}/v1/private/traces/batch`,{method:"POST",headers:u,body:JSON.stringify({traces:[c]})});if(!l.ok){let d=await l.text();An("Failed to create Opik trace:",l.status,d);return}return An("Created Opik trace with ID:",a),a}catch(u){An("Error creating Opik trace:",u);return}}s(dA,"createTrace");async function _R(t,e,r,n,o,i){let a=i.baseUrl||"https://www.comet.com/opik/api",c=i.workspace,u=new Date().toISOString(),l=Wa(),d,m=r;if(m?.usage&&typeof m.usage=="object"){let y=m.usage,v=typeof y.input_tokens=="number"?y.input_tokens:typeof y.prompt_tokens=="number"?y.prompt_tokens:void 0,w=typeof y.output_tokens=="number"?y.output_tokens:typeof y.completion_tokens=="number"?y.completion_tokens:void 0;d={prompt_tokens:v,completion_tokens:w,total_tokens:typeof y.total_tokens=="number"?y.total_tokens:void 0}}let p="";m?.output&&Array.isArray(m.output)?p=m.output.map(y=>{let w=y.content;return w&&Array.isArray(w)?w.map(x=>x.text).filter(x=>typeof x=="string").join(" "):""}).filter(y=>typeof y=="string"&&y.length>0).join(" "):m?.choices&&Array.isArray(m.choices)&&(p=m.choices.map(y=>y.message?.content).filter(y=>typeof y=="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:e?.messages?{messages:e.messages}:e?.input?{input:e.input}:{},output:{content:p},metadata:{request_id:o.requestId,temperature:e?.temperature,max_tokens:e?.max_tokens},tags:["llm-call","ai-gateway"]};try{let y={"Content-Type":"application/json","Comet-Workspace":c};i.apiKey&&(y.authorization=i.apiKey);let v={spans:[f]},w=await N.fetch(`${a}/v1/private/spans/batch`,{method:"POST",headers:y,body:JSON.stringify(v)});if(w.ok)An("Created Opik span for trace:",t);else{let x=await w.text();An("Failed to create Opik span:",w.status,x)}}catch(y){An("Error creating Opik span:",y)}}s(_R,"createSpan");async function pA(t,e,r,n){I("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,m=!1;try{l=await t.clone().json(),m=l?.stream===!0,l?.messages?d={messages:l.messages,model:u||l.model,temperature:l.temperature,max_tokens:l.max_tokens}:l?.input&&(d={input:l.input,model:u||l.model,temperature:l.temperature})}catch{e.log.error("Could not parse request body for Opik tracing")}if(d){let p=new Date().toISOString(),f=await dA(d,e,a);f&&(uA(e,{traceId:f,startTime:p,input:d}),e.addResponseSendingFinalHook(async v=>{let w=lA(e);if(w?.traceId)if(m&&v.body){let x=v.clone(),P=!!l?.input,k=ER(e,w,a,_R,P);x.body&&e.waitUntil(x.body.pipeThrough(k).pipeTo(new WritableStream({write(){},close(){},abort(O){e.log.error("Opik streaming accumulation aborted",{error:O})}})).catch(O=>{e.log.error("Error in Opik streaming accumulation",{error:O})}))}else{let x;try{x=await v.clone().json()}catch{e.log.error("Could not parse response body for Opik tracing")}e.waitUntil(_R(w.traceId,w.input,x,w.startTime,e,a))}}))}return t}s(pA,"CometOpikTracingInboundPolicy");var Ka=class extends Error{static{s(this,"ValidationError")}},hg=class extends Ka{static{s(this,"ArgumentUndefinedError")}constructor(e){super(`The argument '${e}' is undefined.`)}},yg=class extends Ka{static{s(this,"ArgumentTypeError")}constructor(e,r){super(`The argument '${e}' must be of type '${r}'.`)}};function mA(t,e){if(Vh(t))throw new hg(e)}s(mA,"throwIfUndefinedOrNull");function $R(t,e){if(mA(t,e),!Mt(t))throw new yg(e,"string")}s($R,"throwIfNotString");var fA=250,bg=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.")}},wg=class{constructor(e,r=S.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}){$R(e,"url");let i=new AbortController;setTimeout(()=>{i.abort()},this.timeoutMs);let a,c=new Headers({"content-type":"application/json"});Le(c,o);try{a=await N.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+=fA,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 ge("Rate limiting client timed out",{cause:l})}throw new ge("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 ge("Rate limiting service failed with 401: Unauthorized"):new ge(`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 Nr(e);return await this.fetch({url:`/quota/${n}`,method:"GET",requestId:r})}async setQuota(e,r,n){let o=await Nr(e);await this.fetch({url:`/quota/${o}`,method:"POST",body:JSON.stringify(r),requestId:n})}},Ln;function kr(t,e,r){let{redisURL:n,authApiJWT:o}=S.instance;if(Ln)return Ln;if(!o)return e.info("Using in-memory rate limit client for local development."),Ln=new bg,Ln;if(!Mt(n))throw new ge(`RateLimitClient used in policy '${t}' - rate limit service not configured`);if(!Mt(o))throw new ge(`RateLimitClient used in policy '${t}' - rate limit service not configured`);return Ln=new wg(n,r?.timeoutMs,e),Ln}s(kr,"getRateLimitClient");var gA=s(t=>vt(t)??"127.0.0.1","getRealIP");function Nn(t,e){return{function:wA(e,"RateLimitInboundPolicy",t),user:yA,ip:hA,all:bA}[e.rateLimitBy??"ip"]}s(Nn,"getRateLimitByFunctions");var hA=s(async t=>({key:`ip-${gA(t)}`}),"getIP"),yA=s(async t=>({key:`user-${t.user?.sub??"anonymous"}`}),"getUser"),bA=s(async()=>({key:"all-2d77ce9d-9a3c-4206-9ab2-668cfd271095"}),"getAll");function wA(t,e,r){let n;if(t.rateLimitBy==="function"){if(!t.identifier)throw new R(`${e} '${r}' - If rateLimitBy set to 'function' options.identifier must be specified`);if(!t.identifier.module||typeof t.identifier.module!="object")throw new R(`${e} '${r}' - If rateLimitBy set to 'function' options.identifier.module must be specified`);if(!t.identifier.export)throw new R(`${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 R(`${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==null)return null;if(typeof u!="object"){let l=`${e} '${c}' - Custom rate limit function must return a valid object.`;throw a.log.error(l),new q(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 q(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 q(l)}return u},"outerFunction")}s(wA,"wrapUserFunction");var Mn="Retry-After";var AR=De("zuplo:policies:ComplexRateLimitInboundPolicy"),vg=Symbol("complex-rate-limit-counters"),xg=class t extends Ie{static{s(this,"ComplexRateLimitInboundPolicy")}static setIncrements(e,r){let n=de.get(e,vg)??{};Object.assign(n,r),de.set(e,vg,n)}static getIncrements(e){return de.get(e,vg)??{}}constructor(e,r){super(e,r),I("policy.inbound.complex-rate-limit-inbound"),pe(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&&pe(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 R(`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=J.getLogger(r),i=kr(this.policyName,o),a=s((u,l)=>{if(this.options.throwOnFailure)throw new ge(u,{cause:l});o.error(u,l)},"throwOrLog"),c=s((u,l)=>{let d={};return(!u||u==="retry-after")&&(d[Mn]=l.toString()),U.tooManyRequests(e,r,void 0,d)},"rateLimited");try{let l=await Nn(this.policyName,this.options)(e,r,this.policyName);if(l==null)return e;let d=S.instance.isTestMode||S.instance.isWorkingCopy?S.instance.build.BUILD_ID:"",m=Object.assign({},this.options.limits,l.limits),p=(l.timeWindowMinutes??this.options.timeWindowMinutes??1)*60;r.addResponseSendingFinalHook(async()=>{try{let w=t.getIncrements(r);AR(`ComplexRateLimitInboundPolicy '${this.policyName}' - increments ${JSON.stringify(w)}`);let x=Object.entries(m).map(([k])=>({key:`complex-rate-limit${d}/${this.policyName}/${l.key}/${k}`,ttlSeconds:p,increment:w[k]??0})),P=i.multiIncrement(x,r.requestId);r.waitUntil(P),await P}catch(w){a(w.message,w)}});let f=Object.entries(m).map(([w,x])=>({key:`complex-rate-limit${d}/${this.policyName}/${l.key}/${w}`,ttlSeconds:p,limit:x})),y=await i.multiCount(f,r.requestId);return vA(y,f).length>0?c(this.options.headerMode??"retry-after",p):e}catch(u){return a(u.message,u),e}finally{let u=Date.now()-n;AR(`ComplexRateLimitInboundPolicy '${this.policyName}' - latency ${u}ms`)}}};function vA(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(vA,"findOverLimits");var xA=s(async(t,e,r,n)=>{if(I("policy.inbound.composite"),!r.policies||r.policies.length===0)throw new R(`CompositeInboundPolicy '${n}' must have valid policies defined`);let o=Re.instance,i=Yn(r.policies,o?.routeData.policies);return Fc(i)(t,e)},"CompositeInboundPolicy");var RA=s(async(t,e,r,n,o)=>{if(I("policy.outbound.composite"),!n.policies||n.policies.length===0)throw new R(`CompositeOutboundPolicy '${o}' must have valid policies defined`);let i=Re.instance,a=Xn(n.policies,i?.routeData.policies);return Hc(a)(t,e,r)},"CompositeOutboundPolicy");var PA=s(async(t,e,r,n)=>{I("policy.inbound.curity-phantom-token-auth");let o=t.headers.get("Authorization");if(!o)return U.unauthorized(t,e,{detail:"No authorization header"});let i=IA(o);if(!i)return U.unauthorized(t,e,{detail:"Failed to parse token from Authorization header"});let a=await ve(n,void 0,r),c=new be(a,e),u=await c.get(i);if(!u){let l=await N.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}'`),U.internalServerError(t,e,{detail:"Problem encountered authorizing the HTTP request"})):U.unauthorized(t,e)}return t.headers.set("Authorization",`Bearer ${u}`),t},"CurityPhantomTokenInboundPolicy");function IA(t){return t.split(" ")[0]==="Bearer"?t.split(" ")[1]:null}s(IA,"getToken");var SA=s(async(t,e,r,n)=>(I("policy.inbound.firebase-jwt-auth"),pe(r,n).required("projectId","string").optional("allowUnauthenticatedRequests","boolean"),it(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 TA=s(async(t,e,r)=>{I("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,m]of a)c[d]=m.toString();let u=new Headers(t.headers);return u.set("content-type","application/json"),u.delete("content-length"),new le(t,{body:JSON.stringify(c),headers:u})},"FormDataToJsonInboundPolicy");function LR(t,e,r,n,o){return o?po(async i=>{await n(e.input,i,e.traceStartTime,t,r)}):lo(t,async i=>{await n(e.input,i,e.traceStartTime,t,r)})}s(LR,"createGalileoStreamingAccumulator");var Rg=De("zuplo:policies:GalileoTracingPolicy"),UR=Symbol("galileo-tracing");function kA(t,e){de.set(t,UR,e)}s(kA,"setTracingContext");function CA(t){return de.get(t,UR)}s(CA,"getTracingContext");function NR(t){let e=new Date(t).getTime();return(Date.now()-e)*1e6}s(NR,"getDurationNs");async function MR(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 x=u.usage,P=typeof x.input_tokens=="number"?x.input_tokens:typeof x.prompt_tokens=="number"?x.prompt_tokens:void 0,k=typeof x.output_tokens=="number"?x.output_tokens:typeof x.completion_tokens=="number"?x.completion_tokens:void 0;c={num_input_tokens:P,num_output_tokens:k,num_total_tokens:typeof x.total_tokens=="number"?x.total_tokens:void 0,duration_ns:NR(r)}}let l="",d;u?.output&&Array.isArray(u.output)?l=u.output.map(x=>{let k=x.content;return k&&Array.isArray(k)?k.map(O=>O.text).filter(O=>typeof O=="string").join(" "):""}).filter(x=>typeof x=="string"&&x.length>0).join(" "):u?.choices&&Array.isArray(u.choices)&&(l=u.choices.map(x=>{let P=x,k=P.message;return P.finish_reason&&(d=String(P.finish_reason)),k?.content}).filter(x=>typeof x=="string").join(" "));let m=[],p="";t?.messages?(m=t.messages.map(x=>({role:x.role,content:x.content})),p=m.map(x=>`${x.role}: ${x.content}`).join(`
|
|
335
|
+
${await l.text()}`;if(n)throw new Error(m);return r.log.error(m),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 R(o);e.log.warn(o)}}async#r(e,r,n){return U.forbidden(e,r,{detail:n})}async#o(e){if(!this.#t){let r=await ve(this.policyName,void 0,this.options);this.#t=new be(r,e)}}static setAuthorizationPayload(e,r){de.set(e,SR,r)}static getAuthorizationPayload(e){return de.get(e,SR)}};var Ga=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 N.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 lg=class t extends Ie{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),I("policy.inbound.axiomatics-authz"),pe(e,r).required("pdpUrl","string").required("pdpUsername","string").required("pdpPassword","string"),this.pdpService=new Ga(e)}async handler(e,r){let n=s(a=>this.options.allowUnauthorizedRequests?e:U.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),U.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)=>{I("policy.inbound.basic-auth");let n=t.headers.get("Authorization"),o="basic ",i=s(l=>U.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(),m=d.indexOf(":");if(m===-1||/[\0-\x1F\x7F]/.test(d))return await i("Invalid basic token value - see https://tools.ietf.org/html/rfc5234#appendix-B.1");let p=d.substring(0,m),f=d.substring(m+1),y=r.accounts.find(v=>v.username===p&&v.password===f);return y||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 Ba(t){return{second:t.getSeconds(),minute:t.getMinutes(),hour:t.getHours(),day:t.getDate(),month:t.getMonth(),weekday:t.getDay(),year:t.getFullYear()}}s(Ba,"extractDateElements");function TR(t,e){return new Date(t,e+1,0).getDate()}s(TR,"getDaysInMonth");function dg(t,e){return t<=e?e-t:6-t+e+1}s(dg,"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(m=>typeof m!="number"||m%1!==0||m<d.min||m>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=TR(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(),m=e==="next"?this.weekdays.find(p=>p>=d)??this.weekdays[0]:this.reversed.weekdays.find(p=>p<=d)??this.reversed.weekdays[0];if(m!==void 0){let p=e==="next"?dg(d,m):dg(m,d);l=e==="next"?o+p:o-p,(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=Ba(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),m=l&&d===r.day;if(d!==void 0&&m){let p=this.findAllowedTime("next",r);if(p!==void 0)return new Date(c,u,d,p.hour,p.minute,p.second);d=this.findAllowedDayInMonth("next",c,u,d+1),m=!1}if(d!==void 0&&!m)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=Ba(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),m=l&&d===r.day;if(d!==void 0&&m){let p=this.findAllowedTime("prev",r);if(p!==void 0)return new Date(c,u,d,p.hour,p.minute,p.second);d>1&&(d=this.findAllowedDayInMonth("prev",c,u,d-1),m=!1)}if(d!==void 0&&!m)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}=Ba(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 Vr(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=>{Vr(d,e).forEach(p=>r.add(p))}),r;let o=s(d=>{d=e.aliases?.[d.toLowerCase()]??d;let m=parseInt(d,10);if(Number.isNaN(m))throw new Error(`Failed to parse ${t}: ${d} is NaN.`);if(m<e.min||m>e.max)throw new Error(`Failed to parse ${t}: ${d} is outside of constraint range of ${e.min} - ${e.max}.`);return m},"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(Vr,"parseElement");function pg(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:Vr(r,H$),minutes:Vr(n,G$),hours:Vr(o,B$),days:Vr(i,V$),months:new Set(Array.from(Vr(a,J$)).map(u=>u-1)),weekdays:new Set(Array.from(Vr(c,W$)).map(u=>u%7))})}s(pg,"parseCronExpression");var mg=class extends Ie{static{s(this,"BrownoutInboundPolicy")}crons;constructor(e,r){if(super(e,r),I("policy.inbound.brownout"),pe(e,r).optional("problem","object"),e.problem&&pe(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 R(`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=[pg(this.options.cronSchedule)]:this.crons=this.options.cronSchedule.map(n=>pg(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=U.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 U.format(i,e,r)}return e}};var Q$=["cdn-cache-control","cloudflare-cdn-cache-control","surrogate-control","cache-tag","expires"];async function Y$(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(Y$,"digestMessage");var X$=s(async(t,e)=>{let r=[...e.dangerouslyIgnoreAuthorizationHeader===!0?[]:["authorization"],...e.headers??[]],n=[];for(let[d,m]of t.headers.entries())r.includes(d)&&n.push({key:d.toLowerCase(),value:m});n.sort((d,m)=>d.key.localeCompare(m.key));let o=await Y$(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 eA(t,e,r,n){I("policy.inbound.caching");let o=await ve(n,r.cacheId,r),i=await caches.open(o),a=r?.cacheHttpMethods?.map(l=>l.toUpperCase())??["GET"],c=await X$(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],m=l.response.clone();if(!d.includes(m.status)||!a.includes(t.method.toUpperCase()))return;let p=r?.expirationSecondsTtl??60,f=new Response(m.body,m);Q$.forEach(y=>f.headers.delete(y)),f.headers.set("cache-control",`s-maxage=${p}`),e.waitUntil(i.put(c,f))}catch(d){e.log.error(`Error in caching-inbound-policy '${n}': "${d.message}"`,d)}}),t)}s(eA,"CachingInboundPolicy");var tA=s(async(t,e,r,n)=>{if(I("policy.inbound.change-method"),!r.method)throw new R(`ChangeMethodInboundPolicy '${n}' options.method must be valid HttpMethod`);return new le(t,{method:r.method})},"ChangeMethodInboundPolicy");var rA=s(async(t,e,r)=>{I("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 le(t,{headers:o})},"ClearHeadersInboundPolicy");var nA=s(async(t,e,r,n)=>{I("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 oA=s(async(t,e,r,n)=>{I("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",it(t,e,{issuer:o.href.slice(0,-1),jwkUrl:i.toString(),allowUnauthenticatedRequests:r.allowUnauthenticatedRequests,oAuthResourceMetadataEnabled:r.oAuthResourceMetadataEnabled},n)},"ClerkJwtInboundPolicy");var iA=s(async(t,e,r,n)=>{if(I("policy.inbound.cognito-jwt-auth"),!r.userPoolId)throw new R("userPoolId must be set in the options for CognitoJwtInboundPolicy");if(!r.region)throw new R("region must be set in the options for CognitoJwtInboundPolicy");return it(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 Ke=[];for(let t=0;t<256;++t)Ke.push((t+256).toString(16).slice(1));function kR(t,e=0){return(Ke[t[e+0]]+Ke[t[e+1]]+Ke[t[e+2]]+Ke[t[e+3]]+"-"+Ke[t[e+4]]+Ke[t[e+5]]+"-"+Ke[t[e+6]]+Ke[t[e+7]]+"-"+Ke[t[e+8]]+Ke[t[e+9]]+"-"+Ke[t[e+10]]+Ke[t[e+11]]+Ke[t[e+12]]+Ke[t[e+13]]+Ke[t[e+14]]+Ke[t[e+15]]).toLowerCase()}s(kR,"unsafeStringify");var fg,sA=new Uint8Array(16);function Ja(){if(!fg){if(typeof crypto>"u"||!crypto.getRandomValues)throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");fg=crypto.getRandomValues.bind(crypto)}return fg(sA)}s(Ja,"rng");var gg={};function aA(t,e,r){let n;if(t)n=CR(t.random??t.rng?.()??Ja(),t.msecs,t.seq,e,r);else{let o=Date.now(),i=Ja();cA(gg,o,i),n=CR(i,gg.msecs,gg.seq,e,r)}return e??kR(n)}s(aA,"v7");function cA(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(cA,"updateV7State");function CR(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(CR,"v7Bytes");var Wa=aA;function ER(t,e,r,n,o){return o?po(async i=>{e.traceId&&await n(e.traceId,e.input,i,e.startTime,t,r)}):lo(t,async i=>{e.traceId&&await n(e.traceId,e.input,i,e.startTime,t,r)})}s(ER,"createOpikStreamingAccumulator");var An=De("zuplo:policies:CometOpikTracingPolicy"),OR=Symbol("comet-opik-tracing");function uA(t,e){de.set(t,OR,e)}s(uA,"setTracingContext");function lA(t){return de.get(t,OR)}s(lA,"getTracingContext");async function dA(t,e,r){let n=r.baseUrl||"https://www.comet.com/opik/api",o=r.workspace,i=new Date().toISOString(),a=Wa(),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 N.fetch(`${n}/v1/private/traces/batch`,{method:"POST",headers:u,body:JSON.stringify({traces:[c]})});if(!l.ok){let d=await l.text();An("Failed to create Opik trace:",l.status,d);return}return An("Created Opik trace with ID:",a),a}catch(u){An("Error creating Opik trace:",u);return}}s(dA,"createTrace");async function _R(t,e,r,n,o,i){let a=i.baseUrl||"https://www.comet.com/opik/api",c=i.workspace,u=new Date().toISOString(),l=Wa(),d,m=r;if(m?.usage&&typeof m.usage=="object"){let y=m.usage,v=typeof y.input_tokens=="number"?y.input_tokens:typeof y.prompt_tokens=="number"?y.prompt_tokens:void 0,w=typeof y.output_tokens=="number"?y.output_tokens:typeof y.completion_tokens=="number"?y.completion_tokens:void 0;d={prompt_tokens:v,completion_tokens:w,total_tokens:typeof y.total_tokens=="number"?y.total_tokens:void 0}}let p="";m?.output&&Array.isArray(m.output)?p=m.output.map(y=>{let w=y.content;return w&&Array.isArray(w)?w.map(x=>x.text).filter(x=>typeof x=="string").join(" "):""}).filter(y=>typeof y=="string"&&y.length>0).join(" "):m?.choices&&Array.isArray(m.choices)&&(p=m.choices.map(y=>y.message?.content).filter(y=>typeof y=="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:e?.messages?{messages:e.messages}:e?.input?{input:e.input}:{},output:{content:p},metadata:{request_id:o.requestId,temperature:e?.temperature,max_tokens:e?.max_tokens},tags:["llm-call","ai-gateway"]};try{let y={"Content-Type":"application/json","Comet-Workspace":c};i.apiKey&&(y.authorization=i.apiKey);let v={spans:[f]},w=await N.fetch(`${a}/v1/private/spans/batch`,{method:"POST",headers:y,body:JSON.stringify(v)});if(w.ok)An("Created Opik span for trace:",t);else{let x=await w.text();An("Failed to create Opik span:",w.status,x)}}catch(y){An("Error creating Opik span:",y)}}s(_R,"createSpan");async function pA(t,e,r,n){I("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,m=!1;try{l=await t.clone().json(),m=l?.stream===!0,l?.messages?d={messages:l.messages,model:u||l.model,temperature:l.temperature,max_tokens:l.max_tokens}:l?.input&&(d={input:l.input,model:u||l.model,temperature:l.temperature})}catch{e.log.error("Could not parse request body for Opik tracing")}if(d){let p=new Date().toISOString(),f=await dA(d,e,a);f&&(uA(e,{traceId:f,startTime:p,input:d}),e.addResponseSendingFinalHook(async v=>{let w=lA(e);if(w?.traceId)if(m&&v.body){let x=v.clone(),P=!!l?.input,k=ER(e,w,a,_R,P);x.body&&e.waitUntil(x.body.pipeThrough(k).pipeTo(new WritableStream({write(){},close(){},abort(O){e.log.error("Opik streaming accumulation aborted",{error:O})}})).catch(O=>{e.log.error("Error in Opik streaming accumulation",{error:O})}))}else{let x;try{x=await v.clone().json()}catch{e.log.error("Could not parse response body for Opik tracing")}e.waitUntil(_R(w.traceId,w.input,x,w.startTime,e,a))}}))}return t}s(pA,"CometOpikTracingInboundPolicy");var Ka=class extends Error{static{s(this,"ValidationError")}},hg=class extends Ka{static{s(this,"ArgumentUndefinedError")}constructor(e){super(`The argument '${e}' is undefined.`)}},yg=class extends Ka{static{s(this,"ArgumentTypeError")}constructor(e,r){super(`The argument '${e}' must be of type '${r}'.`)}};function mA(t,e){if(Vh(t))throw new hg(e)}s(mA,"throwIfUndefinedOrNull");function $R(t,e){if(mA(t,e),!Mt(t))throw new yg(e,"string")}s($R,"throwIfNotString");var fA=250,bg=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.")}},wg=class{constructor(e,r=S.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}){$R(e,"url");let i=new Headers({"content-type":"application/json"});Le(i,o);let a=new AbortController,c=setTimeout(()=>{a.abort()},this.timeoutMs),u;try{u=await N.fetch(`${this.clientUrl}${e}`,{method:n,body:r,signal:a.signal,headers:i})}catch(d){if(d instanceof Error&&d.name==="AbortError"){let m=this.timeoutMs;throw this.timeoutMs+=fA,this.logger.warn({previousRateLimitClientTimeout:m,newRateLimitClientTimeout:this.timeoutMs,requestId:o},`Rate limit client timed out after ${m}ms. Increasing rate limit client timeout from ${m}ms to ${this.timeoutMs}ms.`),new ge("Rate limiting client timed out",{cause:d})}throw new ge("Could not fetch rate limiting client",{cause:d})}finally{clearTimeout(c)}let l=u.headers.get("Content-Type")?.includes("application/json")?await u.json():await u.text();if(u.ok)return l;throw u.status===401?new ge("Rate limiting service failed with 401: Unauthorized"):new ge(`Rate limiting service failed with (${u.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 Nr(e);return await this.fetch({url:`/quota/${n}`,method:"GET",requestId:r})}async setQuota(e,r,n){let o=await Nr(e);await this.fetch({url:`/quota/${o}`,method:"POST",body:JSON.stringify(r),requestId:n})}},Ln;function kr(t,e,r){let{redisURL:n,authApiJWT:o}=S.instance;if(Ln)return Ln;if(!o)return e.info("Using in-memory rate limit client for local development."),Ln=new bg,Ln;if(!Mt(n))throw new ge(`RateLimitClient used in policy '${t}' - rate limit service not configured`);if(!Mt(o))throw new ge(`RateLimitClient used in policy '${t}' - rate limit service not configured`);return Ln=new wg(n,r?.timeoutMs,e),Ln}s(kr,"getRateLimitClient");var gA=s(t=>vt(t)??"127.0.0.1","getRealIP");function Nn(t,e){return{function:wA(e,"RateLimitInboundPolicy",t),user:yA,ip:hA,all:bA}[e.rateLimitBy??"ip"]}s(Nn,"getRateLimitByFunctions");var hA=s(async t=>({key:`ip-${gA(t)}`}),"getIP"),yA=s(async t=>({key:`user-${t.user?.sub??"anonymous"}`}),"getUser"),bA=s(async()=>({key:"all-2d77ce9d-9a3c-4206-9ab2-668cfd271095"}),"getAll");function wA(t,e,r){let n;if(t.rateLimitBy==="function"){if(!t.identifier)throw new R(`${e} '${r}' - If rateLimitBy set to 'function' options.identifier must be specified`);if(!t.identifier.module||typeof t.identifier.module!="object")throw new R(`${e} '${r}' - If rateLimitBy set to 'function' options.identifier.module must be specified`);if(!t.identifier.export)throw new R(`${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 R(`${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==null)return null;if(typeof u!="object"){let l=`${e} '${c}' - Custom rate limit function must return a valid object.`;throw a.log.error(l),new q(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 q(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 q(l)}return u},"outerFunction")}s(wA,"wrapUserFunction");var Mn="Retry-After";var AR=De("zuplo:policies:ComplexRateLimitInboundPolicy"),vg=Symbol("complex-rate-limit-counters"),xg=class t extends Ie{static{s(this,"ComplexRateLimitInboundPolicy")}static setIncrements(e,r){let n=de.get(e,vg)??{};Object.assign(n,r),de.set(e,vg,n)}static getIncrements(e){return de.get(e,vg)??{}}constructor(e,r){super(e,r),I("policy.inbound.complex-rate-limit-inbound"),pe(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&&pe(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 R(`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=J.getLogger(r),i=kr(this.policyName,o),a=s((u,l)=>{if(this.options.throwOnFailure)throw new ge(u,{cause:l});o.error(u,l)},"throwOrLog"),c=s((u,l)=>{let d={};return(!u||u==="retry-after")&&(d[Mn]=l.toString()),U.tooManyRequests(e,r,void 0,d)},"rateLimited");try{let l=await Nn(this.policyName,this.options)(e,r,this.policyName);if(l==null)return e;let d=S.instance.isTestMode||S.instance.isWorkingCopy?S.instance.build.BUILD_ID:"",m=Object.assign({},this.options.limits,l.limits),p=(l.timeWindowMinutes??this.options.timeWindowMinutes??1)*60;r.addResponseSendingFinalHook(async()=>{try{let w=t.getIncrements(r);AR(`ComplexRateLimitInboundPolicy '${this.policyName}' - increments ${JSON.stringify(w)}`);let x=Object.entries(m).map(([k])=>({key:`complex-rate-limit${d}/${this.policyName}/${l.key}/${k}`,ttlSeconds:p,increment:w[k]??0})),P=i.multiIncrement(x,r.requestId);r.waitUntil(P),await P}catch(w){a(w.message,w)}});let f=Object.entries(m).map(([w,x])=>({key:`complex-rate-limit${d}/${this.policyName}/${l.key}/${w}`,ttlSeconds:p,limit:x})),y=await i.multiCount(f,r.requestId);return vA(y,f).length>0?c(this.options.headerMode??"retry-after",p):e}catch(u){return a(u.message,u),e}finally{let u=Date.now()-n;AR(`ComplexRateLimitInboundPolicy '${this.policyName}' - latency ${u}ms`)}}};function vA(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(vA,"findOverLimits");var xA=s(async(t,e,r,n)=>{if(I("policy.inbound.composite"),!r.policies||r.policies.length===0)throw new R(`CompositeInboundPolicy '${n}' must have valid policies defined`);let o=Re.instance,i=Yn(r.policies,o?.routeData.policies);return Fc(i)(t,e)},"CompositeInboundPolicy");var RA=s(async(t,e,r,n,o)=>{if(I("policy.outbound.composite"),!n.policies||n.policies.length===0)throw new R(`CompositeOutboundPolicy '${o}' must have valid policies defined`);let i=Re.instance,a=Xn(n.policies,i?.routeData.policies);return Hc(a)(t,e,r)},"CompositeOutboundPolicy");var PA=s(async(t,e,r,n)=>{I("policy.inbound.curity-phantom-token-auth");let o=t.headers.get("Authorization");if(!o)return U.unauthorized(t,e,{detail:"No authorization header"});let i=IA(o);if(!i)return U.unauthorized(t,e,{detail:"Failed to parse token from Authorization header"});let a=await ve(n,void 0,r),c=new be(a,e),u=await c.get(i);if(!u){let l=await N.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}'`),U.internalServerError(t,e,{detail:"Problem encountered authorizing the HTTP request"})):U.unauthorized(t,e)}return t.headers.set("Authorization",`Bearer ${u}`),t},"CurityPhantomTokenInboundPolicy");function IA(t){return t.split(" ")[0]==="Bearer"?t.split(" ")[1]:null}s(IA,"getToken");var SA=s(async(t,e,r,n)=>(I("policy.inbound.firebase-jwt-auth"),pe(r,n).required("projectId","string").optional("allowUnauthenticatedRequests","boolean"),it(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 TA=s(async(t,e,r)=>{I("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,m]of a)c[d]=m.toString();let u=new Headers(t.headers);return u.set("content-type","application/json"),u.delete("content-length"),new le(t,{body:JSON.stringify(c),headers:u})},"FormDataToJsonInboundPolicy");function LR(t,e,r,n,o){return o?po(async i=>{await n(e.input,i,e.traceStartTime,t,r)}):lo(t,async i=>{await n(e.input,i,e.traceStartTime,t,r)})}s(LR,"createGalileoStreamingAccumulator");var Rg=De("zuplo:policies:GalileoTracingPolicy"),UR=Symbol("galileo-tracing");function kA(t,e){de.set(t,UR,e)}s(kA,"setTracingContext");function CA(t){return de.get(t,UR)}s(CA,"getTracingContext");function NR(t){let e=new Date(t).getTime();return(Date.now()-e)*1e6}s(NR,"getDurationNs");async function MR(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 x=u.usage,P=typeof x.input_tokens=="number"?x.input_tokens:typeof x.prompt_tokens=="number"?x.prompt_tokens:void 0,k=typeof x.output_tokens=="number"?x.output_tokens:typeof x.completion_tokens=="number"?x.completion_tokens:void 0;c={num_input_tokens:P,num_output_tokens:k,num_total_tokens:typeof x.total_tokens=="number"?x.total_tokens:void 0,duration_ns:NR(r)}}let l="",d;u?.output&&Array.isArray(u.output)?l=u.output.map(x=>{let k=x.content;return k&&Array.isArray(k)?k.map(O=>O.text).filter(O=>typeof O=="string").join(" "):""}).filter(x=>typeof x=="string"&&x.length>0).join(" "):u?.choices&&Array.isArray(u.choices)&&(l=u.choices.map(x=>{let P=x,k=P.message;return P.finish_reason&&(d=String(P.finish_reason)),k?.content}).filter(x=>typeof x=="string").join(" "));let m=[],p="";t?.messages?(m=t.messages.map(x=>({role:x.role,content:x.content})),p=m.map(x=>`${x.role}: ${x.content}`).join(`
|
|
336
336
|
`)):t?.input&&(typeof t.input=="string"?(p=t.input,m=[{role:"user",content:t.input}]):Array.isArray(t.input)&&(m=t.input.filter(x=>typeof x.content=="string").map(x=>({role:x.role||"user",content:x.content})),p=m.map(x=>`${x.role}: ${x.content}`).join(`
|
|
337
337
|
`)));let f={type:"llm",input:m,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},y={type:"workflow",input:p,output:l,name:"AI Gateway Workflow",created_at:r,user_metadata:{request_id:n.requestId},tags:["ai-gateway"],spans:[f]},v={type:"trace",input:m.find(x=>x.role==="user")?.content||p,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:NR(r)},spans:[y]},w={log_stream_id:o.logStreamId,traces:[v]};try{let x={"Content-Type":"application/json","Galileo-API-Key":o.apiKey},P=await N.fetch(`${i}/projects/${o.projectId}/traces`,{method:"POST",headers:x,body:JSON.stringify(w)});if(P.ok)Rg("Successfully sent Galileo trace");else{let k=await P.text();n.log.error("Failed to send Galileo trace",{status:P.status,error:k}),Rg("Failed to send Galileo trace:",P.status,k)}}catch(x){n.log.error(x,"Error sending Galileo trace"),Rg("Error sending Galileo trace:",x)}}s(MR,"sendTrace");async function EA(t,e,r,n){I("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,m=!1;try{l=await t.clone().json(),m=l?.stream===!0,l?.messages?d={messages:l.messages,model:u||l.model,temperature:l.temperature,max_tokens:l.max_tokens}:l?.input&&(d={input:l.input,model:u||l.model,temperature:l.temperature})}catch{e.log.error("Could not parse request body for Galileo tracing")}if(d){let f={traceStartTime:new Date().toISOString(),input:d};kA(e,f),e.addResponseSendingFinalHook(async y=>{let v=CA(e);if(v)if(m&&y.body){let w=y.clone(),x=!!l?.input,P=LR(e,v,a,MR,x);w.body&&e.waitUntil(w.body.pipeThrough(P).pipeTo(new WritableStream({write(){},close(){},abort(k){e.log.error("Galileo streaming accumulation aborted",{error:k})}})).catch(k=>{e.log.error("Error in Galileo streaming accumulation",{error:k})}))}else{let w;try{w=await y.clone().json()}catch{e.log.error("Could not parse response body for Galileo tracing")}e.waitUntil(MR(v.input,w,v.traceStartTime,e,a))}})}return t}s(EA,"GalileoTracingInboundPolicy");var Un="__unknown__",_A=s(async(t,e,r,n)=>{I("policy.inbound.geo-filter");let o={allow:{countries:zn(r.allow?.countries,"allow.countries",n),regionCodes:zn(r.allow?.regionCodes,"allow.regionCode",n),asns:zn(r.allow?.asns,"allow.asOrganization",n)},block:{countries:zn(r.block?.countries,"block.countries",n),regionCodes:zn(r.block?.regionCodes,"block.regionCode",n),asns:zn(r.block?.asns,"block.asOrganization",n)},ignoreUnknown:r.ignoreUnknown!==!1},i=e.incomingRequestProperties.country?.toLowerCase()??Un,a=e.incomingRequestProperties.regionCode?.toLowerCase()??Un,c=e.incomingRequestProperties.asn?.toString()??Un,u=o.ignoreUnknown&&i===Un,l=o.ignoreUnknown&&a===Un,d=o.ignoreUnknown&&c===Un,m=o.allow.countries,p=o.allow.regionCodes,f=o.allow.asns;if(m.length>0&&!m.includes(i)&&!u||p.length>0&&!p.includes(a)&&!l||f.length>0&&!f.includes(c)&&!d)return Dn(t,e,n,i,a,c);let y=o.block.countries,v=o.block.regionCodes,w=o.block.asns;return y.length>0&&y.includes(i)&&!u||v.length>0&&v.includes(a)&&!l||w.length>0&&w.includes(c)&&!d?Dn(t,e,n,i,a,c):t},"GeoFilterInboundPolicy");function Dn(t,e,r,n,o,i){return e.log.debug(`Request blocked by GeoFilterInboundPolicy '${r}' (country: '${n}', regionCode: '${o}', asn: '${i}')`),U.forbidden(t,e,{geographicContext:{country:n,regionCode:o,asn:i}})}s(Dn,"blockedResponse");function zn(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 R(`Invalid '${e}' for GeoFilterInboundPolicy '${r}': '${t}', must be a string or string[]`)}s(zn,"toLowerStringArray");var OA=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;function DR(t,e,r){if(!OA.test(t))throw new R(`HttpDeprecationOutboundPolicy '${r}' ${e} '${t}' is not a valid ISO 8601 date string with a timezone offset (e.g. '2024-12-31T23:59:59Z')`);let n=new Date(t);if(Number.isNaN(n.getTime()))throw new R(`HttpDeprecationOutboundPolicy '${r}' ${e} '${t}' is not a valid date`);return n}s(DR,"parseISODateString");var $A=s(async(t,e,r,n,o)=>{if(I("policy.outbound.http-deprecation"),n.deprecation===void 0||n.deprecation===null)throw new R(`HttpDeprecationOutboundPolicy '${o}' requires the 'deprecation' option to be set`);let i=new Headers(t.headers),a=n.deprecation;if(a===!0)i.set("Deprecation","true");else if(typeof a=="number"){if(!Number.isFinite(a)||a<0)throw new R(`HttpDeprecationOutboundPolicy '${o}' deprecation timestamp must be a non-negative, finite number`);i.set("Deprecation",`@${Math.floor(a)}`)}else if(typeof a=="string"){let c=DR(a,"deprecation date string",o);i.set("Deprecation",c.toUTCString())}else throw new R(`HttpDeprecationOutboundPolicy '${o}' deprecation must be true, an ISO 8601 date string, or a Unix timestamp number`);if(n.sunset!==void 0&&n.sunset!==null){if(typeof n.sunset!="string")throw new R(`HttpDeprecationOutboundPolicy '${o}' sunset must be a string`);let c=DR(n.sunset,"sunset date string",o);i.set("Sunset",c.toUTCString())}if(n.link!==void 0){let c;try{c=new URL(n.link)}catch{throw new R(`HttpDeprecationOutboundPolicy '${o}' link '${n.link}' is not a valid URL`)}i.set("Link",`<${c.href}>; rel="deprecation"; type="text/html"`)}return new Response(t.body,{headers:i,status:t.status,statusText:t.statusText})},"HttpDeprecationOutboundPolicy");var AA=s(async(t,e,r)=>{I("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 LA=s(async(t,e,r,n)=>{I("policy.inbound.mock-api");let o=e.route.raw().responses;if(!o)return Pg(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 Pg(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],m=d.examples,p=d.example;m?Object.keys(m).forEach(y=>{a.push({responseName:c,contentName:l,exampleName:y,exampleValue:m[y]})}):p!==void 0&&a.push({responseName:c,contentName:l,exampleName:"example",exampleValue:p})})}),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 zR(a[c])}else return a.length>0?zR(a[0]):Pg(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 zR(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(zR,"generateResponse");var Pg=s((t,e,r,n)=>{let o=`Error in policy: ${t} - On route ${e.method} ${r.route.path}. ${n}`;return U.internalServerError(e,r,{detail:o})},"getProblemDetailResponse");var NA="Incoming",MA={logRequestBody:!0,logResponseBody:!0};function jR(t){let e={};return t.forEach((r,n)=>{e[n]=r}),e}s(jR,"headersToObject");function ZR(){return new Date().toISOString()}s(ZR,"timestamp");var Ig=new WeakMap,UA={};function DA(t,e){let r=Ig.get(t);r||(r=UA);let n=Object.assign({...r},e);Ig.set(t,n)}s(DA,"setMoesifContext");async function qR(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(qR,"readBody");var zA={},Sg;function FR(){if(!Sg)throw new q("Invalid State - no _lastLogger");return Sg}s(FR,"getLastLogger");function jA(t){let e=zA[t];return e||(e=new ae("moesif-inbound",100,async r=>{let n=JSON.stringify(r);FR().debug("posting",n);let o=await N.fetch("https://api.moesif.net/v1/events/batch",{method:"POST",headers:{"content-type":"application/json","X-Moesif-Application-Id":t},body:n});o.ok||FR().error({status:o.status,body:await o.text()})})),e}s(jA,"getDispatcher");async function ZA(t,e,r,n){I("policy.inbound.moesif-analytics"),Sg=e.log;let o=ZR(),i=Object.assign(MA,r);if(!i.applicationId)throw new R(`Invalid configuration for MoesifInboundPolicy '${n}' - applicationId is required`);let a=i.logRequestBody?await qR(t,e):void 0;return e.addResponseSendingFinalHook(async(c,u)=>{let l=jA(i.applicationId),d=vt(t),m=Ig.get(e)??{},p={time:o,uri:t.url,verb:t.method,body:a,ip_address:d??void 0,api_version:m.apiVersion,headers:jR(t.headers)},f=i.logResponseBody?await qR(c,e):void 0,y={time:ZR(),status:c.status,headers:jR(c.headers),body:f},v={request:p,response:y,user_id:m.userId??u.user?.sub,session_token:m.sessionToken,company_id:m.companyId,metadata:m.metadata,direction:NA};l.enqueue(v),e.waitUntil(l.waitUntilFlushed())}),t}s(ZA,"MoesifInboundPolicy");function HR(t,e){if(e==="")return t;let r=t.trim(),n=e.toLowerCase();if(!r.toLowerCase().startsWith(n))throw new Error(`Invalid authorization header format. Expected "${e} <token>"`);let i=r.slice(e.length);if(!i||i.trim()==="")throw new Error(`API Key is misconfigured for use in this API. Expected "${e} <token>"`);let a=i[0];if(a!==" "&&a!==" ")throw new Error(`Invalid authorization header format. Expected "${e} <token>"`);let c=i.trim();if(!c)throw new Error(`API Key is misconfigured for use in this API. Expected "${e} <token>"`);return c}s(HR,"getKeyValue");async function GR(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(GR,"hashValue");var Tg=60;function BR(t){let{options:e,policyName:r,bucketId:n}=t;if(e.meterOnStatusCodes!==void 0&&typeof e.meterOnStatusCodes!="string"&&!Array.isArray(e.meterOnStatusCodes))throw new R(`Invalid MonetizationInboundPolicy '${r}': options.meterOnStatusCodes must be a string or array. Received type ${typeof e.meterOnStatusCodes}.`);if(Array.isArray(e.meterOnStatusCodes)){for(let i of e.meterOnStatusCodes)if(typeof i!="number"||!Number.isFinite(i))throw new R(`Invalid MonetizationInboundPolicy '${r}': options.meterOnStatusCodes must be an array of finite numbers. Received ${JSON.stringify(i)}.`)}if(e.cacheTtlSeconds!==void 0&&e.cacheTtlSeconds<Tg)throw new R(`MonetizationInboundPolicy '${r}' - minimum cacheTtlSeconds value is ${Tg}s, '${e.cacheTtlSeconds}' is invalid`);if(!n)throw new R("ZUPLO_SERVICE_BUCKET_ID env not configured");let o=qA(e.meters,r);return{bucketId:n,authHeader:e.authHeader??"authorization",authScheme:e.authScheme??"Bearer",cacheTtlSeconds:e.cacheTtlSeconds??Tg,meterOnStatusCodes:Dt(e.meterOnStatusCodes??"200-299"),staticMeters:o}}s(BR,"validateAndParseOptions");function qA(t,e){if(t===void 0)return;if(typeof t!="object"||t===null)throw new R(`Invalid MonetizationInboundPolicy '${e}': options.meters must be an object. Received type ${typeof t}.`);let r=Object.entries(t);if(r.length===0)throw new R(`Invalid MonetizationInboundPolicy '${e}': options.meters must contain at least one meter.`);for(let[n,o]of r)if(typeof o!="number"||o<=0||!Number.isFinite(o))throw new R(`Invalid MonetizationInboundPolicy '${e}': options.meters["${n}"] must be a positive number. Received ${o}.`);return t}s(qA,"validateStaticMeters");function Qa(t){if(!t||typeof t!="object"||Array.isArray(t))throw new q("MonetizationInboundPolicy - meters must be a valid object");let e=Object.entries(t);if(e.length===0)throw new q("MonetizationInboundPolicy - meters must contain at least one meter");for(let[r,n]of e)if(typeof n!="number"||n<=0||!Number.isFinite(n))throw new q(`MonetizationInboundPolicy - invalid quantity for meter '${r}'. Expected a positive number, received ${n}.`);return t}s(Qa,"validateRuntimeMeters");function VR(t,e,r=!1){let n={};if(t)for(let[o,i]of Object.entries(t))n[o]=i;for(let[o,i]of Object.entries(e)){if(r&&n[o]!==void 0){n[o]=i;continue}n[o]=(n[o]??0)+i}return n}s(VR,"mergeMeters");function Ya(t,e){if(!t.entitlements)return{detail:"Subscription entitlements are not available."};for(let[r]of Object.entries(e)){let n=t.entitlements[r];if(!n)return{detail:`API Key does not have "${r}" meter provided by the subscription.`};if(!n.hasAccess){let o=`API Key does not have access to "${r}" meter.`;return n.balance<=0&&(o=`API Key has exceeded the allowed limit for "${r}" meter.`),{detail:o}}}}s(Ya,"validateEntitlements");var JR="monetization-key-cache-type",FA=1e3*60*60*24,WR=Symbol("monetization-subscription-context-data"),Xa=Symbol("monetization-meter-context-data"),KR=Symbol("monetization-meter-override-context-data"),kg=class t extends Ie{static{s(this,"MonetizationInboundPolicy")}#e;static setSubscriptionData(e,r){de.set(e,WR,r)}static getSubscriptionData(e){return de.get(e,WR)}static setMeters(e,r){de.set(e,Xa,Qa(r)),de.set(e,KR,!0)}static addMeters(e,r){let n=Qa(r),o=de.get(e,Xa)??{};for(let[i,a]of Object.entries(n))o[i]=(o[i]??0)+a;de.set(e,Xa,o)}static#t(e){return de.get(e,KR)??!1}static getMeters(e){return de.get(e,Xa)??{}}constructor(e,r){super(e,r),I("policy.inbound.monetization"),this.#e=BR({options:this.options,policyName:this.policyName,bucketId:Fe.ZUPLO_SERVICE_BUCKET_ID})}async handler(e,r){let n=e.headers.get(this.#e.authHeader);if(!n)return U.forbidden(e,r,{detail:"No Authorization Header"});if(!n.toLowerCase().startsWith(this.#e.authScheme.toLowerCase()))return U.forbidden(e,r,{detail:"Invalid Authorization Scheme"});let o=HR(n,this.#e.authScheme);if(!o||o==="")return U.forbidden(e,r,{detail:"No key present"});let i=await GR(o),a=await ve(this.policyName,void 0,this.options),c=new be(a,r),u=await c.get(i);if(u?.isValid===!0&&u.user&&u.subscription){e.user=u.user,t.setSubscriptionData(r,u.subscription);let x=this.#e.staticMeters;if(x){let P=Ya(u.subscription,x);if(P)return U.forbidden(e,r,{detail:P.detail})}return this.#n(r,u.subscription),e}if(u&&!u.isValid)return u.typeId!==JR&&J.getLogger(r).error(`MonetizationInboundPolicy '${this.policyName}' - cached metadata has invalid typeId '${u.typeId}'`,u),U.forbidden(e,r,{detail:"Authorization Failed"});let l=new Headers({"content-type":"application/json"});Le(l,r.requestId);let d=await He({retryDelayMs:5,retries:2,logger:J.getLogger(r)},`${S.instance.zuploEdgeApiUrl}/v3/metering/${this.#e.bucketId}/validate-api-key`,{method:"POST",headers:l,body:JSON.stringify({apiKey:o})});if(d.status===401)return r.log.info(`MonetizationInboundPolicy '${this.policyName}' - 401 response from Gateway Service`),U.forbidden(e,r,{detail:"Authorization Failed"});if(d.status!==200){try{let x=await d.text(),P=JSON.parse(x);r.log.error("Unexpected response from key service",P)}catch{r.log.error("Invalid response from key service")}throw new q(`MonetizationInboundPolicy '${this.policyName}' - unexpected response from Gateway Service. Status: ${d.status}`)}let m=await d.json();if(!m||!m.subscription)return U.forbidden(e,r,{detail:"API Key is invalid or does not have access to the API"});if(m.expiresOn&&new Date>new Date(m.expiresOn))return U.forbidden(e,r,{detail:"API Key has expired."});let p=m.subscription;if(p.activeTo&&new Date>new Date(p.activeTo))return r.log.info(`API Key has an expired subscription with status ${p.status} and end date ${p.activeTo}`),U.forbidden(e,r,{detail:"API Key has an expired subscription."});if(!p.paymentStatus)return r.log.error("Subscription payment status is not available"),U.forbidden(e,r,{detail:"Subscription payment status is not available."});let y=p.paymentStatus.status==="not_required";if(p.paymentStatus.isFirstPayment&&!y&&p.paymentStatus.status!=="paid")return r.log.info(`API Key has a first payment and payment is required but payment has not been made. Payment status: ${p.paymentStatus.status}`),U.forbidden(e,r,{detail:"Payment has not been made."});if(!p.paymentStatus.isFirstPayment&&!y&&p.paymentStatus.status!=="paid"&&(r.log.info(`API Key payment is required but payment has not been made. Payment status: ${p.paymentStatus.status}`),p.paymentStatus.lastPaymentFailedAt)){let x=new Date(p.paymentStatus.lastPaymentFailedAt),P=(Date.now()-x.getTime())/FA;if(P>=p.maxPaymentOverdueDays)return r.log.info({daysSincePaymentFailure:Math.floor(P),maxPaymentOverdueDays:p.maxPaymentOverdueDays},"Blocking request: payment has been overdue beyond the grace period"),U.forbidden(e,r,{detail:"Payment is overdue. Please update your payment method."})}let v=this.#e.staticMeters;if(v){let x=Ya(p,v);if(x)return U.forbidden(e,r,{detail:x.detail})}let w={apiKeyId:m.id,sub:m.consumer.name,data:m.consumer.metadata};return e.user=w,t.setSubscriptionData(r,p),c.put(i,{isValid:!0,typeId:JR,user:w,subscription:p},this.#e.cacheTtlSeconds),this.#n(r,p),e}#n(e,r){e.addResponseSendingFinalHook(async n=>{try{if(!this.#e.meterOnStatusCodes.includes(n.status))return;let o=VR(this.#e.staticMeters,t.getMeters(e),t.#t(e));if(Object.keys(o).length===0)return;Qa(o);let i=Ya(r,o);if(i){e.log.error(`MonetizationInboundPolicy '${this.policyName}' - ${i.detail}`);return}let a=[];e.log.debug(`MonetizationInboundPolicy '${this.policyName}' - sending usage data for status code ${n.status}`);for(let[c,u]of Object.entries(o))a.push({type:c,id:crypto.randomUUID(),specversion:"1.0",source:"monetization-policy",subject:r.id,data:{total:u},subscription:r.id});e.waitUntil(ln.instance.sendUsageEvent(this.#e.bucketId,a,e).catch(c=>{e.log.error(c,`MonetizationInboundPolicy '${this.policyName}' - failed to send usage event`)}))}catch(o){e.log.error(o,`MonetizationInboundPolicy '${this.policyName}' - failed to send usage event`)}})}};async function ec(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 He({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 q("Error getting token from identity provider.")}let o=await n.json();if(o&&typeof o=="object"&&"access_token"in o&&typeof o.access_token=="string"&&"expires_in"in o&&typeof o.expires_in=="number")return{access_token:o.access_token,expires_in:o.expires_in};throw new q("Response returned from identity provider is not in the expected format.")}s(ec,"getClientCredentialsAccessToken");var jn=class extends Error{constructor(r,n,o){super(n,o);this.code=r}static{s(this,"OpenFGAError")}},tc=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 R("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",S.instance.systemUserAgent);let a=`${this.apiUrl}${e}`,c=new Request(a,{method:r,headers:i,body:o?JSON.stringify(o):void 0}),u=await N.fetch(c);if(u.status!==200){let l;try{l=await u.json()}catch{}throw!l||!l.code||!l.message?new jn("unknown",`Unknown error. Status: ${u.status}`):new jn(l.code,l.message)}return u.json()}};function wi(t,e,r){!t[e]&&r&&(t[e]=r)}s(wi,"setHeaderIfNotSet");var QR="X-OpenFGA-Client-Method",YR="X-OpenFGA-Client-Bulk-Request-Id",vi=class extends tc{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 wi(n,QR,"BatchCheck"),wi(n,YR,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 jn)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(wi(u,QR,"ListRelations"),wi(u,YR,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(m=>({user:n,relation:m,object:o,contextualTuples:a,context:c})),Object.assign({},r,u)),d=l.responses.find(m=>m.error);if(d)throw d.error;return{relations:l.responses.filter(m=>m.allowed).map(m=>m._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 XR=Symbol("openfga-authz-context-data"),Zn=class extends Ie{static{s(this,"BaseOpenFGAAuthZInboundPolicy")}client;authorizer;cache;static setContextChecks(e,r){let n=Array.isArray(r)?r:[r];de.set(e,XR,n)}constructor(e,r){if(super(e,r),pe(e,r).required("apiUrl","string").optional("storeId","string").optional("authorizationModelId","string"),!e.credentials)throw new R(`${this.policyType} '${this.policyName}' - The 'credentials' option is required.`);if(e.credentials.method==="client-credentials")pe(e.credentials,r).required("clientId","string").required("clientSecret","string").required("oauthTokenEndpointUrl","string").optional("apiAudience","string");else if(e.credentials.method==="api-token")pe(e.credentials,r).required("token","string").optional("headerName","string").optional("headerValuePrefix","string");else if(e.credentials.method==="header")pe(e.credentials,r).optional("headerName","string");else if(e.credentials.method!=="none")throw new R(`${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 vi({apiUrl:e.apiUrl,storeId:e.storeId,authorizationModelId:e.authorizationModelId})}async handler(e,r){if(!this.cache){let a=await ve(this.policyName,void 0,this.options);this.cache=new be(a,r)}let n=s(a=>this.options.allowUnauthorizedRequests?e:U.forbidden(e,r,{detail:a}),"forbiddenResponse"),o=de.get(r,XR);if(!o||o.length===0)throw new q(`${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),U.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 ge(`${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 ec({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 q("Invalid state for credentials method is not valid. This should not happen.")}};var eP=["us1","eu1","au1"],Cg=class extends Zn{static{s(this,"OktaFGAAuthZInboundPolicy")}constructor(e,r){if(!eP.includes(e.region))throw new R(`OktaFGAAuthZInboundPolicy '${r}' - The 'region' option is invalid. Must be one of ${eP.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),I("policy.inbound.oktafga-authz")}};var HA=s(async(t,e,r,n)=>(I("policy.inbound.okta-jwt-auth"),it(t,e,{issuer:r.issuerUrl,audience:r.audience,jwkUrl:`${r.issuerUrl}/v1/keys`,allowUnauthenticatedRequests:r.allowUnauthenticatedRequests,oAuthResourceMetadataEnabled:r.oAuthResourceMetadataEnabled},n)),"OktaJwtInboundPolicy");var Eg=class extends Zn{static{s(this,"OpenFGAAuthZInboundPolicy")}constructor(e,r){super(e,r),I("policy.inbound.openfga-authz")}};var tP={},_g=Symbol("openmeter-meters"),Og=class extends Ie{static{s(this,"OpenMeterInboundPolicy")}#e;#t;#n;#r;#o;#i;constructor(e,r){if(super(e,r),I("policy.inbound.openmeter-metering"),pe(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 R(`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 R(`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 R(`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=Dt(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}'.`),U.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 q(`OpenMeterInboundPolicy '${this.policyName}' requires a user to be authenticated. Ensure you have an authentication policy set before this policy?`);return Wt(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 N.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=de.get(r,_g)??(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=tP[l];d||(d=new ae("openmeter-ingest-event",10,async m=>{try{let p=await N.fetch(this.#r,{method:"POST",body:JSON.stringify(m),headers:this.#e});if(p.status!==204){let f=await p.text().catch(()=>"");r.log.error(`Unexpected response in OpenMeterInboundPolicy '${this.policyName}'. ${p.status}`,f)}}catch(p){let f=p instanceof Error?p.message:String(p);throw r.log.error(`Error in OpenMeterInboundPolicy '${this.policyName}': ${f}`),p}}),tP[l]=d),d.enqueue(u),r.waitUntil(d.waitUntilFlushed())}}})}static setMeters(e,r){let n=de.get(e,_g)||[];de.set(e,_g,[...n,...Array.isArray(r)?r:[r]])}};var GA=s(async(t,e,r,n)=>{I("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.
|
|
338
338
|
|