@astrasyncai/adapter-lambda 2.5.0 → 2.7.0

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/INSTALL.md ADDED
@@ -0,0 +1,106 @@
1
+ # Install the AstraSync Trusted Agent Gateway (CloudFront)
2
+
3
+ Customer-facing install guide: put the Trusted Agent Gateway in front of an
4
+ existing website or API on AWS, with **zero code changes and zero local
5
+ build**. Observe-only by default — the gateway classifies and records
6
+ inbound AI-agent traffic for your Visit Intelligence dashboard; it blocks
7
+ nothing until you opt specific paths into enforce mode from the dashboard.
8
+
9
+ Two ways to install:
10
+
11
+ - **A. Quick launch (recommended)** — deploy AstraSync's versioned
12
+ CloudFormation template straight from S3. No tooling beyond the AWS
13
+ console.
14
+ - **B. From this npm package** — build and deploy with SAM yourself
15
+ (see `infra/RUNBOOK.md` for the operator-grade version).
16
+
17
+ ## Prerequisites (one-time, ~15 minutes)
18
+
19
+ 1. **An AstraSync account and a registered endpoint.** In the dashboard
20
+ (Endpoints → Add), register your site's public URL. Note the endpoint id
21
+ (`ASTRAE-…`) and mint a merchant API key (`kya_live_…`).
22
+ 2. **AWS account, us-east-1.** Lambda@Edge deploys from us-east-1 only.
23
+ 3. **ACM certificate** for your site domain, in **us-east-1** (CloudFront
24
+ requirement):
25
+ ```bash
26
+ aws acm request-certificate --domain-name www.example.com \
27
+ --validation-method DNS --region us-east-1
28
+ ```
29
+ Add the validation CNAME at your DNS host; note the certificate ARN.
30
+ 4. **API key secret** in Secrets Manager (us-east-1):
31
+ ```bash
32
+ aws secretsmanager create-secret --region us-east-1 \
33
+ --name astrasync/edge/www-example-com \
34
+ --secret-string 'kya_live_…'
35
+ ```
36
+ Rotation later is `put-secret-value` — the edge picks it up within
37
+ 15 minutes, no redeploy.
38
+ 5. **A direct origin hostname.** CloudFront's origin cannot be the same
39
+ hostname it serves (that's a loop). Use a hostname that reaches your
40
+ existing hosting directly — a dedicated DNS record to your server, or
41
+ your PaaS-issued domain (e.g. `<service>.up.railway.app`,
42
+ `<app>.herokuapp.com`). Your site still receives the original hostname
43
+ via `X-Forwarded-Host`.
44
+
45
+ ## A. Quick launch
46
+
47
+ 1. Open the launch URL for the release you were given (or construct it —
48
+ `<VERSION>` like `2.7.0`):
49
+
50
+ ```
51
+ https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/create/review?templateURL=https://astrasync-releases.s3.amazonaws.com/tag-cloudfront/v<VERSION>/template.yaml
52
+ ```
53
+
54
+ 2. Fill the parameters:
55
+
56
+ | Parameter | Value |
57
+ | ------------------- | --------------------------------------------------------------------- |
58
+ | `OriginDomainName` | Direct origin hostname (prereq 5) |
59
+ | `SiteDomainName` | Your public site domain |
60
+ | `AcmCertificateArn` | From prereq 3 |
61
+ | `ApiKeySecretName` | From prereq 4 |
62
+ | `CounterpartyId` | Your `ASTRAE-…` endpoint id |
63
+ | `CounterpartyUrl` | Leave blank (defaults to `https://<SiteDomainName>`) |
64
+ | `ApiBaseUrl` | Leave default unless AstraSync gave you an environment-specific value |
65
+ | `PublicBaseUrl` | Leave blank unless instructed |
66
+
67
+ Per-deploy configuration travels as CloudFront **origin custom headers**
68
+ — the Lambda bundle is identical for every customer and never needs a
69
+ rebuild.
70
+
71
+ 3. Create the stack (acknowledge IAM capabilities). First deploy takes
72
+ ~15–25 minutes (CloudFront distribution creation).
73
+
74
+ 4. **Cut over DNS**: point your site domain (ALIAS/CNAME) at the
75
+ `DistributionDomainName` stack output. Roll back at any time by
76
+ pointing DNS back at the old target — the gateway holds no state.
77
+
78
+ 5. **Verify**: browse the site (unchanged behaviour), then check the
79
+ Visit Intelligence live feed in your AstraSync dashboard — traffic
80
+ events should appear within a minute or two.
81
+
82
+ ## B. From the npm package
83
+
84
+ ```bash
85
+ npm install @astrasyncai/adapter-lambda
86
+ ```
87
+
88
+ The package ships `infra/template.yaml`, `infra/deploy.sh`, and
89
+ `infra/RUNBOOK.md`. Set the `ASTRASYNC_*` / stack environment variables and
90
+ run `infra/deploy.sh` (requires `aws` + `sam` CLIs). See `infra/RUNBOOK.md`
91
+ for the full operator runbook including smoke tests and rollback.
92
+
93
+ ## Safety properties
94
+
95
+ - **Fail-open, always**: if the AstraSync backend is unreachable — or the
96
+ gateway itself errors — requests pass straight through to your origin.
97
+ Enforce mode degrades to observe after 24h of stale config.
98
+ - **Observe-only by default**: nothing is blocked until you flip specific
99
+ paths to enforce in the dashboard.
100
+ - **No secrets in the bundle**: your API key lives in your Secrets
101
+ Manager; the edge reads it with a narrowly-scoped IAM role.
102
+
103
+ ## Support
104
+
105
+ - Dashboard & docs: https://astrasync.ai
106
+ - Issues with the adapter: https://github.com/AstraSync-KYA/KYA-Platform
@@ -1 +1 @@
1
- "use strict";var Ae=Object.create;var R=Object.defineProperty;var we=Object.getOwnPropertyDescriptor;var be=Object.getOwnPropertyNames;var Re=Object.getPrototypeOf,Se=Object.prototype.hasOwnProperty;var Ie=(e,t)=>{for(var r in t)R(e,r,{get:t[r],enumerable:!0})},N=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of be(t))!Se.call(e,a)&&a!==r&&R(e,a,{get:()=>t[a],enumerable:!(n=we(t,a))||n.enumerable});return e};var Ee=(e,t,r)=>(r=e!=null?Ae(Re(e)):{},N(t||!e||!e.__esModule?R(r,"default",{value:e,enumerable:!0}):r,e)),Ce=e=>N(R({},"__esModule",{value:!0}),e);var Jt={};Ie(Jt,{handler:()=>Yt});module.exports=Ce(Jt);var W="5.0.0",S=`astrasync-sdk/${W}`;function Te(e){if(!e)return{"user-agent":S};if(e instanceof Headers){let r=new Headers(e);return r.has("user-agent")||r.set("user-agent",S),r}return Array.isArray(e)?e.some(([n])=>n.toLowerCase()==="user-agent")?e:[...e,["user-agent",S]]:Object.keys(e).some(r=>r.toLowerCase()==="user-agent")?e:{"user-agent":S,...e}}var E=(e,t)=>fetch(e,{...t,headers:Te(t?.headers)}),Zt=Object.freeze({version:1,mode:"observe",depth:"classify",pathRules:[],sampling:Object.freeze({anonymousBeaconRate:.1}),failurePosture:"open"}),Qt=60*1e3,qt=1440*60*1e3;function Pe(e,t){for(let r of e)if(Ue(r.pattern).test(t))return r}function Ue(e){let t=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${t}$`,"i")}var _e=1,xe=new Set(["cookie","set-cookie","x-csrf-token","proxy-authorization","x-astrasync-signature","x-astrasync-secret","x-hub-signature","x-hub-signature-256","x-astra-verified-hop"]),ke=["x-astrasync-","kya-","kya_"],Oe=new Set(["authorization","x-api-key","x-goog-api-key","api-key"]);function Me(e){return e==="signature"||e.endsWith("-signature")||e.endsWith("-signature-256")}var Fe=new Set(["openai-organization","openai-project","openai-version","openai-processing-ms","anthropic-version","anthropic-beta","x-goog-user-project","x-goog-api-client","user-agent","x-agent-card-url","x-agent-provider"]),De=["x-goog-","x-stainless-","x-anthropic-","x-openai-","sec-ch-"],Ne=["sk-ant-api03","sk-ant-api","sk-ant","sk-proj","sk-svcacct","sk-or-v1","sk-or","sk-lf","sk-","gsk_","aiza","ya29","ghp_","gho_","github_pat_","xai-","pplx-","r8_","hf_","astra-","astrae-"],$e=64,$=1024,je=16*1024;function U(e){let t=0;for(let r=0;r<e.length;r++){let n=e.charCodeAt(r);n<128?t+=1:n<2048?t+=2:n>=55296&&n<=56319?(t+=4,r++):t+=3}return t}function He(e){if(!e)return;let t=e.trim(),r=t.indexOf(" ");if(r>0){let a=t.slice(0,r).toLowerCase();(a==="bearer"||a==="basic"||a==="token")&&(t=t.slice(r+1).trim())}let n=t.toLowerCase();for(let a of Ne)if(n.startsWith(a))return a}function Le(e){return!!(xe.has(e)||ke.some(t=>e.startsWith(t))||Me(e))}function Be(e){return Fe.has(e)?!0:De.some(t=>e.startsWith(t))}function Z(e){let t={},r={},n,a,i=0,o=0;if(!e)return{headers:t};for(let c of Object.keys(e)){if(o>=$e)break;let p=c.toLowerCase(),u=e[c];if(u===void 0)continue;let y=Array.isArray(u)?u.join(", "):String(u);if(Oe.has(p)){let f=He(y);f&&!n&&(n=f);continue}if(p==="cookie"&&(a=y.split(";").filter(f=>f.trim().length>0).length),Le(p))continue;let m=y;U(m)>$&&(m=m.slice(0,$));let l=U(p)+U(m);i+l>je||(i+=l,o++,t[p]=m,Be(p)&&(r[p]=m))}let s={headers:t};return n&&(s.apiKeyFormat=n),Object.keys(r).length>0&&(s.platformHeaders=r),a!==void 0&&(s.cookieCount=a),s}var Ke=[{vendor:"claude",displayName:"Anthropic Claude",uaPatterns:[/claude/i,/anthropic/i],agentCardPatterns:[/anthropic\.com/i,/claude\.ai/i],apiKeyFormatPatterns:[/^sk-ant/i],headerPatterns:[/^anthropic-version/i,/^anthropic-beta/i,/^x-anthropic-/i]},{vendor:"chatgpt",displayName:"OpenAI ChatGPT",uaPatterns:[/chatgpt/i,/openai/i,/gpt-?\d/i],agentCardPatterns:[/openai\.com/i,/chatgpt\.com/i],apiKeyFormatPatterns:[/^sk-proj/i,/^sk-svcacct/i],headerPatterns:[/^openai-organization/i,/^openai-project/i,/^openai-version/i]},{vendor:"gemini",displayName:"Google Gemini",uaPatterns:[/gemini/i,/google-gemini/i,/bard/i],agentCardPatterns:[/gemini\.google\.com/i,/ai\.google\.dev/i],apiKeyFormatPatterns:[/^aiza/i],headerPatterns:[/^x-goog-user-project/i,/^x-goog-api-client/i]},{vendor:"cursor",displayName:"Cursor",uaPatterns:[/cursor/i],agentCardPatterns:[/cursor\.sh/i,/cursor\.com/i]},{vendor:"goose",displayName:"Block Goose",uaPatterns:[/goose/i,/block-goose/i],agentCardPatterns:[/block\.xyz\/goose/i,/goose\.tools/i]},{vendor:"perplexity",displayName:"Perplexity",uaPatterns:[/perplexity/i],agentCardPatterns:[/perplexity\.ai/i],apiKeyFormatPatterns:[/^pplx-/i]},{vendor:"chatgpt-atlas",displayName:"ChatGPT Atlas browser",uaPatterns:[/\batlas\/\d/i],headerPatterns:[/^sec-ch-ua: .*atlas/i]},{vendor:"perplexity-comet",displayName:"Perplexity Comet browser",uaPatterns:[/\bcomet\/\d/i],headerPatterns:[/^sec-ch-ua: .*comet/i]},{vendor:"astrasync-sdk",displayName:"AstraSync SDK",uaPatterns:[/^astrasync-sdk\//i]}];function Ve(e,t){let r=t.userAgent??"",n=t.agentCardUrl??"",a=t.apiKeyFormat??"",i=t.ja4??"",o=t.asn??"",s=[];if(t.platformHeaders)for(let[c,p]of Object.entries(t.platformHeaders))s.push(c,`${c}: ${p}`);for(let c of e){let p=c.uaPatterns?.some(d=>d.test(r)),u=c.agentCardPatterns?.some(d=>d.test(n)),y=a.length>0&&c.apiKeyFormatPatterns?.some(d=>d.test(a)),m=s.length>0&&c.headerPatterns?.some(d=>s.some(h=>d.test(h))),l=i.length>0&&c.ja4Patterns?.some(d=>d.test(i)),f=o.length>0&&c.asnList?.includes(o);if(p||u||y||m||l||f){let d=r.split(/[\s/]/)[0]?.toLowerCase()??"",h=(()=>{try{return n?new URL(n).host:""}catch{return""}})(),P=d||h||a||i||o&&`asn${o}`||"unknown";return{vendor:c.vendor,fingerprintKey:`${c.vendor}:${P}`,displayName:c.displayName}}}}function j(e){return Ve(Ke,e)}function ze(e){return e>=80?"PLATINUM":e>=60?"GOLD":e>=40?"SILVER":"BRONZE"}var er=3600*1e3,Ge=new Map;function Xe(e){return Ge.get(e)?.data}var Q={apiBaseUrl:"https://astrasync.ai/api",debug:!1},q=!1,H=!1;async function L(e,t,r,n){q=!0;try{let a=`${e}/agents/verify-access`,o=(await E(a,{method:"HEAD"})).headers.get("content-type")??"";if(o.startsWith("text/html")){let s=`[VerificationGateway] apiBaseUrl '${e}' returned HTML (content-type: ${o}). This usually means apiBaseUrl is pointing at a marketing site instead of the API. Expected: 'https://astrasync.ai/api' (prod) or 'https://staging.astrasync.ai/api' (staging).`;if(r)throw new Error(`${s} (strictInit=true)`);console.warn(`${s} Set disableInitChecks: true on GatewayConfig to silence.`)}else t&&console.log(`[VerificationGateway] init check passed for ${e} (content-type: ${o})`);if(n){let s=await E(`${e}/agents/verify-access/self-check`,{headers:{Authorization:`Bearer ${n}`}});if(s.status===401){let c=await s.json().catch(()=>({})),p=`[VerificationGateway] the configured AstraSync API key was REJECTED at startup (${c.code??"api_key_invalid"}: ${c.message??"invalid key"}). Every inbound agent will be turned away until the key is rotated`+(c.remediation?.manageUrl?` at ${c.remediation.manageUrl}`:"")+".";if(r)throw new Error(`${p} (strictInit=true)`);console.error(p)}else if(s.ok){let c=await s.json().catch(()=>({}));typeof c.daysToExpiry=="number"&&c.daysToExpiry<=7?console.warn(`[VerificationGateway] the configured AstraSync API key expires in ${c.daysToExpiry} day(s) \u2014 rotate it at Settings \u2192 Developer Tools before integrations start failing.`):t&&console.log("[VerificationGateway] API key self-check passed")}}}catch(a){if(r)throw a;t&&console.log(`[VerificationGateway] init check failed (non-blocking): ${String(a)}`)}}var x=new Map;function ee(e,t){let r=e.credentials;return[r.astraId||"",r.apiKey||"",r.jwt||"",e.purpose||"",e.action||"",e.resourceType||"",e.resource||"",e.jurisdiction||"",e.transactionValue??"",e.currency||"",t||"",e.counterpartyUrl||"",e.counterpartyType||"",e.isSubAgentRequest?"1":"0",e.parentAgentId||"",e.subAgentDepth??"",e.durationRequired??"",e.invocationProtocol||"",e.enableRuntimeChallenge?"1":"0",e.callerMetadata?.sourceIp||"",e.callerMetadata?.userAgent||"",e.callerMetadata?.forwardedFor||"",e.callerMetadata?.agentCardUrl||""].join("|")}function Ye(e,t){let r=ee(e,t),n=x.get(r);return n&&n.expiresAt>Date.now()?n.result:(n&&x.delete(r),null)}var Je=60;function We(e,t,r,n){let a=r&&r>0?r:Je,i=ee(e,n);x.set(i,{result:t,expiresAt:Date.now()+a*1e3})}function te(e,t){let r={},n=/^ASTRAE?-[A-Za-z0-9_-]{1,64}$/,a=e["x-astra-id"]||e["X-Astra-Id"]||e["X-ASTRA-ID"]||e["x-astra-agentid"]||e["X-Astra-AgentId"]||e["x-astra-agent-id"]||e["X-Astra-Agent-Id"]||e["X-ASTRA-AGENT-ID"];if(a){let s=Array.isArray(a)?a[0]:typeof a=="string"?a:void 0;typeof s=="string"&&n.test(s)&&(r.astraId=s)}let i=e["x-api-key"]||e["X-Api-Key"]||e["X-API-KEY"];i&&(r.apiKey=Array.isArray(i)?i[0]:i);let o=e.authorization||e.Authorization;if(o){let s=Array.isArray(o)?o[0]:o;typeof s=="string"&&(r.authorizationHeader=s,s.startsWith("Bearer ")&&(r.jwt=s.slice(7)))}return t&&(t.astraId&&!r.astraId&&(r.astraId=t.astraId),t.apiKey&&!r.apiKey&&(r.apiKey=t.apiKey)),r}function C(e){if(e?.mcpEndpoint)return{endpoint:e.mcpEndpoint,discoveryUrl:e.mcpDiscoveryUrl,message:"If you are operating inside an MCP-capable host (Claude, ChatGPT, Cursor, or any MCP client), add the AstraSync MCP connector instead of integrating these URLs by hand: registration through the connector is KEYLESS and HUMAN-APPROVED \u2014 your human approves in an in-chat card, and you never see, hold, or transmit an API key, password, or private key."}}function Ze(e,t,r={}){let n=r.source??"no_credentials",a=n==="api_error",i=n==="merchant_misconfig",o=r.urls,s=i?{message:"This site's AstraSync integration is misconfigured (its API key was revoked, expired, or rotated). Your identity and the AstraSync platform are fine \u2014 contact the site operator. Retrying will not help.",registrationUrl:o?.registrationUrl??"",documentationUrl:r.remediation?.docsUrl??o?.documentationUrl??"",steps:["Report the failure to the site operator \u2014 their AstraSync API key needs rotating","Do not retry: the failure is deterministic until the operator updates their key"]}:a?{message:"Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",registrationUrl:o?.registrationUrl??"",documentationUrl:o?.documentationUrl??"",steps:["Retry the request with exponential backoff","If failures persist, share the correlationId with support"]}:{message:"This service verifies AI agents before granting access. Please register your agent with AstraSync.",registrationUrl:o?.registrationUrl??"",documentationUrl:o?.documentationUrl??"",steps:[...o?.mcpEndpoint?[`Fastest path (inside an MCP host): add the AstraSync MCP connector at ${o.mcpEndpoint} \u2014 keyless, human-approved registration`]:[],"Register for an AstraSync account","Create and register your agent","Add your ASTRA-ID to request headers","Retry your request"],...C(o)&&{mcp:C(o)}};return{identityVerified:!1,policyAllowed:!1,guidance:s,denialReasons:t?[t]:["No valid agent credentials provided"],failures:i?[{dimension:"verify_access.merchant_misconfigured",message:t??"The integration API key was rejected by AstraSync",guidance:s.message}]:a?[{dimension:"verify_access.api_error",message:t??"Verification temporarily unavailable",guidance:s.message}]:void 0,...i&&{misconfigured:!0},...a&&{retryable:!0},correlationId:r.correlationId,attemptId:r.attemptId,verifiedAt:new Date}}async function Qe(e,t){let{credentials:r,...n}=t,a={...r.astraId&&{agentId:r.astraId},...n.purpose&&{purpose:n.purpose}};if(n.action&&(a.action=n.action),n.resourceType&&(a.resourceType=n.resourceType),n.resource&&(a.resource=n.resource),n.jurisdiction&&(a.jurisdiction=n.jurisdiction),n.transactionValue&&(a.transactionValue=n.transactionValue),n.currency&&(a.currency=n.currency),n.isSubAgentRequest&&(a.isSubAgentRequest=n.isSubAgentRequest),n.parentAgentId&&(a.parentAgentId=n.parentAgentId),n.subAgentDepth!==void 0&&(a.subAgentDepth=n.subAgentDepth),n.enableRuntimeChallenge&&(a.enableRuntimeChallenge=n.enableRuntimeChallenge),n.createSession&&(a.createSession=n.createSession),n.durationRequired&&(a.durationRequired=n.durationRequired),n.counterpartyType&&(a.counterpartyType=n.counterpartyType),n.counterpartyUrl&&(a.counterpartyUrl=n.counterpartyUrl),e.counterpartyId&&(a.counterpartyId=e.counterpartyId),n.runtimeChallengeOptions&&(a.runtimeChallengeOptions=n.runtimeChallengeOptions),n.invocationProtocol&&(a.invocationProtocol=n.invocationProtocol),n.commerceArtifacts&&(a.commerceArtifacts=n.commerceArtifacts),n.attemptId&&(a.attemptId=n.attemptId),n.considerationSet&&(a.considerationSet=n.considerationSet),a.sdkVersion=W,n.callerMetadata||n.clientIp||n.userAgent){let o={...n.clientIp&&{sourceIp:n.clientIp},...n.userAgent&&{userAgent:n.userAgent},...n.callerMetadata};Object.keys(o).length>0&&(a.callerMetadata=o)}let i={"Content-Type":"application/json",...e.customHeaders};e.apiKey&&(i.Authorization=`Bearer ${e.apiKey}`,i["X-API-Key"]=e.apiKey);try{let o=await E(`${e.apiBaseUrl}/agents/verify-access`,{method:"POST",headers:i,body:JSON.stringify(a),signal:AbortSignal.timeout(e.verifyTimeoutMs??1e4)}),s=await o.json();return o.status===410?{success:!0,attemptId:typeof s?.attemptId=="string"?s.attemptId:void 0,access:{allowed:!1,reason:"endpoint_deactivated",failures:[{dimension:"endpoint.deactivated",message:typeof s?.message=="string"?s.message:"Endpoint has been deactivated",guidance:typeof s?.guidance=="string"?s.guidance:"Reactivate via POST /api/endpoints/{id}/reactivate, or update the URL on the calling agent."}]}}:o.ok?s:o.status===401?{success:!1,error:s.message||s.error||"Integration API key rejected",misconfig:!0,misconfigCode:typeof s?.code=="string"?s.code:void 0,remediation:s?.remediation&&typeof s.remediation=="object"?s.remediation:void 0,correlationId:typeof s?.correlationId=="string"?s.correlationId:void 0,attemptId:typeof s?.attemptId=="string"?s.attemptId:void 0}:{success:!1,error:s.message||s.error||`API returned ${o.status}`,correlationId:typeof s?.correlationId=="string"?s.correlationId:void 0,attemptId:typeof s?.attemptId=="string"?s.attemptId:void 0}}catch(o){return{success:!1,error:`Failed to call verify-access API: ${o instanceof Error?o.message:"Unknown error"}`}}}async function B(e,t,r){let n={...Q,...e},a=n.apiBaseUrl?Xe(n.apiBaseUrl):void 0;if(!q&&!n.disableInitChecks&&n.apiBaseUrl&&(n.strictInit?await L(n.apiBaseUrl,n.debug,!0,n.apiKey):L(n.apiBaseUrl,n.debug,!1,n.apiKey)),!H&&(e.minTrustScore!==void 0||e.minTrustScoreForFull!==void 0)&&(H=!0,console.warn("[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 and have no effect. Server is now the single source of truth for access decisions (verified ID + runtime challenge + PDLSS + trust score). To gate access to an endpoint, configure the endpoint's trust_score_requirement server-side.")),n.cacheTtl!==0&&!r?.bypassCache){let d=Ye(t,n.counterpartyId);if(d){n.debug&&console.log("[VerificationGateway] Returning cached result");let h={...d};return t.attemptId?h.attemptId=t.attemptId:delete h.attemptId,h}}let i={...t};!i.counterpartyUrl&&n.counterpartyUrl&&(i.counterpartyUrl=n.counterpartyUrl),!i.counterpartyType&&n.counterpartyType&&(i.counterpartyType=n.counterpartyType),n.debug&&console.log("[VerificationGateway] Calling verify-access API");let o=await Qe(n,i),s=o.denialReasons,c=Array.isArray(s)&&s.length>0?s:void 0;if(!o.success)return Ze(n,o.error,{source:o.misconfig?"merchant_misconfig":"api_error",correlationId:o.correlationId,attemptId:o.attemptId,remediation:o.remediation,urls:a});if(!o.access?.allowed){let d=o.access?.failures;return{identityVerified:o.verificationContext?.idVerified===!0,policyAllowed:!1,denialReasons:c??(d&&d.length>0?d.map(ve=>ve.message):o.access?.reason?[o.access.reason]:["Access denied"]),failures:d,requiresStepUp:o.access?.requiresStepUp,requiresApproval:o.access?.requiresApproval,guidance:{message:o.access?.reason||"Access denied by PDLSS policy",registrationUrl:a?.registrationUrl??"",documentationUrl:a?.documentationUrl??"",...C(a)&&{mcp:C(a)}},verifiedAt:new Date,sessionId:o.sessionId,correlationId:o.correlationId,attemptId:o.attemptId,recommendation:o.recommendation,recommendationReasons:o.recommendationReasons,stepUpApproval:o.stepUpApproval,settlement:o.settlement}}let p=o.agent?{astraId:o.agent.astraId,name:o.agent.name,trustScore:o.agent.trustScore,trustLevel:ze(o.agent.trustScore),blockchainVerified:o.agent.blockchainStatus==="verified",status:o.agent.agentStatus}:void 0,u=o.developer?{astradId:o.developer.kyaOwnerId,name:o.developer.fullName,trustScore:o.developer.trustScore||0,verified:o.developer.identityVerified}:void 0,y=o.organization?{name:o.organization.name,verified:o.organization.verified,trustScore:o.organization.trustScore}:void 0,m=o.verificationContext,l={identityVerified:o.verificationContext?.idVerified===!0,policyAllowed:!0,agent:p,developer:u,organization:y,appliedPolicy:o.access?.appliedPolicy,verificationContext:m,requiresStepUp:o.access?.requiresStepUp,requiresApproval:o.access?.requiresApproval,verifiedAt:new Date,cacheTtl:n.cacheTtl,sessionId:o.sessionId,correlationId:o.correlationId,attemptId:o.attemptId,runtimeChallenge:o.runtimeChallenge,tokenGuidance:o.tokenGuidance,recommendation:o.recommendation,recommendationReasons:o.recommendationReasons,warningHeader:o.warningHeader,stepUpApproval:o.stepUpApproval,settlement:o.settlement};l.recommendation==="deny"?(l.policyAllowed=!1,l.denialReasons=c??l.recommendationReasons??["Access denied by AstraSync recommendation"],l.guidance=l.runtimeChallenge?{message:`Verification failed: ${l.runtimeChallenge.reason||"runtime challenge failed"}`,registrationUrl:a?.registrationUrl??"",documentationUrl:a?.documentationUrl??""}:{message:l.recommendationReasons?.[0]||"Access denied by AstraSync recommendation",registrationUrl:a?.registrationUrl??"",documentationUrl:a?.documentationUrl??""}):l.recommendation==="step_up_required"&&(l.requiresStepUp=!0,l.denialReasons=c??l.recommendationReasons??["Step-up verification required"]);let f=l.requiresStepUp===!0||l.requiresApproval===!0||l.recommendation==="step_up_required";return n.cacheTtl!==0&&l.recommendation!=="deny"&&!f&&We(t,l,n.cacheTtl,n.counterpartyId),l}async function qe(e,t){let r=e.apiBaseUrl||Q.apiBaseUrl,{counterpartyUrl:n,...a}=t,i={...a,...n&&{counterpartyUrl:n},...e.counterpartyId&&{counterpartyId:e.counterpartyId}};await E(`${r}/verification-activity/unregistered-attempt`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)}).catch(()=>{})}function g(e,t){return e.headers[t.toLowerCase()]}function et(e,t){let r=e.querystring?`?${e.querystring}`:"";return`https://${t}${e.uri}${r}`}function O(e){let{headers:t,apiKeyFormat:r,platformHeaders:n,cookieCount:a}=Z(e.headers),i=e.connection??{},o=nt(e.querystring);return{headers:t,...r&&{apiKeyFormat:r},...n&&{platformHeaders:n},...Object.keys(i).length>0&&{connection:i},...a!==void 0&&{cookieCount:a},...o&&{queryKeys:o},schemaVersion:_e}}var tt=32,rt=64;function nt(e){if(!e)return;let t;try{t=new URLSearchParams(e)}catch{return}let r=[];for(let n of t.keys()){let a=n.toLowerCase().slice(0,rt);if(a&&!r.includes(a)&&(r.push(a),r.length>=tt))break}return r.length>0?r:void 0}var at=/^eyJ[\w-]+\.[\w-]*\.[\w-]+~/;function ot(e){let t=e.replace(/-/g,"+").replace(/_/g,"/"),r=t+"=".repeat((4-t.length%4)%4),n=atob(r),a=new Uint8Array(n.length);for(let i=0;i<n.length;i++)a[i]=n.charCodeAt(i);return new TextDecoder().decode(a)}function it(e){try{let t=e.split(".")[0];return JSON.parse(ot(t))}catch{return}}function st(e){if(e)try{let t=JSON.parse(e);return typeof t=="object"&&t!==null?t:void 0}catch{return}}function ct(e,t){let r=et(e,t),n=e.method,a=e.headers,i=st(e.bodyText),o=e.bodyTruncated?{bodyTruncated:!0}:{},s=g(e,"authorization"),c=s?.replace(/^Bearer\s+/i,""),u=[g(e,"x-payment-mandate")??g(e,"payment-mandate"),c].find(f=>f&&at.test(f));if(u){let f=it(u)?.typ;return{protocol:"vi-sd-jwt",artifacts:{viSdJwt:u},evidence:{typ:f,...o}}}let y=g(e,"signature"),m=g(e,"signature-input");if(y&&m){let f=g(e,"signature-agent"),d=g(e,"x-agent-registry"),h=m.toLowerCase();return{protocol:f?"rfc9421-web-bot-auth":d?.toLowerCase().includes("visa")||h.includes("visa")?"rfc9421-tap":d?.toLowerCase().includes("mastercard")||h.includes("mastercard")?"rfc9421-agent-pay":"rfc9421",artifacts:{rfc9421:{headers:a,method:n,url:r,...e.bodyText&&{body:e.bodyText}}},evidence:{...f&&{signatureAgent:f},...d&&{registryHint:d},keyid:m.match(/keyid="([^"]+)"/)?.[1],...o}}}let l=g(e,"timestamp");if(y&&!m&&(l||g(e,"idempotency-key")))return{protocol:"acp",artifacts:{acpRequest:{method:n,url:r,headers:a,...e.bodyText&&{rawBody:e.bodyText},...i&&{body:i}}},evidence:{hasTimestamp:!!l,...o}};if(/\/checkout[-_]sessions(\/|$)/.test(e.uri))return{protocol:"ucp",artifacts:{ucpRequest:{method:n,url:r,...i&&{body:i}}},evidence:{path:e.uri,...o}};if(i){let f=i.intent_mandate??i.intentMandate,d=i.cart_mandate??i.cartMandate,h=i.payment_mandate??i.paymentMandate;if(typeof f=="string"||typeof d=="string"||typeof h=="string")return{protocol:"ap2",artifacts:{ap2Mandates:{...typeof f=="string"&&{intent:f},...typeof d=="string"&&{cart:d},...typeof h=="string"&&{payment:h}}},evidence:{mandatesPresent:[typeof f=="string"&&"intent",typeof d=="string"&&"cart",typeof h=="string"&&"payment"].filter(Boolean),...o}}}if(s&&/^Payment\s+/i.test(s))return{protocol:"mpp",artifacts:{mppRequest:{method:n,url:r,headers:a,...e.bodyText&&{rawBody:e.bodyText},...i&&{body:i}}},evidence:o};if(g(e,"x-payment"))return{protocol:"x402",artifacts:{x402Request:{method:n,url:r,headers:a,...i&&{body:i}}},evidence:o}}var dt=/\.(css|js|mjs|map|png|jpe?g|gif|webp|avif|svg|ico|woff2?|ttf|otf|eot|mp4|webm|pdf|txt|xml)$/i,ut=/^astrasync-sdk\//i,lt=/curl|wget|python-requests|python-urllib|node-fetch|axios|got|okhttp|go-http-client|libwww|httpie|java\/|ruby|php|scrapy|headless|phantomjs|selenium|playwright|puppeteer|bot|crawler|spider|slurp/i,pt=/mozilla\/\d/i;function ft(e,t){if(dt.test(t))return{mode:e.mode,depth:e.depth,skip:!0};let r=Pe(e.pathRules,t);return r?{mode:r.mode??e.mode,depth:r.depth??e.depth,skip:r.skip===!0}:{mode:e.mode,depth:e.depth,skip:!1}}function gt(e,t,r){let n=g(e,"user-agent")??"";if(ut.test(n))return{tier:"self"};let a=te(e.headers,{});if(a.astraId||a.apiKey||a.jwt)return{tier:"verified",protocol:"x-astra"};let{apiKeyFormat:i,platformHeaders:o}=Z(e.headers),s={userAgent:n,apiKeyFormat:i,platformHeaders:o};if(r!=="classify"){let p=ct(e,t);if(p)return{tier:"identified",protocol:p.protocol,artifacts:p.artifacts,evidence:p.evidence,fingerprint:j(s)}}let c=j(s);return c?{tier:"identified",protocol:"platform-ua",fingerprint:c}:!n||lt.test(n)||!pt.test(n)?{tier:"anonymous-bot",evidence:{userAgent:n||"(none)"}}:!g(e,"sec-fetch-mode")&&!g(e,"accept-language")?{tier:"anonymous-bot",evidence:{userAgent:n,spoofedBrowser:!0}}:{tier:"human"}}var yt={"vi-sd-jwt":"This request presented Visa Intelligent Commerce credentials, but the agent is not verified with AstraSync. Register the agent to pair your VI credentials with a verified identity and mandate.","rfc9421-agent-pay":"This request carried a Mastercard Agent Pay signature, but the agent is not verified with AstraSync. Register the agent to pair Agent Pay credentials with a verified identity and mandate.","rfc9421-tap":"This request carried a Visa TAP signature, but the agent is not verified with AstraSync. Register the agent to pair TAP credentials with a verified identity and mandate.","rfc9421-web-bot-auth":"This request carried a Web Bot Auth signature, but the agent is not verified with AstraSync. Register the agent to link your signed-agent identity to a verified principal.",rfc9421:"This request carried an RFC 9421 HTTP message signature, but the agent is not verified with AstraSync. Register the agent to link the signing identity to a verified principal.",acp:"This request used the Agentic Commerce Protocol, but the agent is not verified with AstraSync. Register the agent to transact on this property.",ucp:"This request used a UCP checkout session, but the agent is not verified with AstraSync. Register the agent to transact on this property.",ap2:"This request presented AP2 mandates, but the agent is not verified with AstraSync. Register the agent to pair your mandates with a verified identity.",mpp:"This request presented MPP payment credentials, but the agent is not verified with AstraSync. Register the agent to transact on this property.",x402:"This request used x402 payment headers, but the agent is not verified with AstraSync. Register the agent to transact on this property.","platform-ua":"This traffic was identified as a platform AI agent without AstraSync credentials. Register the agent to access this property with a verified identity.","x-astra":"The presented AstraSync credentials failed verification or were denied by this property\u2019s access policy."};function ht(e){try{let t=new URL(e).hostname.replace(/^www\./,"");if(t==="astrasync.ai"||t.endsWith(".astrasync.ai"))return`https://mcp.${t}/mcp`}catch{}}function mt(e,t){let r=t.replace(/\/api\/?$/,""),n=e.guidance?.mcp?.endpoint||ht(r),a=(e.protocol&&yt[e.protocol])??"This request could not be verified by AstraSync.";return{success:!1,error:{code:e.tier==="verified"?"INSUFFICIENT_ACCESS":"UNAUTHORIZED",message:a,...e.protocol&&{protocol:e.protocol},failures:e.reasons,...e.correlationId&&{correlationId:e.correlationId},guidance:{message:e.guidance?.message||"Register this agent with AstraSync to receive verifiable credentials.",registrationUrl:e.guidance?.registrationUrl||`${r}/register`,documentationUrl:e.guidance?.documentationUrl||`${r}/docs/edge-adapter`,...n&&{mcp:{endpoint:n,discoveryUrl:e.guidance?.mcp?.discoveryUrl||`${n.replace(/\/mcp$/,"")}/.well-known/mcp.json`,message:e.guidance?.mcp?.message||"Inside an MCP host? Add the AstraSync MCP connector at this endpoint instead of the registration URL \u2014 registration through the connector is keyless and human-approved (your human approves in an in-chat card; you never handle credentials)."}}}}}}function vt(e){return{success:!1,error:{code:"VERIFICATION_UNAVAILABLE",message:"Agent verification is temporarily unavailable and this path enforces verification. Your identity was not evaluated and no denial was recorded \u2014 retry with exponential backoff.",failures:e.reasons,...e.correlationId&&{correlationId:e.correlationId},guidance:{message:"Retry the request with exponential backoff; the condition is transient."}}}}function At(e){return{success:!1,status:"manual_review",message:"This action requires human approval. Poll the step-up approval endpoint and retry once approved.",...e.stepUp&&{stepUpApproval:e.stepUp},...e.correlationId&&{correlationId:e.correlationId}}}var wt="X-Astra-Verified-Hop";function bt(e){return`${e.astraId};${e.sessionId??""};${e.checkedAt}`}var w={trustScore:"X-AstraSync-Trust-Score",agentId:"X-AstraSync-Agent-Id",developerId:"X-AstraSync-Developer-Id",observedDecision:"X-AstraSync-Observed-Decision"},K=["x-astrasync-","x-astra-verified-hop"];function _(){return{action:"pass",injectHeaders:{},stripHeaderPrefixes:[]}}function Rt(e,t,r){let n={};if(t.misconfig&&(n[w.observedDecision]="misconfig"),r.mode!=="enforce")return t.decision!=="allow"&&(n[w.observedDecision]=t.decision),Object.assign(n,V(t),z(t)),{action:"pass",injectHeaders:n,stripHeaderPrefixes:K};switch(t.decision){case"deny":return t.unavailable?{action:"respond",status:503,headers:{"Retry-After":"30"},bodyJson:vt(t)}:{action:"respond",status:403,headers:{},bodyJson:mt(t,e.apiBaseUrl)};case"manual_review":return{action:"respond",status:202,headers:{"Retry-After":"30"},bodyJson:At(t)};default:return Object.assign(n,V(t),z(t)),{action:"pass",injectHeaders:n,stripHeaderPrefixes:K}}}function V(e){if(!e.asat)return{};let{trustScore:t,agentId:r,developerId:n}=e.asat;return{...t!==void 0&&{[w.trustScore]:String(t)},...r&&{[w.agentId]:r},...n&&{[w.developerId]:n}}}function z(e){let t=e.asat?.agentId;return t?{[wt]:bt({astraId:t,...e.sessionId&&{sessionId:e.sessionId},checkedAt:Date.now()})}:{}}var St={GET:"data.read",HEAD:"data.read",OPTIONS:"data.read",POST:"data.write",PUT:"data.write",PATCH:"data.write",DELETE:"data.delete"},It="data.write",Et="data";function Ct(e){return St[e.toUpperCase()]??It}function Tt(e){let t=e.indexOf(":");if(t>=0)return{purpose:e.slice(0,t)};let r=e.indexOf(".");return r>0&&r<e.length-1?{purpose:e.slice(0,r),actionCandidate:e}:{purpose:e}}function Pt(e){let t=e.astraPurpose?Tt(e.astraPurpose):void 0,r,n;e.routeAction?(r=e.routeAction,n="route_config"):e.hasCustomActionExtractor&&e.customAction?(r=e.customAction,n="custom_extractor"):!e.hasCustomActionExtractor&&e.astraAction?(r=e.astraAction,n="header"):!e.hasCustomActionExtractor&&t?.actionCandidate?(r=t.actionCandidate,n="purpose_header_derived"):(r=Ct(e.method),n="method_table");let a,i;if(e.routePurpose?(a=e.routePurpose,i="route_config"):e.hasCustomPurposeExtractor?e.customPurpose&&(a=e.customPurpose,i="custom_extractor"):t?(a=t.purpose,i="header"):e.legacyPurpose?(a=e.legacyPurpose,i="legacy_header"):e.queryPurpose&&(a=e.queryPurpose,i="query"),!a){let o=r.indexOf(".");o>0?(a=r.slice(0,o),i="action_derived"):(a=Et,i="transport_default")}return{purpose:a,action:r,purposeSource:i,actionSource:n}}async function k(e,t){let r;try{return await Promise.race([e,new Promise(n=>{r=setTimeout(()=>n(void 0),t)})])}catch{return}finally{r&&clearTimeout(r)}}async function G(e,t,r,n){let a=k(qe({apiBaseUrl:e.apiBaseUrl,counterpartyId:e.counterpartyId},{counterpartyUrl:e.counterpartyUrl,counterpartyType:"website",sourceIp:t.clientIp,userAgent:g(t,"user-agent"),requestPath:t.uri,requestMethod:t.method,protocol:r.protocol,evidence:r.evidence,observedMetadata:O(t)}),n);if(e.waitUntil){e.waitUntil(a);return}await a}function Ut(e,t=Math.random){return e<=0?!1:e>=1?!0:t()<e}function v(e){return{tier:e.tier,decision:"allow",reasons:[],protocol:e.protocol}}function X(e,t,r,n){let a=Pt({method:t.method,astraPurpose:g(t,"x-astra-purpose"),astraAction:g(t,"x-astra-action")}),i=g(t,"x-astra-attempt-id");return{...i&&/^att_[0-9a-f]{32}$/.test(i)&&{attemptId:i},credentials:te(t.headers,{}),purpose:a.purpose,action:a.action,resource:t.uri,createSession:!0,counterpartyType:"website",counterpartyUrl:e.counterpartyUrl,callerMetadata:{sourceIp:t.clientIp,userAgent:g(t,"user-agent"),referer:g(t,"referer"),host:g(t,"host"),observedMetadata:O(t)},...n&&r.artifacts&&{commerceArtifacts:r.artifacts}}}function Y(e,t){let r=v(e);return r.sessionId=t.sessionId,r.correlationId=t.correlationId,r.guidance=t.guidance,t.misconfigured?(r.reasons=["verification key misconfigured \u2014 fail-open (merchant_misconfig)"],r.misconfig=!0,r):t.requiresStepUp||t.stepUpApproval?(r.decision="manual_review",r.reasons=["step-up approval required"],r.stepUp={pollUrl:t.stepUpApproval?.pollUrl,expiresAt:t.stepUpApproval?.expiresAt},r):!t.identityVerified||!t.policyAllowed?(r.decision="deny",r.reasons=t.denialReasons?.length?t.denialReasons:[t.identityVerified?"denied by access policy":"identity not verified"],r):(r.asat={trustScore:t.agent?.trustScore,agentId:t.agent?.astraId,developerId:t.developer?.astradId},r)}function I(e,t,r,n){let a=v(e);return a.unavailable=!0,a.reasons=[r],n&&(a.correlationId=n),t.mode==="enforce"&&(a.decision="deny"),a}function J(e){return(e.failures??[]).some(t=>t.dimension==="verify_access.api_error")===!0&&!e.misconfigured}async function _t(e,t,r,n,a,i){let o=e.budgets??{},s=o.beaconMs??300,c=n.mode==="enforce"?o.verifyEnforceMs??3e3:o.verifyObserveMs??1500,p={apiBaseUrl:e.apiBaseUrl,...a&&{apiKey:a},counterpartyId:e.counterpartyId,disableInitChecks:!0};try{switch(r.tier){case"verified":{if(n.depth==="classify")return v(r);let u=await k(B(p,X(e,t,r,n.depth==="authorize")),c);return u?J(u)?I(r,n,u.denialReasons?.[0]??"verify-access api error",u.correlationId):Y(r,u):I(r,n,"verify-access unreachable within budget")}case"identified":{if(n.depth==="authorize"&&r.artifacts){let y=await k(B(p,X(e,t,r,!0)),c);return y?J(y)?I(r,n,y.denialReasons?.[0]??"verify-access api error",y.correlationId):Y(r,y):I(r,n,"verify-access unreachable within budget")}await G(e,t,r,s);let u=v(r);return n.mode==="enforce"&&n.depth!=="classify"&&(u.decision="deny",u.reasons=["agent is not registered with AstraSync"]),u}case"anonymous-bot":return Ut(i.anonymousBeaconRate,e.random)&&await G(e,t,{...r,protocol:r.protocol??"ua-heuristic"},s),v(r);default:return v(r)}}catch(u){let y=v(r);return y.reasons=[`edge pipeline error \u2014 fail-open: ${u instanceof Error?u.message:String(u)}`],y}}async function re(e,t,r,n){let a=ft(r,t.uri);try{if(a.skip)return{policy:a,application:_()};let i=g(t,"x-forwarded-host")??g(t,"host")??new URL(e.counterpartyUrl).host,o=gt(t,i,a.depth);if(o.tier==="human"||o.tier==="self")return{policy:a,classification:o,application:_()};let s=await _t(e,t,o,a,n,r.sampling);return s.decision!=="allow"&&e.log?.("info",a.mode==="enforce"?`${s.decision.toUpperCase()}: ${t.method} ${t.uri}`:`[OBSERVE] would have been ${s.decision.toUpperCase()}: ${t.method} ${t.uri}`,{tier:s.tier,protocol:s.protocol,reasons:s.reasons}),{policy:a,classification:o,outcome:s,application:Rt(e,s,a)}}catch(i){return e.log?.("error","edge evaluation error \u2014 passing request through",{error:i instanceof Error?i.message:String(i)}),{policy:a,application:_()}}}function ne(e){return e.Records[0].cf.request}function A(e,t){return e.headers[t.toLowerCase()]?.[0]?.value}function xt(e){let t={};for(let[r,n]of Object.entries(e))n?.length&&(t[r]=n.map(a=>a.value).join(", "));return t}function kt(e){let t=e.body;return t?.data?{text:t.encoding==="base64"?Buffer.from(t.data,"base64").toString("utf8"):t.data,truncated:t.inputTruncated===!0}:{truncated:!1}}function Ot(e){let t={},r=(i,o,s)=>{let c=A(e,o);c&&(t[i]=s?s(c):c)},n=A(e,"cloudfront-viewer-address");if(n){t.ip=n.replace(/:\d+$/,"");let i=n.match(/:(\d+)$/);i&&(t.sourcePort=i[1])}r("country","cloudfront-viewer-country"),r("countryName","cloudfront-viewer-country-name"),r("region","cloudfront-viewer-country-region"),r("countryRegionName","cloudfront-viewer-country-region-name"),r("city","cloudfront-viewer-city"),r("latitude","cloudfront-viewer-latitude"),r("longitude","cloudfront-viewer-longitude"),r("postalCode","cloudfront-viewer-postal-code"),r("asn","cloudfront-viewer-asn"),r("tlsVersion","cloudfront-viewer-tls");{let i=A(e,"cloudfront-viewer-tls")?.split(":")[1];i&&(t.tlsCipher=i)}r("httpVersion","cloudfront-viewer-http-version"),r("timeZone","cloudfront-viewer-time-zone"),r("metroCode","cloudfront-viewer-metro-code"),r("tlsFingerprint","cloudfront-viewer-ja3-fingerprint"),r("ja4","cloudfront-viewer-ja4-fingerprint"),r("headerOrder","cloudfront-viewer-header-order",i=>i.slice(0,256)),r("headerCount","cloudfront-viewer-header-count");let a=[];for(let[i,o]of[["desktop","cloudfront-is-desktop-viewer"],["mobile","cloudfront-is-mobile-viewer"],["tablet","cloudfront-is-tablet-viewer"],["smarttv","cloudfront-is-smarttv-viewer"]])A(e,o)==="true"&&a.push(i);return a.length&&(t.device=a.join(",")),t}function ae(e){let t=kt(e),r=Ot(e),n=A(e,"cloudfront-viewer-address")?.split(":")[0];return{method:e.method,uri:e.uri,querystring:e.querystring??"",headers:xt(e.headers),...t.text!==void 0&&{bodyText:t.text},...t.truncated&&{bodyTruncated:!0},...n&&{clientIp:n},...Object.keys(r).length>0&&{connection:r}}}function oe(e,t){if(t.action==="respond")return Ft(t.status,t.bodyJson,t.headers);for(let r of t.stripHeaderPrefixes)Mt(e,r);for(let[r,n]of Object.entries(t.injectHeaders))M(e,r,n);return e}function ie(e){let t=e.origin?.custom?.domainName??e.origin?.s3?.domainName??void 0;if(!t)return;let r=A(e,"host");!r||r===t||(A(e,"x-forwarded-host")||M(e,"X-Forwarded-Host",r),M(e,"Host",t))}function M(e,t,r){e.headers[t.toLowerCase()]=[{key:t,value:r}]}function Mt(e,t){let r=t.toLowerCase();for(let n of Object.keys(e.headers))n.startsWith(r)&&delete e.headers[n]}function Ft(e,t,r){let n={"content-type":[{key:"Content-Type",value:"application/json"}]};for(let[a,i]of Object.entries(r??{}))n[a.toLowerCase()]=[{key:a,value:i}];return{status:String(e),statusDescription:e===403?"Forbidden":e===202?"Accepted":"OK",headers:n,body:JSON.stringify(t)}}var Dt="5.0.0",T=`astrasync-sdk/${Dt}`;function Nt(e){if(!e)return{"user-agent":T};if(e instanceof Headers){let r=new Headers(e);return r.has("user-agent")||r.set("user-agent",T),r}return Array.isArray(e)?e.some(([n])=>n.toLowerCase()==="user-agent")?e:[...e,["user-agent",T]]:Object.keys(e).some(r=>r.toLowerCase()==="user-agent")?e:{"user-agent":T,...e}}var $t=(e,t)=>fetch(e,{...t,headers:Nt(t?.headers)}),D=Object.freeze({version:1,mode:"observe",depth:"classify",pathRules:[],sampling:Object.freeze({anonymousBeaconRate:.1}),failurePosture:"open"}),se=["observe","enforce"],ce=["classify","authenticate","authorize"];function jt(e){if(typeof e!="object"||e===null)return!1;let t=e;if(t.version!==1||!se.includes(t.mode)||!ce.includes(t.depth)||!Array.isArray(t.pathRules))return!1;for(let n of t.pathRules){if(typeof n!="object"||n===null)return!1;let a=n;if(typeof a.pattern!="string"||a.pattern.length===0||a.mode!==void 0&&!se.includes(a.mode)||a.depth!==void 0&&!ce.includes(a.depth))return!1}let r=t.sampling;return typeof r!="object"||r===null||typeof r.anonymousBeaconRate!="number"||r.anonymousBeaconRate<0||r.anonymousBeaconRate>1?!1:t.failurePosture==="open"}async function Ht(e,t,r){if(!t)return null;let n={Accept:"application/json"};e.apiKey&&(n.Authorization=`Bearer ${e.apiKey}`,n["X-API-Key"]=e.apiKey),r?.etag&&(n["If-None-Match"]=r.etag);try{let a=await $t(`${e.apiBaseUrl}/endpoints/${encodeURIComponent(t)}/edge-config`,{method:"GET",headers:n,signal:AbortSignal.timeout(r?.timeoutMs??5e3)});if(a.status===304)return{notModified:!0};if(!a.ok)return null;let o=(await a.json()).data?.edgeConfig;return jt(o)?{edgeConfig:o,etag:a.headers.get("etag")??void 0}:null}catch{return null}}var Lt=60*1e3,Bt=1440*60*1e3,b=new Map,F=new Map;function ue(e,t){return`${e}|${t}`}function Kt(e){return e.mode!=="enforce"&&!e.pathRules.some(t=>t.mode==="enforce")?e:{...e,mode:"observe",pathRules:e.pathRules.map(t=>t.mode==="enforce"?{...t,mode:"observe"}:t)}}async function de(e,t){let r=ue(e.apiBaseUrl,t),n=F.get(r);if(n)return n;let a=Ht(e,t,{etag:b.get(r)?.etag}).then(i=>{if(i===null)return;let o=Date.now();if("notModified"in i){let s=b.get(r);s&&(s.lastSuccessAt=o);return}b.set(r,{config:i.edgeConfig,etag:i.etag,lastSuccessAt:o})}).finally(()=>{F.delete(r)});return F.set(r,a),a}async function le(e,t,r){let n=r?.ttlMs??Lt,a=r?.maxStaleMs??Bt,i=ue(e.apiBaseUrl,t),o=b.get(i);if(o){let s=Date.now()-o.lastSuccessAt;return s>n&&de(e,t).catch(()=>{}),s>a?Kt(o.config):o.config}return await de(e,t).catch(()=>{}),b.get(i)?.config??D}var Vt=900*1e3,pe=new Map;async function zt(e){let{SecretsManagerClient:t,GetSecretValueCommand:r}=await import("@aws-sdk/client-secrets-manager");return(await new t({region:"us-east-1"}).send(new r({SecretId:e}))).SecretString??void 0}async function fe(e){if(e.apiKey)return e.apiKey;let t=e.apiKeySecretName;if(!t)return;let r=pe.get(t);if(r&&Date.now()-r.fetchedAt<Vt)return r.value;try{let a=await(e.fetchSecret??zt)(t);return pe.set(t,{value:a,fetchedAt:Date.now()}),a}catch(n){return e.log?.("warn","Secrets Manager fetch failed \u2014 continuing keyless",{secretName:t,error:n instanceof Error?n.message:String(n)}),r?.value}}async function ge(e,t){try{return await le({apiBaseUrl:e.apiBaseUrl,apiKey:t},e.counterpartyId,{ttlMs:e.configTtlMs})}catch{return e.fallbackConfig??D}}function ye(e){let t=e.log??((r,n,a)=>{console[r==="info"?"log":r](`[astrasync-edge] ${n}`,a??"")});return async function(n){let a=ne(n);try{ie(a);let i=await fe({...e,log:t}),o=await ge(e,i),{application:s}=await re({...e,log:t},ae(a),o,i);return oe(a,s)}catch(i){return t("error","edge handler error \u2014 passing request through",{error:i instanceof Error?i.message:String(i)}),a}}}var Gt="https://astrasync.ai/api",he="",me="",Xt=void 0;(!he||!me)&&console.error("[astrasync-edge] ASTRASYNC_COUNTERPARTY_ID / ASTRASYNC_COUNTERPARTY_URL were not baked into the bundle \u2014 rebuild via infra/deploy.sh with the ASTRASYNC_* env vars set.");var Yt=ye({apiBaseUrl:Gt,counterpartyId:he,counterpartyUrl:me,apiKeySecretName:Xt});0&&(module.exports={handler});
1
+ "use strict";var be=Object.create;var R=Object.defineProperty;var Re=Object.getOwnPropertyDescriptor;var Se=Object.getOwnPropertyNames;var Ie=Object.getPrototypeOf,Ce=Object.prototype.hasOwnProperty;var Ee=(e,t)=>{for(var r in t)R(e,r,{get:t[r],enumerable:!0})},B=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of Se(t))!Ce.call(e,a)&&a!==r&&R(e,a,{get:()=>t[a],enumerable:!(n=Re(t,a))||n.enumerable});return e};var Te=(e,t,r)=>(r=e!=null?be(Ie(e)):{},B(t||!e||!e.__esModule?R(r,"default",{value:e,enumerable:!0}):r,e)),Ue=e=>B(R({},"__esModule",{value:!0}),e);var Qt={};Ee(Qt,{handler:()=>Zt});module.exports=Ue(Qt);var Z="5.6.0",S=`astrasync-sdk/${Z}`;function Pe(e){if(!e)return{"user-agent":S};if(e instanceof Headers){let r=new Headers(e);return r.has("user-agent")||r.set("user-agent",S),r}return Array.isArray(e)?e.some(([n])=>n.toLowerCase()==="user-agent")?e:[...e,["user-agent",S]]:Object.keys(e).some(r=>r.toLowerCase()==="user-agent")?e:{"user-agent":S,...e}}var C=(e,t)=>fetch(e,{...t,headers:Pe(t?.headers)}),er=Object.freeze({version:1,mode:"observe",depth:"classify",pathRules:[],sampling:Object.freeze({anonymousBeaconRate:.1}),failurePosture:"open"}),tr=60*1e3,rr=1440*60*1e3;function _e(e,t){for(let r of e)if(xe(r.pattern).test(t))return r}function xe(e){let t=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${t}$`,"i")}var ke=1,Oe=new Set(["cookie","set-cookie","x-csrf-token","proxy-authorization","x-astrasync-signature","x-astrasync-secret","x-hub-signature","x-hub-signature-256","x-astra-verified-hop"]),Me=["x-astrasync-","kya-","kya_"],Fe=new Set(["authorization","x-api-key","x-goog-api-key","api-key"]);function De(e){return e==="signature"||e.endsWith("-signature")||e.endsWith("-signature-256")}var Ne=new Set(["openai-organization","openai-project","openai-version","openai-processing-ms","anthropic-version","anthropic-beta","x-goog-user-project","x-goog-api-client","user-agent","x-agent-card-url","x-agent-provider"]),Be=["x-goog-","x-stainless-","x-anthropic-","x-openai-","sec-ch-"],He=["sk-ant-api03","sk-ant-api","sk-ant","sk-proj","sk-svcacct","sk-or-v1","sk-or","sk-lf","sk-","gsk_","aiza","ya29","ghp_","gho_","github_pat_","xai-","pplx-","r8_","hf_","astra-","astrae-"],je=64,H=1024,$e=16*1024;function _(e){let t=0;for(let r=0;r<e.length;r++){let n=e.charCodeAt(r);n<128?t+=1:n<2048?t+=2:n>=55296&&n<=56319?(t+=4,r++):t+=3}return t}function Le(e){if(!e)return;let t=e.trim(),r=t.indexOf(" ");if(r>0){let a=t.slice(0,r).toLowerCase();(a==="bearer"||a==="basic"||a==="token")&&(t=t.slice(r+1).trim())}let n=t.toLowerCase();for(let a of He)if(n.startsWith(a))return a}function Ke(e){return!!(Oe.has(e)||Me.some(t=>e.startsWith(t))||De(e))}function Ve(e){return Ne.has(e)?!0:Be.some(t=>e.startsWith(t))}function Q(e){let t={},r={},n,a,i=0,o=0;if(!e)return{headers:t};for(let c of Object.keys(e)){if(o>=je)break;let p=c.toLowerCase(),u=e[c];if(u===void 0)continue;let y=Array.isArray(u)?u.join(", "):String(u);if(Fe.has(p)){let f=Le(y);f&&!n&&(n=f);continue}if(p==="cookie"&&(a=y.split(";").filter(f=>f.trim().length>0).length),Ke(p))continue;let h=y;_(h)>H&&(h=h.slice(0,H));let l=_(p)+_(h);i+l>$e||(i+=l,o++,t[p]=h,Ve(p)&&(r[p]=h))}let s={headers:t};return n&&(s.apiKeyFormat=n),Object.keys(r).length>0&&(s.platformHeaders=r),a!==void 0&&(s.cookieCount=a),s}var Ge=[{vendor:"claude",displayName:"Anthropic Claude",uaPatterns:[/claude/i,/anthropic/i],agentCardPatterns:[/anthropic\.com/i,/claude\.ai/i],apiKeyFormatPatterns:[/^sk-ant/i],headerPatterns:[/^anthropic-version/i,/^anthropic-beta/i,/^x-anthropic-/i]},{vendor:"chatgpt",displayName:"OpenAI ChatGPT",uaPatterns:[/chatgpt/i,/openai/i,/gpt-?\d/i],agentCardPatterns:[/openai\.com/i,/chatgpt\.com/i],apiKeyFormatPatterns:[/^sk-proj/i,/^sk-svcacct/i],headerPatterns:[/^openai-organization/i,/^openai-project/i,/^openai-version/i]},{vendor:"gemini",displayName:"Google Gemini",uaPatterns:[/gemini/i,/google-gemini/i,/bard/i],agentCardPatterns:[/gemini\.google\.com/i,/ai\.google\.dev/i],apiKeyFormatPatterns:[/^aiza/i],headerPatterns:[/^x-goog-user-project/i,/^x-goog-api-client/i]},{vendor:"cursor",displayName:"Cursor",uaPatterns:[/cursor/i],agentCardPatterns:[/cursor\.sh/i,/cursor\.com/i]},{vendor:"goose",displayName:"Block Goose",uaPatterns:[/goose/i,/block-goose/i],agentCardPatterns:[/block\.xyz\/goose/i,/goose\.tools/i]},{vendor:"perplexity",displayName:"Perplexity",uaPatterns:[/perplexity/i],agentCardPatterns:[/perplexity\.ai/i],apiKeyFormatPatterns:[/^pplx-/i]},{vendor:"chatgpt-atlas",displayName:"ChatGPT Atlas browser",uaPatterns:[/\batlas\/\d/i],headerPatterns:[/^sec-ch-ua: .*atlas/i]},{vendor:"perplexity-comet",displayName:"Perplexity Comet browser",uaPatterns:[/\bcomet\/\d/i],headerPatterns:[/^sec-ch-ua: .*comet/i]},{vendor:"astrasync-sdk",displayName:"AstraSync SDK",uaPatterns:[/^astrasync-sdk\//i]}];function ze(e,t){let r=t.userAgent??"",n=t.agentCardUrl??"",a=t.apiKeyFormat??"",i=t.ja4??"",o=t.asn??"",s=[];if(t.platformHeaders)for(let[c,p]of Object.entries(t.platformHeaders))s.push(c,`${c}: ${p}`);for(let c of e){let p=c.uaPatterns?.some(d=>d.test(r)),u=c.agentCardPatterns?.some(d=>d.test(n)),y=a.length>0&&c.apiKeyFormatPatterns?.some(d=>d.test(a)),h=s.length>0&&c.headerPatterns?.some(d=>s.some(m=>d.test(m))),l=i.length>0&&c.ja4Patterns?.some(d=>d.test(i)),f=o.length>0&&c.asnList?.includes(o);if(p||u||y||h||l||f){let d=r.split(/[\s/]/)[0]?.toLowerCase()??"",m=(()=>{try{return n?new URL(n).host:""}catch{return""}})(),P=d||m||a||i||o&&`asn${o}`||"unknown";return{vendor:c.vendor,fingerprintKey:`${c.vendor}:${P}`,displayName:c.displayName}}}}function j(e){return ze(Ge,e)}function Xe(e){return e>=80?"PLATINUM":e>=60?"GOLD":e>=40?"SILVER":"BRONZE"}var nr=3600*1e3,Ye=new Map;function Je(e){return Ye.get(e)?.data}var q={apiBaseUrl:"https://astrasync.ai/api",debug:!1},ee=!1,$=!1;async function L(e,t,r,n){ee=!0;try{let a=`${e}/agents/verify-access`,o=(await C(a,{method:"HEAD"})).headers.get("content-type")??"";if(o.startsWith("text/html")){let s=`[VerificationGateway] apiBaseUrl '${e}' returned HTML (content-type: ${o}). This usually means apiBaseUrl is pointing at a marketing site instead of the API. Expected: 'https://astrasync.ai/api' (prod) or 'https://staging.astrasync.ai/api' (staging).`;if(r)throw new Error(`${s} (strictInit=true)`);console.warn(`${s} Set disableInitChecks: true on GatewayConfig to silence.`)}else t&&console.log(`[VerificationGateway] init check passed for ${e} (content-type: ${o})`);if(n){let s=await C(`${e}/agents/verify-access/self-check`,{headers:{Authorization:`Bearer ${n}`}});if(s.status===401){let c=await s.json().catch(()=>({})),p=`[VerificationGateway] the configured AstraSync API key was REJECTED at startup (${c.code??"api_key_invalid"}: ${c.message??"invalid key"}). Every inbound agent will be turned away until the key is rotated`+(c.remediation?.manageUrl?` at ${c.remediation.manageUrl}`:"")+".";if(r)throw new Error(`${p} (strictInit=true)`);console.error(p)}else if(s.ok){let c=await s.json().catch(()=>({}));typeof c.daysToExpiry=="number"&&c.daysToExpiry<=7?console.warn(`[VerificationGateway] the configured AstraSync API key expires in ${c.daysToExpiry} day(s) \u2014 rotate it at Settings \u2192 Developer Tools before integrations start failing.`):t&&console.log("[VerificationGateway] API key self-check passed")}}}catch(a){if(r)throw a;t&&console.log(`[VerificationGateway] init check failed (non-blocking): ${String(a)}`)}}var k=new Map;function te(e,t){let r=e.credentials;return[r.astraId||"",r.apiKey||"",r.jwt||"",e.purpose||"",e.action||"",e.resourceType||"",e.resource||"",e.jurisdiction||"",e.transactionValue??"",e.currency||"",t||"",e.counterpartyUrl||"",e.counterpartyType||"",e.isSubAgentRequest?"1":"0",e.parentAgentId||"",e.subAgentDepth??"",e.durationRequired??"",e.invocationProtocol||"",e.enableRuntimeChallenge?"1":"0",e.callerMetadata?.sourceIp||"",e.callerMetadata?.userAgent||"",e.callerMetadata?.forwardedFor||"",e.callerMetadata?.agentCardUrl||"",e.commercePhase||"",e.checkoutSessionId||""].join("|")}function We(e,t){let r=te(e,t),n=k.get(r);return n&&n.expiresAt>Date.now()?n.result:(n&&k.delete(r),null)}var Ze=60;function Qe(e,t,r,n){let a=r&&r>0?r:Ze,i=te(e,n);k.set(i,{result:t,expiresAt:Date.now()+a*1e3})}function re(e,t){let r={},n=/^ASTRAE?-[A-Za-z0-9_-]{1,64}$/,a=e["x-astra-id"]||e["X-Astra-Id"]||e["X-ASTRA-ID"]||e["x-astra-agentid"]||e["X-Astra-AgentId"]||e["x-astra-agent-id"]||e["X-Astra-Agent-Id"]||e["X-ASTRA-AGENT-ID"];if(a){let s=Array.isArray(a)?a[0]:typeof a=="string"?a:void 0;typeof s=="string"&&n.test(s)&&(r.astraId=s)}let i=e["x-api-key"]||e["X-Api-Key"]||e["X-API-KEY"];i&&(r.apiKey=Array.isArray(i)?i[0]:i);let o=e.authorization||e.Authorization;if(o){let s=Array.isArray(o)?o[0]:o;typeof s=="string"&&(r.authorizationHeader=s,s.startsWith("Bearer ")&&(r.jwt=s.slice(7)))}return t&&(t.astraId&&!r.astraId&&(r.astraId=t.astraId),t.apiKey&&!r.apiKey&&(r.apiKey=t.apiKey)),r}function E(e){if(e?.mcpEndpoint)return{endpoint:e.mcpEndpoint,discoveryUrl:e.mcpDiscoveryUrl,message:"If you are operating inside an MCP-capable host (Claude, ChatGPT, Cursor, or any MCP client), add the AstraSync MCP connector instead of integrating these URLs by hand: registration through the connector is KEYLESS and HUMAN-APPROVED \u2014 your human approves in an in-chat card, and you never see, hold, or transmit an API key, password, or private key."}}function qe(e,t,r={}){let n=r.source??"no_credentials",a=n==="api_error",i=n==="merchant_misconfig",o=r.urls,s=i?{message:"This site's AstraSync integration is misconfigured (its API key was revoked, expired, or rotated). Your identity and the AstraSync platform are fine \u2014 contact the site operator. Retrying will not help.",registrationUrl:o?.registrationUrl??"",documentationUrl:r.remediation?.docsUrl??o?.documentationUrl??"",steps:["Report the failure to the site operator \u2014 their AstraSync API key needs rotating","Do not retry: the failure is deterministic until the operator updates their key"]}:a?{message:"Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",registrationUrl:o?.registrationUrl??"",documentationUrl:o?.documentationUrl??"",steps:["Retry the request with exponential backoff","If failures persist, share the correlationId with support"]}:{message:"This service verifies AI agents before granting access. Please register your agent with AstraSync.",registrationUrl:o?.registrationUrl??"",documentationUrl:o?.documentationUrl??"",steps:[...o?.mcpEndpoint?[`Fastest path (inside an MCP host): add the AstraSync MCP connector at ${o.mcpEndpoint} \u2014 keyless, human-approved registration`]:[],"Register for an AstraSync account","Create and register your agent","Add your ASTRA-ID to request headers","Retry your request"],...E(o)&&{mcp:E(o)}};return{identityVerified:!1,policyAllowed:!1,guidance:s,denialReasons:t?[t]:["No valid agent credentials provided"],failures:i?[{dimension:"verify_access.merchant_misconfigured",message:t??"The integration API key was rejected by AstraSync",guidance:s.message}]:a?[{dimension:"verify_access.api_error",message:t??"Verification temporarily unavailable",guidance:s.message}]:void 0,...i&&{misconfigured:!0},...a&&{retryable:!0},correlationId:r.correlationId,attemptId:r.attemptId,verifiedAt:new Date}}async function et(e,t){let{credentials:r,...n}=t,a={...r.astraId&&{agentId:r.astraId},...n.purpose&&{purpose:n.purpose}};if(n.action&&(a.action=n.action),n.resourceType&&(a.resourceType=n.resourceType),n.resource&&(a.resource=n.resource),n.jurisdiction&&(a.jurisdiction=n.jurisdiction),n.transactionValue&&(a.transactionValue=n.transactionValue),n.currency&&(a.currency=n.currency),n.isSubAgentRequest&&(a.isSubAgentRequest=n.isSubAgentRequest),n.parentAgentId&&(a.parentAgentId=n.parentAgentId),n.subAgentDepth!==void 0&&(a.subAgentDepth=n.subAgentDepth),n.enableRuntimeChallenge&&(a.enableRuntimeChallenge=n.enableRuntimeChallenge),n.createSession&&(a.createSession=n.createSession),n.durationRequired&&(a.durationRequired=n.durationRequired),n.counterpartyType&&(a.counterpartyType=n.counterpartyType),n.counterpartyUrl&&(a.counterpartyUrl=n.counterpartyUrl),e.counterpartyId&&(a.counterpartyId=e.counterpartyId),n.runtimeChallengeOptions&&(a.runtimeChallengeOptions=n.runtimeChallengeOptions),n.invocationProtocol&&(a.invocationProtocol=n.invocationProtocol),n.commercePhase&&(a.commercePhase=n.commercePhase),n.checkoutSessionId&&(a.checkoutSessionId=n.checkoutSessionId),n.checkoutItems&&(a.checkoutItems=n.checkoutItems),n.buyerEmail&&(a.buyerEmail=n.buyerEmail),n.commerceArtifacts&&(a.commerceArtifacts=n.commerceArtifacts),n.attemptId&&(a.attemptId=n.attemptId),n.considerationSet&&(a.considerationSet=n.considerationSet),a.sdkVersion=Z,n.callerMetadata||n.clientIp||n.userAgent){let o={...n.clientIp&&{sourceIp:n.clientIp},...n.userAgent&&{userAgent:n.userAgent},...n.callerMetadata};Object.keys(o).length>0&&(a.callerMetadata=o)}let i={"Content-Type":"application/json",...e.customHeaders};e.apiKey&&(i.Authorization=`Bearer ${e.apiKey}`,i["X-API-Key"]=e.apiKey);try{let o=await C(`${e.apiBaseUrl}/agents/verify-access`,{method:"POST",headers:i,body:JSON.stringify(a),signal:AbortSignal.timeout(e.verifyTimeoutMs??1e4)}),s=await o.json();return o.status===410?{success:!0,attemptId:typeof s?.attemptId=="string"?s.attemptId:void 0,access:{allowed:!1,reason:"endpoint_deactivated",failures:[{dimension:"endpoint.deactivated",message:typeof s?.message=="string"?s.message:"Endpoint has been deactivated",guidance:typeof s?.guidance=="string"?s.guidance:"Reactivate via POST /api/endpoints/{id}/reactivate, or update the URL on the calling agent."}]}}:o.ok?s:o.status===401?{success:!1,error:s.message||s.error||"Integration API key rejected",misconfig:!0,misconfigCode:typeof s?.code=="string"?s.code:void 0,remediation:s?.remediation&&typeof s.remediation=="object"?s.remediation:void 0,correlationId:typeof s?.correlationId=="string"?s.correlationId:void 0,attemptId:typeof s?.attemptId=="string"?s.attemptId:void 0}:{success:!1,error:s.message||s.error||`API returned ${o.status}`,correlationId:typeof s?.correlationId=="string"?s.correlationId:void 0,attemptId:typeof s?.attemptId=="string"?s.attemptId:void 0}}catch(o){return{success:!1,error:`Failed to call verify-access API: ${o instanceof Error?o.message:"Unknown error"}`}}}async function K(e,t,r){let n={...q,...e},a=n.apiBaseUrl?Je(n.apiBaseUrl):void 0;if(!ee&&!n.disableInitChecks&&n.apiBaseUrl&&(n.strictInit?await L(n.apiBaseUrl,n.debug,!0,n.apiKey):L(n.apiBaseUrl,n.debug,!1,n.apiKey)),!$&&(e.minTrustScore!==void 0||e.minTrustScoreForFull!==void 0)&&($=!0,console.warn("[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 and have no effect. Server is now the single source of truth for access decisions (verified ID + runtime challenge + PDLSS + trust score). To gate access to an endpoint, configure the endpoint's trust_score_requirement server-side.")),n.cacheTtl!==0&&!r?.bypassCache){let d=We(t,n.counterpartyId);if(d){n.debug&&console.log("[VerificationGateway] Returning cached result");let m={...d};return t.attemptId?m.attemptId=t.attemptId:delete m.attemptId,m}}let i={...t};!i.counterpartyUrl&&n.counterpartyUrl&&(i.counterpartyUrl=n.counterpartyUrl),!i.counterpartyType&&n.counterpartyType&&(i.counterpartyType=n.counterpartyType),n.debug&&console.log("[VerificationGateway] Calling verify-access API");let o=await et(n,i),s=o.denialReasons,c=Array.isArray(s)&&s.length>0?s:void 0;if(!o.success)return qe(n,o.error,{source:o.misconfig?"merchant_misconfig":"api_error",correlationId:o.correlationId,attemptId:o.attemptId,remediation:o.remediation,urls:a});if(!o.access?.allowed){let d=o.access?.failures;return{identityVerified:o.verificationContext?.idVerified===!0,policyAllowed:!1,denialReasons:c??(d&&d.length>0?d.map(we=>we.message):o.access?.reason?[o.access.reason]:["Access denied"]),failures:d,requiresStepUp:o.access?.requiresStepUp,requiresApproval:o.access?.requiresApproval,guidance:{message:o.access?.reason||"Access denied by PDLSS policy",registrationUrl:a?.registrationUrl??"",documentationUrl:a?.documentationUrl??"",...E(a)&&{mcp:E(a)}},verifiedAt:new Date,sessionId:o.sessionId,correlationId:o.correlationId,attemptId:o.attemptId,recommendation:o.recommendation,recommendationReasons:o.recommendationReasons,stepUpApproval:o.stepUpApproval,settlement:o.settlement,settlementOutcome:o.settlementOutcome,settlementToken:o.settlementToken,fulfilment:o.fulfilment}}let p=o.agent?{astraId:o.agent.astraId,name:o.agent.name,trustScore:o.agent.trustScore,trustLevel:Xe(o.agent.trustScore),blockchainVerified:o.agent.blockchainStatus==="verified",status:o.agent.agentStatus}:void 0,u=o.developer?{astradId:o.developer.kyaOwnerId,name:o.developer.fullName,trustScore:o.developer.trustScore||0,verified:o.developer.identityVerified}:void 0,y=o.organization?{name:o.organization.name,verified:o.organization.verified,trustScore:o.organization.trustScore}:void 0,h=o.verificationContext,l={identityVerified:o.verificationContext?.idVerified===!0,policyAllowed:!0,agent:p,developer:u,organization:y,appliedPolicy:o.access?.appliedPolicy,verificationContext:h,requiresStepUp:o.access?.requiresStepUp,requiresApproval:o.access?.requiresApproval,verifiedAt:new Date,cacheTtl:n.cacheTtl,sessionId:o.sessionId,correlationId:o.correlationId,attemptId:o.attemptId,runtimeChallenge:o.runtimeChallenge,tokenGuidance:o.tokenGuidance,recommendation:o.recommendation,recommendationReasons:o.recommendationReasons,warningHeader:o.warningHeader,stepUpApproval:o.stepUpApproval,settlement:o.settlement,settlementOutcome:o.settlementOutcome,settlementToken:o.settlementToken,fulfilment:o.fulfilment};l.recommendation==="deny"?(l.policyAllowed=!1,l.denialReasons=c??l.recommendationReasons??["Access denied by AstraSync recommendation"],l.guidance=l.runtimeChallenge?{message:`Verification failed: ${l.runtimeChallenge.reason||"runtime challenge failed"}`,registrationUrl:a?.registrationUrl??"",documentationUrl:a?.documentationUrl??""}:{message:l.recommendationReasons?.[0]||"Access denied by AstraSync recommendation",registrationUrl:a?.registrationUrl??"",documentationUrl:a?.documentationUrl??""}):l.recommendation==="step_up_required"&&(l.requiresStepUp=!0,l.denialReasons=c??l.recommendationReasons??["Step-up verification required"]);let f=l.requiresStepUp===!0||l.requiresApproval===!0||l.recommendation==="step_up_required";return n.cacheTtl!==0&&l.recommendation!=="deny"&&!f&&Qe(t,l,n.cacheTtl,n.counterpartyId),l}async function tt(e,t){let r=e.apiBaseUrl||q.apiBaseUrl,{counterpartyUrl:n,...a}=t,i={...a,...n&&{counterpartyUrl:n},...e.counterpartyId&&{counterpartyId:e.counterpartyId}};await C(`${r}/verification-activity/unregistered-attempt`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)}).catch(()=>{})}function g(e,t){return e.headers[t.toLowerCase()]}function rt(e,t){let r=e.querystring?`?${e.querystring}`:"";return`https://${t}${e.uri}${r}`}function M(e){let{headers:t,apiKeyFormat:r,platformHeaders:n,cookieCount:a}=Q(e.headers),i=e.connection??{},o=ot(e.querystring);return{headers:t,...r&&{apiKeyFormat:r},...n&&{platformHeaders:n},...Object.keys(i).length>0&&{connection:i},...a!==void 0&&{cookieCount:a},...o&&{queryKeys:o},schemaVersion:ke}}var nt=32,at=64;function ot(e){if(!e)return;let t;try{t=new URLSearchParams(e)}catch{return}let r=[];for(let n of t.keys()){let a=n.toLowerCase().slice(0,at);if(a&&!r.includes(a)&&(r.push(a),r.length>=nt))break}return r.length>0?r:void 0}var it=/^eyJ[\w-]+\.[\w-]*\.[\w-]+~/;function st(e){let t=e.replace(/-/g,"+").replace(/_/g,"/"),r=t+"=".repeat((4-t.length%4)%4),n=atob(r),a=new Uint8Array(n.length);for(let i=0;i<n.length;i++)a[i]=n.charCodeAt(i);return new TextDecoder().decode(a)}function ct(e){try{let t=e.split(".")[0];return JSON.parse(st(t))}catch{return}}function dt(e){if(e)try{let t=JSON.parse(e);return typeof t=="object"&&t!==null?t:void 0}catch{return}}function ut(e,t){let r=rt(e,t),n=e.method,a=e.headers,i=dt(e.bodyText),o=e.bodyTruncated?{bodyTruncated:!0}:{},s=g(e,"authorization"),c=s?.replace(/^Bearer\s+/i,""),u=[g(e,"x-payment-mandate")??g(e,"payment-mandate"),c].find(f=>f&&it.test(f));if(u){let f=ct(u)?.typ;return{protocol:"vi-sd-jwt",artifacts:{viSdJwt:u},evidence:{typ:f,...o}}}let y=g(e,"signature"),h=g(e,"signature-input");if(y&&h){let f=g(e,"signature-agent"),d=g(e,"x-agent-registry"),m=h.toLowerCase();return{protocol:f?"rfc9421-web-bot-auth":d?.toLowerCase().includes("visa")||m.includes("visa")?"rfc9421-tap":d?.toLowerCase().includes("mastercard")||m.includes("mastercard")?"rfc9421-agent-pay":"rfc9421",artifacts:{rfc9421:{headers:a,method:n,url:r,...e.bodyText&&{body:e.bodyText}}},evidence:{...f&&{signatureAgent:f},...d&&{registryHint:d},keyid:h.match(/keyid="([^"]+)"/)?.[1],...o}}}let l=g(e,"timestamp");if(y&&!h&&(l||g(e,"idempotency-key")))return{protocol:"acp",artifacts:{acpRequest:{method:n,url:r,headers:a,...e.bodyText&&{rawBody:e.bodyText},...i&&{body:i}}},evidence:{hasTimestamp:!!l,...o}};if(/\/checkout[-_]sessions(\/|$)/.test(e.uri))return{protocol:"ucp",artifacts:{ucpRequest:{method:n,url:r,...i&&{body:i}}},evidence:{path:e.uri,...o}};if(i){let f=i.intent_mandate??i.intentMandate,d=i.cart_mandate??i.cartMandate,m=i.payment_mandate??i.paymentMandate;if(typeof f=="string"||typeof d=="string"||typeof m=="string")return{protocol:"ap2",artifacts:{ap2Mandates:{...typeof f=="string"&&{intent:f},...typeof d=="string"&&{cart:d},...typeof m=="string"&&{payment:m}}},evidence:{mandatesPresent:[typeof f=="string"&&"intent",typeof d=="string"&&"cart",typeof m=="string"&&"payment"].filter(Boolean),...o}}}if(s&&/^Payment\s+/i.test(s))return{protocol:"mpp",artifacts:{mppRequest:{method:n,url:r,headers:a,...e.bodyText&&{rawBody:e.bodyText},...i&&{body:i}}},evidence:o};if(g(e,"x-payment"))return{protocol:"x402",artifacts:{x402Request:{method:n,url:r,headers:a,...i&&{body:i}}},evidence:o}}var lt=/\.(css|js|mjs|map|png|jpe?g|gif|webp|avif|svg|ico|woff2?|ttf|otf|eot|mp4|webm|pdf|txt|xml)$/i,pt=/^astrasync-sdk\//i,ft=/curl|wget|python-requests|python-urllib|node-fetch|axios|got|okhttp|go-http-client|libwww|httpie|java\/|ruby|php|scrapy|headless|phantomjs|selenium|playwright|puppeteer|bot|crawler|spider|slurp/i,gt=/mozilla\/\d/i;function yt(e,t){if(lt.test(t))return{mode:e.mode,depth:e.depth,skip:!0};let r=_e(e.pathRules,t);return r?{mode:r.mode??e.mode,depth:r.depth??e.depth,skip:r.skip===!0}:{mode:e.mode,depth:e.depth,skip:!1}}function mt(e,t,r){let n=g(e,"user-agent")??"";if(pt.test(n))return{tier:"self"};let a=re(e.headers,{});if(a.astraId||a.apiKey||a.jwt)return{tier:"verified",protocol:"x-astra"};let{apiKeyFormat:i,platformHeaders:o}=Q(e.headers),s={userAgent:n,apiKeyFormat:i,platformHeaders:o};if(r!=="classify"){let p=ut(e,t);if(p)return{tier:"identified",protocol:p.protocol,artifacts:p.artifacts,evidence:p.evidence,fingerprint:j(s)}}let c=j(s);return c?{tier:"identified",protocol:"platform-ua",fingerprint:c}:!n||ft.test(n)||!gt.test(n)?{tier:"anonymous-bot",evidence:{userAgent:n||"(none)"}}:!g(e,"sec-fetch-mode")&&!g(e,"accept-language")?{tier:"anonymous-bot",evidence:{userAgent:n,spoofedBrowser:!0}}:{tier:"human"}}var ht={"vi-sd-jwt":"This request presented Visa Intelligent Commerce credentials, but the agent is not verified with AstraSync. Register the agent to pair your VI credentials with a verified identity and mandate.","rfc9421-agent-pay":"This request carried a Mastercard Agent Pay signature, but the agent is not verified with AstraSync. Register the agent to pair Agent Pay credentials with a verified identity and mandate.","rfc9421-tap":"This request carried a Visa TAP signature, but the agent is not verified with AstraSync. Register the agent to pair TAP credentials with a verified identity and mandate.","rfc9421-web-bot-auth":"This request carried a Web Bot Auth signature, but the agent is not verified with AstraSync. Register the agent to link your signed-agent identity to a verified principal.",rfc9421:"This request carried an RFC 9421 HTTP message signature, but the agent is not verified with AstraSync. Register the agent to link the signing identity to a verified principal.",acp:"This request used the Agentic Commerce Protocol, but the agent is not verified with AstraSync. Register the agent to transact on this property.",ucp:"This request used a UCP checkout session, but the agent is not verified with AstraSync. Register the agent to transact on this property.",ap2:"This request presented AP2 mandates, but the agent is not verified with AstraSync. Register the agent to pair your mandates with a verified identity.",mpp:"This request presented MPP payment credentials, but the agent is not verified with AstraSync. Register the agent to transact on this property.",x402:"This request used x402 payment headers, but the agent is not verified with AstraSync. Register the agent to transact on this property.","platform-ua":"This traffic was identified as a platform AI agent without AstraSync credentials. Register the agent to access this property with a verified identity.","x-astra":"The presented AstraSync credentials failed verification or were denied by this property\u2019s access policy."};function vt(e){try{let t=new URL(e).hostname.replace(/^www\./,"");if(t==="astrasync.ai"||t.endsWith(".astrasync.ai"))return`https://mcp.${t}/mcp`}catch{}}function At(e,t,r){let n=(r||t).replace(/\/api\/?$/,""),a=e.guidance?.mcp?.endpoint||vt(n),i=(e.protocol&&ht[e.protocol])??"This request could not be verified by AstraSync.";return{success:!1,error:{code:e.tier==="verified"?"INSUFFICIENT_ACCESS":"UNAUTHORIZED",message:i,...e.protocol&&{protocol:e.protocol},failures:e.reasons,...e.correlationId&&{correlationId:e.correlationId},guidance:{message:e.guidance?.message||"Register this agent with AstraSync to receive verifiable credentials.",registrationUrl:e.guidance?.registrationUrl||`${n}/register`,documentationUrl:e.guidance?.documentationUrl||`${n}/docs/edge-adapter`,...a&&{mcp:{endpoint:a,discoveryUrl:e.guidance?.mcp?.discoveryUrl||`${a.replace(/\/mcp$/,"")}/.well-known/mcp.json`,message:e.guidance?.mcp?.message||"Inside an MCP host? Add the AstraSync MCP connector at this endpoint instead of the registration URL \u2014 registration through the connector is keyless and human-approved (your human approves in an in-chat card; you never handle credentials)."}}}}}}function wt(e){return{success:!1,error:{code:"VERIFICATION_UNAVAILABLE",message:"Agent verification is temporarily unavailable and this path enforces verification. Your identity was not evaluated and no denial was recorded \u2014 retry with exponential backoff.",failures:e.reasons,...e.correlationId&&{correlationId:e.correlationId},guidance:{message:"Retry the request with exponential backoff; the condition is transient."}}}}function bt(e){return{success:!1,status:"manual_review",message:"This action requires human approval. Poll the step-up approval endpoint and retry once approved.",...e.stepUp&&{stepUpApproval:e.stepUp},...e.correlationId&&{correlationId:e.correlationId}}}var Rt="X-Astra-Verified-Hop";function St(e){return`${e.astraId};${e.sessionId??""};${e.checkedAt}`}var w={trustScore:"X-AstraSync-Trust-Score",agentId:"X-AstraSync-Agent-Id",developerId:"X-AstraSync-Developer-Id",observedDecision:"X-AstraSync-Observed-Decision"},V=["x-astrasync-","x-astra-verified-hop"];function x(){return{action:"pass",injectHeaders:{},stripHeaderPrefixes:[]}}function It(e,t,r){let n={};if(t.misconfig&&(n[w.observedDecision]="misconfig"),r.mode!=="enforce")return t.decision!=="allow"&&(n[w.observedDecision]=t.decision),Object.assign(n,G(t),z(t)),{action:"pass",injectHeaders:n,stripHeaderPrefixes:V};switch(t.decision){case"deny":return t.unavailable?{action:"respond",status:503,headers:{"Retry-After":"30"},bodyJson:wt(t)}:{action:"respond",status:403,headers:{},bodyJson:At(t,e.apiBaseUrl,e.publicBaseUrl)};case"manual_review":return{action:"respond",status:202,headers:{"Retry-After":"30"},bodyJson:bt(t)};default:return Object.assign(n,G(t),z(t)),{action:"pass",injectHeaders:n,stripHeaderPrefixes:V}}}function G(e){if(!e.asat)return{};let{trustScore:t,agentId:r,developerId:n}=e.asat;return{...t!==void 0&&{[w.trustScore]:String(t)},...r&&{[w.agentId]:r},...n&&{[w.developerId]:n}}}function z(e){let t=e.asat?.agentId;return t?{[Rt]:St({astraId:t,...e.sessionId&&{sessionId:e.sessionId},checkedAt:Date.now()})}:{}}var Ct={GET:"data.read",HEAD:"data.read",OPTIONS:"data.read",POST:"data.write",PUT:"data.write",PATCH:"data.write",DELETE:"data.delete"},Et="data.write",Tt="data";function Ut(e){return Ct[e.toUpperCase()]??Et}function Pt(e){let t=e.indexOf(":");if(t>=0)return{purpose:e.slice(0,t)};let r=e.indexOf(".");return r>0&&r<e.length-1?{purpose:e.slice(0,r),actionCandidate:e}:{purpose:e}}function _t(e){let t=e.astraPurpose?Pt(e.astraPurpose):void 0,r,n;e.routeAction?(r=e.routeAction,n="route_config"):e.hasCustomActionExtractor&&e.customAction?(r=e.customAction,n="custom_extractor"):!e.hasCustomActionExtractor&&e.astraAction?(r=e.astraAction,n="header"):!e.hasCustomActionExtractor&&t?.actionCandidate?(r=t.actionCandidate,n="purpose_header_derived"):(r=Ut(e.method),n="method_table");let a,i;if(e.routePurpose?(a=e.routePurpose,i="route_config"):e.hasCustomPurposeExtractor?e.customPurpose&&(a=e.customPurpose,i="custom_extractor"):t?(a=t.purpose,i="header"):e.legacyPurpose?(a=e.legacyPurpose,i="legacy_header"):e.queryPurpose&&(a=e.queryPurpose,i="query"),!a){let o=r.indexOf(".");o>0?(a=r.slice(0,o),i="action_derived"):(a=Tt,i="transport_default")}return{purpose:a,action:r,purposeSource:i,actionSource:n}}async function O(e,t){let r;try{return await Promise.race([e,new Promise(n=>{r=setTimeout(()=>n(void 0),t)})])}catch{return}finally{r&&clearTimeout(r)}}async function X(e,t,r,n){let a=O(tt({apiBaseUrl:e.apiBaseUrl,counterpartyId:e.counterpartyId},{counterpartyUrl:e.counterpartyUrl,counterpartyType:"website",sourceIp:t.clientIp,userAgent:g(t,"user-agent"),requestPath:t.uri,requestMethod:t.method,protocol:r.protocol,evidence:r.evidence,observedMetadata:M(t)}),n);if(e.waitUntil){e.waitUntil(a);return}await a}function xt(e,t=Math.random){return e<=0?!1:e>=1?!0:t()<e}function v(e){return{tier:e.tier,decision:"allow",reasons:[],protocol:e.protocol}}function Y(e,t,r,n){let a=_t({method:t.method,astraPurpose:g(t,"x-astra-purpose"),astraAction:g(t,"x-astra-action")}),i=g(t,"x-astra-attempt-id");return{...i&&/^att_[0-9a-f]{32}$/.test(i)&&{attemptId:i},credentials:re(t.headers,{}),purpose:a.purpose,action:a.action,resource:t.uri,createSession:!0,counterpartyType:"website",counterpartyUrl:e.counterpartyUrl,callerMetadata:{sourceIp:t.clientIp,userAgent:g(t,"user-agent"),referer:g(t,"referer"),host:g(t,"host"),observedMetadata:M(t)},...n&&r.artifacts&&{commerceArtifacts:r.artifacts}}}function J(e,t){let r=v(e);return r.sessionId=t.sessionId,r.correlationId=t.correlationId,r.guidance=t.guidance,t.misconfigured?(r.reasons=["verification key misconfigured \u2014 fail-open (merchant_misconfig)"],r.misconfig=!0,r):t.requiresStepUp||t.stepUpApproval?(r.decision="manual_review",r.reasons=["step-up approval required"],r.stepUp={pollUrl:t.stepUpApproval?.pollUrl,expiresAt:t.stepUpApproval?.expiresAt},r):!t.identityVerified||!t.policyAllowed?(r.decision="deny",r.reasons=t.denialReasons?.length?t.denialReasons:[t.identityVerified?"denied by access policy":"identity not verified"],r):(r.asat={trustScore:t.agent?.trustScore,agentId:t.agent?.astraId,developerId:t.developer?.astradId},r)}function I(e,t,r,n){let a=v(e);return a.unavailable=!0,a.reasons=[r],n&&(a.correlationId=n),t.mode==="enforce"&&(a.decision="deny"),a}function W(e){return(e.failures??[]).some(t=>t.dimension==="verify_access.api_error")===!0&&!e.misconfigured}async function kt(e,t,r,n,a,i){let o=e.budgets??{},s=o.beaconMs??300,c=n.mode==="enforce"?o.verifyEnforceMs??3e3:o.verifyObserveMs??1500,p={apiBaseUrl:e.apiBaseUrl,...a&&{apiKey:a},counterpartyId:e.counterpartyId,disableInitChecks:!0};try{switch(r.tier){case"verified":{if(n.depth==="classify")return v(r);let u=await O(K(p,Y(e,t,r,n.depth==="authorize")),c);return u?W(u)?I(r,n,u.denialReasons?.[0]??"verify-access api error",u.correlationId):J(r,u):I(r,n,"verify-access unreachable within budget")}case"identified":{if(n.depth==="authorize"&&r.artifacts){let y=await O(K(p,Y(e,t,r,!0)),c);return y?W(y)?I(r,n,y.denialReasons?.[0]??"verify-access api error",y.correlationId):J(r,y):I(r,n,"verify-access unreachable within budget")}await X(e,t,r,s);let u=v(r);return n.mode==="enforce"&&n.depth!=="classify"&&(u.decision="deny",u.reasons=["agent is not registered with AstraSync"]),u}case"anonymous-bot":return xt(i.anonymousBeaconRate,e.random)&&await X(e,t,{...r,protocol:r.protocol??"ua-heuristic"},s),v(r);default:return v(r)}}catch(u){let y=v(r);return y.reasons=[`edge pipeline error \u2014 fail-open: ${u instanceof Error?u.message:String(u)}`],y}}async function ne(e,t,r,n){let a=yt(r,t.uri);try{if(a.skip)return{policy:a,application:x()};let i=g(t,"x-forwarded-host")??g(t,"host")??new URL(e.counterpartyUrl).host,o=mt(t,i,a.depth);if(o.tier==="human"||o.tier==="self")return{policy:a,classification:o,application:x()};let s=await kt(e,t,o,a,n,r.sampling);return s.decision!=="allow"&&e.log?.("info",a.mode==="enforce"?`${s.decision.toUpperCase()}: ${t.method} ${t.uri}`:`[OBSERVE] would have been ${s.decision.toUpperCase()}: ${t.method} ${t.uri}`,{tier:s.tier,protocol:s.protocol,reasons:s.reasons}),{policy:a,classification:o,outcome:s,application:It(e,s,a)}}catch(i){return e.log?.("error","edge evaluation error \u2014 passing request through",{error:i instanceof Error?i.message:String(i)}),{policy:a,application:x()}}}function T(e){return e.Records[0].cf.request}function A(e,t){return e.headers[t.toLowerCase()]?.[0]?.value}function Ot(e){let t={};for(let[r,n]of Object.entries(e))n?.length&&(t[r]=n.map(a=>a.value).join(", "));return t}function Mt(e){let t=e.body;return t?.data?{text:t.encoding==="base64"?Buffer.from(t.data,"base64").toString("utf8"):t.data,truncated:t.inputTruncated===!0}:{truncated:!1}}function Ft(e){let t={},r=(i,o,s)=>{let c=A(e,o);c&&(t[i]=s?s(c):c)},n=A(e,"cloudfront-viewer-address");if(n){t.ip=n.replace(/:\d+$/,"");let i=n.match(/:(\d+)$/);i&&(t.sourcePort=i[1])}r("country","cloudfront-viewer-country"),r("countryName","cloudfront-viewer-country-name"),r("region","cloudfront-viewer-country-region"),r("countryRegionName","cloudfront-viewer-country-region-name"),r("city","cloudfront-viewer-city"),r("latitude","cloudfront-viewer-latitude"),r("longitude","cloudfront-viewer-longitude"),r("postalCode","cloudfront-viewer-postal-code"),r("asn","cloudfront-viewer-asn"),r("tlsVersion","cloudfront-viewer-tls");{let i=A(e,"cloudfront-viewer-tls")?.split(":")[1];i&&(t.tlsCipher=i)}r("httpVersion","cloudfront-viewer-http-version"),r("timeZone","cloudfront-viewer-time-zone"),r("metroCode","cloudfront-viewer-metro-code"),r("tlsFingerprint","cloudfront-viewer-ja3-fingerprint"),r("ja4","cloudfront-viewer-ja4-fingerprint"),r("headerOrder","cloudfront-viewer-header-order",i=>i.slice(0,256)),r("headerCount","cloudfront-viewer-header-count");let a=[];for(let[i,o]of[["desktop","cloudfront-is-desktop-viewer"],["mobile","cloudfront-is-mobile-viewer"],["tablet","cloudfront-is-tablet-viewer"],["smarttv","cloudfront-is-smarttv-viewer"]])A(e,o)==="true"&&a.push(i);return a.length&&(t.device=a.join(",")),t}function ae(e){let t=Mt(e),r=Ft(e),n=A(e,"cloudfront-viewer-address")?.split(":")[0];return{method:e.method,uri:e.uri,querystring:e.querystring??"",headers:Ot(e.headers),...t.text!==void 0&&{bodyText:t.text},...t.truncated&&{bodyTruncated:!0},...n&&{clientIp:n},...Object.keys(r).length>0&&{connection:r}}}function oe(e,t){if(t.action==="respond")return Nt(t.status,t.bodyJson,t.headers);for(let r of t.stripHeaderPrefixes)Dt(e,r);for(let[r,n]of Object.entries(t.injectHeaders))F(e,r,n);return e}function ie(e){let t=e.origin?.custom?.domainName??e.origin?.s3?.domainName??void 0;if(!t)return;let r=A(e,"host");!r||r===t||(A(e,"x-forwarded-host")||F(e,"X-Forwarded-Host",r),F(e,"Host",t))}function F(e,t,r){e.headers[t.toLowerCase()]=[{key:t,value:r}]}function Dt(e,t){let r=t.toLowerCase();for(let n of Object.keys(e.headers))n.startsWith(r)&&delete e.headers[n]}function Nt(e,t,r){let n={"content-type":[{key:"Content-Type",value:"application/json"}]};for(let[a,i]of Object.entries(r??{}))n[a.toLowerCase()]=[{key:a,value:i}];return{status:String(e),statusDescription:e===403?"Forbidden":e===202?"Accepted":"OK",headers:n,body:JSON.stringify(t)}}var Bt="5.6.0",U=`astrasync-sdk/${Bt}`;function Ht(e){if(!e)return{"user-agent":U};if(e instanceof Headers){let r=new Headers(e);return r.has("user-agent")||r.set("user-agent",U),r}return Array.isArray(e)?e.some(([n])=>n.toLowerCase()==="user-agent")?e:[...e,["user-agent",U]]:Object.keys(e).some(r=>r.toLowerCase()==="user-agent")?e:{"user-agent":U,...e}}var jt=(e,t)=>fetch(e,{...t,headers:Ht(t?.headers)}),N=Object.freeze({version:1,mode:"observe",depth:"classify",pathRules:[],sampling:Object.freeze({anonymousBeaconRate:.1}),failurePosture:"open"}),se=["observe","enforce"],ce=["classify","authenticate","authorize"];function $t(e){if(typeof e!="object"||e===null)return!1;let t=e;if(t.version!==1||!se.includes(t.mode)||!ce.includes(t.depth)||!Array.isArray(t.pathRules))return!1;for(let n of t.pathRules){if(typeof n!="object"||n===null)return!1;let a=n;if(typeof a.pattern!="string"||a.pattern.length===0||a.mode!==void 0&&!se.includes(a.mode)||a.depth!==void 0&&!ce.includes(a.depth))return!1}let r=t.sampling;return typeof r!="object"||r===null||typeof r.anonymousBeaconRate!="number"||r.anonymousBeaconRate<0||r.anonymousBeaconRate>1?!1:t.failurePosture==="open"}async function Lt(e,t,r){if(!t)return null;let n={Accept:"application/json"};e.apiKey&&(n.Authorization=`Bearer ${e.apiKey}`,n["X-API-Key"]=e.apiKey),r?.etag&&(n["If-None-Match"]=r.etag);try{let a=await jt(`${e.apiBaseUrl}/endpoints/${encodeURIComponent(t)}/edge-config`,{method:"GET",headers:n,signal:AbortSignal.timeout(r?.timeoutMs??5e3)});if(a.status===304)return{notModified:!0};if(!a.ok)return null;let o=(await a.json()).data?.edgeConfig;return $t(o)?{edgeConfig:o,etag:a.headers.get("etag")??void 0}:null}catch{return null}}var Kt=60*1e3,Vt=1440*60*1e3,b=new Map,D=new Map;function ue(e,t){return`${e}|${t}`}function Gt(e){return e.mode!=="enforce"&&!e.pathRules.some(t=>t.mode==="enforce")?e:{...e,mode:"observe",pathRules:e.pathRules.map(t=>t.mode==="enforce"?{...t,mode:"observe"}:t)}}async function de(e,t){let r=ue(e.apiBaseUrl,t),n=D.get(r);if(n)return n;let a=Lt(e,t,{etag:b.get(r)?.etag}).then(i=>{if(i===null)return;let o=Date.now();if("notModified"in i){let s=b.get(r);s&&(s.lastSuccessAt=o);return}b.set(r,{config:i.edgeConfig,etag:i.etag,lastSuccessAt:o})}).finally(()=>{D.delete(r)});return D.set(r,a),a}async function le(e,t,r){let n=r?.ttlMs??Kt,a=r?.maxStaleMs??Vt,i=ue(e.apiBaseUrl,t),o=b.get(i);if(o){let s=Date.now()-o.lastSuccessAt;return s>n&&de(e,t).catch(()=>{}),s>a?Gt(o.config):o.config}return await de(e,t).catch(()=>{}),b.get(i)?.config??N}var zt=900*1e3,pe=new Map;async function Xt(e){let{SecretsManagerClient:t,GetSecretValueCommand:r}=await import("@aws-sdk/client-secrets-manager");return(await new t({region:"us-east-1"}).send(new r({SecretId:e}))).SecretString??void 0}async function fe(e){if(e.apiKey)return e.apiKey;let t=e.apiKeySecretName;if(!t)return;let r=pe.get(t);if(r&&Date.now()-r.fetchedAt<zt)return r.value;try{let a=await(e.fetchSecret??Xt)(t);return pe.set(t,{value:a,fetchedAt:Date.now()}),a}catch(n){return e.log?.("warn","Secrets Manager fetch failed \u2014 continuing keyless",{secretName:t,error:n instanceof Error?n.message:String(n)}),r?.value}}async function ge(e,t){try{return await le({apiBaseUrl:e.apiBaseUrl,apiKey:t},e.counterpartyId,{ttlMs:e.configTtlMs})}catch{return e.fallbackConfig??N}}function ye(e){let t=e.log??((r,n,a)=>{console[r==="info"?"log":r](`[astrasync-edge] ${n}`,a??"")});return async function(n){let a=T(n);try{ie(a);let i=await fe({...e,log:t}),o=await ge(e,i),{application:s}=await ne({...e,log:t},ae(a),o,i);return oe(a,s)}catch(i){return t("error","edge handler error \u2014 passing request through",{error:i instanceof Error?i.message:String(i)}),a}}}var Yt={apiBaseUrl:"x-astrasync-api-base-url",publicBaseUrl:"x-astrasync-public-base-url",counterpartyId:"x-astrasync-counterparty-id",counterpartyUrl:"x-astrasync-counterparty-url",apiKeySecretName:"x-astrasync-api-key-secret-name"};function Jt(e,t){return e.origin?.custom?.customHeaders?.[t]?.[0]?.value||void 0}function me(e,t){let r=n=>Jt(e,Yt[n]);return{apiBaseUrl:r("apiBaseUrl")??t.apiBaseUrl,publicBaseUrl:r("publicBaseUrl")??t.publicBaseUrl,counterpartyId:r("counterpartyId")??t.counterpartyId,counterpartyUrl:r("counterpartyUrl")??t.counterpartyUrl,apiKeySecretName:r("apiKeySecretName")??t.apiKeySecretName}}function he(e){return[e.apiBaseUrl,e.publicBaseUrl??"",e.counterpartyId,e.counterpartyUrl,e.apiKeySecretName??""].join("|")}var Wt={apiBaseUrl:"https://astrasync.ai/api",publicBaseUrl:void 0,counterpartyId:"",counterpartyUrl:"",apiKeySecretName:void 0},ve=new Map,Ae=!1,Zt=async e=>{let t=me(T(e),Wt);(!t.counterpartyId||!t.counterpartyUrl)&&(Ae||(Ae=!0,console.error("[astrasync-edge] counterpartyId/counterpartyUrl missing \u2014 set the X-AstraSync-* origin custom headers on the distribution (see infra/template.yaml) or bake ASTRASYNC_* constants via infra/deploy.sh.")));let r=he(t),n=ve.get(r);return n||(n=ye(t),ve.set(r,n)),n(e)};0&&(module.exports={handler});
package/infra/deploy.sh CHANGED
@@ -15,6 +15,13 @@ set -euo pipefail
15
15
  # outright). Direct origin also saves a CloudFront hop per call.
16
16
  # e.g. https://staging-origin.astrasync.ai/api — NOT https://staging.astrasync.ai/api
17
17
  export ASTRASYNC_API_BASE_URL="${ASTRASYNC_API_BASE_URL:?Set ASTRASYNC_API_BASE_URL to the backend's DIRECT origin URL (never the CloudFront-fronted hostname — see comment above)}"
18
+ # 2.6.0 two-plane URL doctrine: the API base above is the VERIFY plane (direct
19
+ # origin). ASTRASYNC_PUBLIC_BASE_URL is the AGENT-GUIDANCE plane — the public
20
+ # host templated into deny-body registration/docs/mcp URLs, which agents DO
21
+ # follow (the direct-origin host must never leak there). Optional: unset →
22
+ # guidance falls back to the API base host (only correct when that IS the
23
+ # public apex). e.g. https://staging.astrasync.ai
24
+ export ASTRASYNC_PUBLIC_BASE_URL="${ASTRASYNC_PUBLIC_BASE_URL:-}"
18
25
  export ASTRASYNC_COUNTERPARTY_ID="${ASTRASYNC_COUNTERPARTY_ID:?Set ASTRASYNC_COUNTERPARTY_ID to the property's ASTRAE-id}"
19
26
  export ASTRASYNC_COUNTERPARTY_URL="${ASTRASYNC_COUNTERPARTY_URL:?Set ASTRASYNC_COUNTERPARTY_URL, e.g. https://staging.astrasync.ai}"
20
27
  export ASTRASYNC_API_KEY_SECRET_NAME="${ASTRASYNC_API_KEY_SECRET_NAME:-astrasync/edge/staging-astrasync-ai}"
@@ -42,7 +49,11 @@ sam deploy \
42
49
  "OriginDomainName=${ORIGIN_DOMAIN}" \
43
50
  "SiteDomainName=${SITE_DOMAIN}" \
44
51
  "AcmCertificateArn=${ACM_CERT_ARN}" \
45
- "ApiKeySecretName=${ASTRASYNC_API_KEY_SECRET_NAME}"
52
+ "ApiKeySecretName=${ASTRASYNC_API_KEY_SECRET_NAME}" \
53
+ "ApiBaseUrl=${ASTRASYNC_API_BASE_URL}" \
54
+ "PublicBaseUrl=${ASTRASYNC_PUBLIC_BASE_URL}" \
55
+ "CounterpartyId=${ASTRASYNC_COUNTERPARTY_ID}" \
56
+ "CounterpartyUrl=${ASTRASYNC_COUNTERPARTY_URL}"
46
57
 
47
58
  echo ">> Done. Outputs:"
48
59
  aws cloudformation describe-stacks --stack-name "${STACK_NAME}" --region us-east-1 \
@@ -29,8 +29,40 @@ Parameters:
29
29
  Default: astrasync/edge/staging-astrasync-ai
30
30
  Description: >
31
31
  Secrets Manager secret (us-east-1) holding the merchant kya_* API key.
32
- Referenced for IAM scoping only — the NAME is baked into the bundle at
33
- build time (Lambda@Edge forbids environment variables).
32
+ Used for IAM scoping AND delivered to the function as an origin custom
33
+ header (Lambda@Edge forbids environment variables).
34
+ ApiBaseUrl:
35
+ Type: String
36
+ Default: https://astrasync.ai/api
37
+ Description: >
38
+ AstraSync platform API base — the VERIFY plane. MUST reach the backend
39
+ DIRECTLY, never a hostname this (or any gateway-fronted) distribution
40
+ serves: routing it through the distribution makes every verify/beacon
41
+ call re-enter this Lambda.
42
+ PublicBaseUrl:
43
+ Type: String
44
+ Default: ''
45
+ Description: >
46
+ Optional AGENT-GUIDANCE plane base URL (two-plane doctrine) — the
47
+ public host templated into deny-body registration/docs/mcp URLs.
48
+ Blank = guidance falls back to ApiBaseUrl.
49
+ CounterpartyId:
50
+ Type: String
51
+ Default: ''
52
+ Description: >
53
+ This property's AstraSync counterparty id (ASTRAE-*) from the
54
+ dashboard. Blank ONLY for legacy bespoke builds that bake the id into
55
+ the bundle via infra/deploy.sh.
56
+ CounterpartyUrl:
57
+ Type: String
58
+ Default: ''
59
+ Description: >
60
+ Public URL registered for this endpoint. Blank = https://<SiteDomainName>.
61
+
62
+ Conditions:
63
+ HasPublicBaseUrl: !Not [!Equals [!Ref PublicBaseUrl, '']]
64
+ HasCounterpartyId: !Not [!Equals [!Ref CounterpartyId, '']]
65
+ HasCounterpartyUrl: !Not [!Equals [!Ref CounterpartyUrl, '']]
34
66
 
35
67
  Resources:
36
68
  EdgeFunctionRole:
@@ -63,7 +95,7 @@ Resources:
63
95
  Description: Trusted Agent Gateway edge interception shell (observe-only by default)
64
96
  # Lambda@Edge constraints: no env vars, us-east-1, versioned ARN
65
97
  # association. AutoPublishAlias gives us EdgeFunction.Version.
66
- Runtime: nodejs20.x
98
+ Runtime: nodejs22.x
67
99
  Handler: index.handler
68
100
  CodeUri: ../dist/lambda
69
101
  MemorySize: 512
@@ -162,6 +194,29 @@ Resources:
162
194
  CustomOriginConfig:
163
195
  OriginProtocolPolicy: https-only
164
196
  OriginSSLProtocols: [TLSv1.2]
197
+ # Per-deploy constants for the edge function (Lambda@Edge forbids
198
+ # env vars). Set by the deployer, never the viewer — the function
199
+ # reads them from request.origin.custom.customHeaders, so ONE
200
+ # immutable bundle serves every deploy (origin-config.ts). A
201
+ # header wins over any legacy baked constant.
202
+ OriginCustomHeaders:
203
+ - HeaderName: X-AstraSync-Api-Base-Url
204
+ HeaderValue: !Ref ApiBaseUrl
205
+ - !If
206
+ - HasPublicBaseUrl
207
+ - HeaderName: X-AstraSync-Public-Base-Url
208
+ HeaderValue: !Ref PublicBaseUrl
209
+ - !Ref AWS::NoValue
210
+ - !If
211
+ - HasCounterpartyId
212
+ - HeaderName: X-AstraSync-Counterparty-Id
213
+ HeaderValue: !Ref CounterpartyId
214
+ - !Ref AWS::NoValue
215
+ - HeaderName: X-AstraSync-Counterparty-Url
216
+ HeaderValue:
217
+ !If [HasCounterpartyUrl, !Ref CounterpartyUrl, !Sub 'https://${SiteDomainName}']
218
+ - HeaderName: X-AstraSync-Api-Key-Secret-Name
219
+ HeaderValue: !Ref ApiKeySecretName
165
220
  # 2.3.0 — static assets bypass the Lambda entirely, with caching ON.
166
221
  # classify.ts already skips static extensions inside the handler, so
167
222
  # associating the Lambda here only spent an invocation to decide
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrasyncai/adapter-lambda",
3
- "version": "2.5.0",
3
+ "version": "2.7.0",
4
4
  "description": "AstraSync Trusted Agent Gateway — Lambda@Edge/CloudFront adapter",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -15,7 +15,8 @@
15
15
  "files": [
16
16
  "dist",
17
17
  "infra",
18
- "README.md"
18
+ "README.md",
19
+ "INSTALL.md"
19
20
  ],
20
21
  "scripts": {
21
22
  "build": "tsup && node scripts/check-bundle-size.mjs",
@@ -46,7 +47,7 @@
46
47
  "directory": "packages/adapter-lambda"
47
48
  },
48
49
  "dependencies": {
49
- "@astrasyncai/verification-gateway": "^5.1.0",
50
+ "@astrasyncai/verification-gateway": "^5.2.0",
50
51
  "@aws-sdk/client-secrets-manager": "^3.632.0"
51
52
  },
52
53
  "devDependencies": {