@astrasyncai/adapter-lambda 1.0.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cf.ts","../src/config.ts","../src/classify.ts","../src/detect.ts","../src/pipeline.ts","../src/events.ts","../src/messaging.ts","../src/enforce.ts","../src/handler.ts"],"sourcesContent":["/**\n * CloudFront origin-request event helpers. The Lambda@Edge event shape puts\n * headers in `{ key, value }[]` arrays keyed by LOWERCASED header name, and\n * (with IncludeBody) the body arrives base64-encoded with an\n * `inputTruncated` flag when it exceeded CloudFront's ~1MB exposure cap.\n */\n\nimport type {\n CloudFrontRequest,\n CloudFrontRequestEvent,\n CloudFrontHeaders,\n CloudFrontResultResponse,\n} from 'aws-lambda';\n\nexport function getRequest(event: CloudFrontRequestEvent): CloudFrontRequest {\n return event.Records[0].cf.request;\n}\n\n/** First value of a header (lowercase name), or undefined. */\nexport function getHeader(request: CloudFrontRequest, name: string): string | undefined {\n return request.headers[name.toLowerCase()]?.[0]?.value;\n}\n\n/**\n * Flatten CloudFront headers into the `Record<string, string | string[]>`\n * shape the SDK extractors and verify-access artifacts expect.\n */\nexport function flattenHeaders(headers: CloudFrontHeaders): Record<string, string | string[]> {\n const out: Record<string, string | string[]> = {};\n for (const [name, entries] of Object.entries(headers)) {\n if (!entries?.length) continue;\n out[name] = entries.length === 1 ? entries[0].value : entries.map((e) => e.value);\n }\n return out;\n}\n\nexport interface DecodedBody {\n /** UTF-8 body text, undefined when there is no body. */\n text?: string;\n /** True when CloudFront truncated the body before handing it to the trigger. */\n truncated: boolean;\n}\n\nexport function decodeBody(request: CloudFrontRequest): DecodedBody {\n const body = request.body;\n if (!body?.data) return { truncated: false };\n const text =\n body.encoding === 'base64' ? Buffer.from(body.data, 'base64').toString('utf8') : body.data;\n return { text, truncated: body.inputTruncated === true };\n}\n\n/** Full request URL as the origin will see it (scheme fixed to https). */\nexport function requestUrl(request: CloudFrontRequest, host: string): string {\n const qs = request.querystring ? `?${request.querystring}` : '';\n return `https://${host}${request.uri}${qs}`;\n}\n\n/**\n * Set a header on the origin-bound request (overwrites all prior values).\n */\nexport function setHeader(request: CloudFrontRequest, name: string, value: string): void {\n request.headers[name.toLowerCase()] = [{ key: name, value }];\n}\n\n/**\n * Strip every inbound header matching a prefix (lowercase compare). Used to\n * drop spoofed `x-astrasync-*` trust headers before the shell injects its\n * own — in BOTH modes, so a caller can never smuggle trust past the origin.\n */\nexport function stripHeadersByPrefix(request: CloudFrontRequest, prefix: string): void {\n const p = prefix.toLowerCase();\n for (const name of Object.keys(request.headers)) {\n if (name.startsWith(p)) delete request.headers[name];\n }\n}\n\nexport function jsonResponse(\n status: number,\n body: unknown,\n extraHeaders?: Record<string, string>\n): CloudFrontResultResponse {\n const headers: CloudFrontResultResponse['headers'] = {\n 'content-type': [{ key: 'Content-Type', value: 'application/json' }],\n };\n for (const [name, value] of Object.entries(extraHeaders ?? {})) {\n headers[name.toLowerCase()] = [{ key: name, value }];\n }\n return {\n status: String(status),\n statusDescription: status === 403 ? 'Forbidden' : status === 202 ? 'Accepted' : 'OK',\n headers,\n body: JSON.stringify(body),\n };\n}\n","/**\n * Runtime configuration for the edge shell.\n *\n * Lambda@Edge forbids environment variables, so configuration is layered:\n * 1. Build-time constants baked into the bundle (apiBaseUrl,\n * counterpartyId, counterpartyUrl, apiKeySecretName) — see\n * `tsup.config.ts` define block and `infra/deploy.sh`.\n * 2. The merchant API key from AWS Secrets Manager (us-east-1), fetched\n * lazily once per container and cached with a 15-minute TTL so\n * rotation needs no redeploy. Observe mode works fully without it —\n * the beacon endpoint is unauthenticated and verify() degrades\n * keyless — so a Secrets Manager outage can never take the shell down.\n * 3. The dashboard EdgeConfig via the SDK's getEdgeConfig (60s TTL,\n * stale-while-revalidate, enforce→observe degradation after 24h\n * staleness, DEFAULT_EDGE_CONFIG fallback — all in the SDK).\n */\n\nimport {\n getEdgeConfig,\n DEFAULT_EDGE_CONFIG,\n type EdgeConfig,\n} from '@astrasyncai/verification-gateway/edge-config';\nimport type { EdgeAdapterOptions } from './types';\n\nconst SECRET_TTL_MS = 15 * 60 * 1000;\n\ninterface SecretCacheEntry {\n value: string | undefined;\n fetchedAt: number;\n}\n\nconst secretCache = new Map<string, SecretCacheEntry>();\n\nasync function defaultFetchSecret(secretName: string): Promise<string | undefined> {\n // Lazy import so tests (and the library build) never touch the AWS SDK\n // unless a secret name is actually configured.\n const { SecretsManagerClient, GetSecretValueCommand } =\n await import('@aws-sdk/client-secrets-manager');\n // Lambda@Edge replicates globally but secrets live in us-east-1 (the\n // Lambda@Edge home region).\n const client = new SecretsManagerClient({ region: 'us-east-1' });\n const result = await client.send(new GetSecretValueCommand({ SecretId: secretName }));\n return result.SecretString ?? undefined;\n}\n\n/**\n * Resolve the merchant API key. Never throws — a missing/unreachable secret\n * degrades to keyless operation (observe mode is fully functional without\n * it; enforce mode without a key cannot fetch a config that enforces, so it\n * degrades to observe by construction).\n */\nexport async function resolveApiKey(options: EdgeAdapterOptions): Promise<string | undefined> {\n if (options.apiKey) return options.apiKey;\n const secretName = options.apiKeySecretName;\n if (!secretName) return undefined;\n\n const cached = secretCache.get(secretName);\n if (cached && Date.now() - cached.fetchedAt < SECRET_TTL_MS) return cached.value;\n\n try {\n const fetcher = options.fetchSecret ?? defaultFetchSecret;\n const value = await fetcher(secretName);\n secretCache.set(secretName, { value, fetchedAt: Date.now() });\n return value;\n } catch (err) {\n options.log?.('warn', 'Secrets Manager fetch failed — continuing keyless', {\n secretName,\n error: err instanceof Error ? err.message : String(err),\n });\n // Serve a stale value if we ever had one; otherwise keyless.\n return cached?.value;\n }\n}\n\n/**\n * Load the effective EdgeConfig. Delegates caching/fallback/degradation to\n * the SDK; adds the compile-time fallback override and never throws.\n */\nexport async function loadEdgeConfig(\n options: EdgeAdapterOptions,\n apiKey: string | undefined\n): Promise<EdgeConfig> {\n try {\n return await getEdgeConfig({ apiBaseUrl: options.apiBaseUrl, apiKey }, options.counterpartyId, {\n ttlMs: options.configTtlMs,\n });\n } catch {\n return options.fallbackConfig ?? DEFAULT_EDGE_CONFIG;\n }\n}\n\n/** Reset module caches — tests only. */\nexport function _resetConfigCaches(): void {\n secretCache.clear();\n}\n","/**\n * Three-tier traffic classification (§33.5 #1: verified /\n * identified-but-unregistered / anonymous) plus the two non-tiers the shell\n * touches as little as possible: `human` (zero network calls, zero logging)\n * and `skipped` (static assets / excluded paths).\n *\n * Cheapest checks first — the human path must add microseconds, not\n * milliseconds. Platform signatures come from the SDK so the edge and the\n * backend's verify-access anonymous handler classify identically.\n */\n\nimport type { CloudFrontRequest } from 'aws-lambda';\nimport { extractCredentials } from '@astrasyncai/verification-gateway/verify';\nimport { detectPlatformFingerprint } from '@astrasyncai/verification-gateway/platform-signatures';\nimport { matchEdgePathRule, type EdgeConfig } from '@astrasyncai/verification-gateway/edge-config';\nimport { getHeader, decodeBody, flattenHeaders } from './cf';\nimport { detectCommerce } from './detect';\nimport type { Classification, EffectivePolicy } from './types';\n\n/** Extensions the shell never classifies — static assets. */\nconst STATIC_EXTENSIONS =\n /\\.(css|js|mjs|map|png|jpe?g|gif|webp|avif|svg|ico|woff2?|ttf|otf|eot|mp4|webm|pdf|txt|xml)$/i;\n\n/** Non-browser, non-platform CLI/library UA tokens → anonymous bot. */\nconst BOT_UA_PATTERN =\n /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;\n\n/** Browser-shaped UA. */\nconst BROWSER_UA_PATTERN = /mozilla\\/\\d/i;\n\n/**\n * Resolve the effective mode/depth for a path from the EdgeConfig — ordered\n * first-match-wins rules with case-insensitive globs; no match falls through\n * to the config's top-level defaults. Static extensions are always skipped\n * regardless of rules (a rule can only skip MORE, never un-skip an asset).\n */\nexport function resolvePolicy(config: EdgeConfig, path: string): EffectivePolicy {\n if (STATIC_EXTENSIONS.test(path)) {\n return { mode: config.mode, depth: config.depth, skip: true };\n }\n const rule = matchEdgePathRule(config.pathRules, path);\n if (!rule) return { mode: config.mode, depth: config.depth, skip: false };\n return {\n mode: rule.mode ?? config.mode,\n depth: rule.depth ?? config.depth,\n skip: rule.skip === true,\n };\n}\n\n/**\n * Classify one request. Order (cheapest sufficient evidence wins):\n * 1. X-Astra-* credentials → `verified` candidate\n * 2. commerce-protocol credentials on the wire → `identified`\n * 3. platform UA fingerprint (Claude/ChatGPT/Gemini/…) → `identified`\n * 4. bot-shaped UA / headerless non-browser → `anonymous-bot`\n * 5. everything browser-shaped → `human`\n *\n * `depth: 'classify'` skips step 2 (no body decode, no header sniffing\n * beyond UA) — that is the zero-friction setting.\n */\nexport function classify(\n request: CloudFrontRequest,\n host: string,\n depth: 'classify' | 'authenticate' | 'authorize'\n): Classification {\n const userAgent = getHeader(request, 'user-agent') ?? '';\n\n // 1. Native AstraSync credentials.\n const credentials = extractCredentials(flattenHeaders(request.headers), {});\n if (credentials.astraId || credentials.apiKey || credentials.jwt) {\n return { tier: 'verified', protocol: 'x-astra' };\n }\n\n // 2. Commerce-protocol credentials (skipped entirely at classify depth).\n if (depth !== 'classify') {\n const commerce = detectCommerce(request, host, decodeBody(request));\n if (commerce) {\n return {\n tier: 'identified',\n protocol: commerce.protocol,\n artifacts: commerce.artifacts,\n evidence: commerce.evidence,\n fingerprint: detectPlatformFingerprint({ userAgent }),\n };\n }\n }\n\n // 3. Platform-agent UA fingerprint.\n const fingerprint = detectPlatformFingerprint({ userAgent });\n if (fingerprint) {\n return { tier: 'identified', protocol: 'platform-ua', fingerprint };\n }\n\n // 4. Bot-shaped: CLI/library UA, no UA at all, or any non-browser UA —\n // humans arrive with Mozilla-family UAs; everything else is automation.\n if (!userAgent || BOT_UA_PATTERN.test(userAgent) || !BROWSER_UA_PATTERN.test(userAgent)) {\n return { tier: 'anonymous-bot', evidence: { userAgent: userAgent || '(none)' } };\n }\n\n // 4b. Claims to be a browser but is missing every browser fetch-metadata\n // header — headless/spoofed. `sec-fetch-mode` is sent by all evergreen\n // browsers; its absence on a Mozilla UA is a strong bot signal.\n if (!getHeader(request, 'sec-fetch-mode') && !getHeader(request, 'accept-language')) {\n return { tier: 'anonymous-bot', evidence: { userAgent, spoofedBrowser: true } };\n }\n\n // 5. Human traffic — the shell gets out of the way.\n return { tier: 'human' };\n}\n\n/** Exported for tests. */\nexport const _patterns = { STATIC_EXTENSIONS, BOT_UA_PATTERN, BROWSER_UA_PATTERN };\n","/**\n * Crypto-free commerce-protocol detection (§7.4.2 detection order).\n *\n * The edge only SNIFFS — header shapes, compact-JWT patterns, body field\n * names — and packages what it saw as raw `CommerceArtifactsPayload` for\n * verify-access, whose Step 0.5 pipeline does the authoritative parsing and\n * cryptographic verification server-side. Nothing here imports jose/sd-jwt/\n * signature libraries: detection must stay cheap enough to run on every\n * non-human request, and verification must happen exactly once, in the\n * canonical sink, where it is recorded.\n */\n\nimport type { CloudFrontRequest } from 'aws-lambda';\nimport type { CommerceArtifactsPayload } from '@astrasyncai/verification-gateway';\nimport { flattenHeaders, getHeader, requestUrl, type DecodedBody } from './cf';\n\nexport interface DetectedCommerce {\n /** Detection-order label: rfc9421-agent-pay | rfc9421-tap | rfc9421-web-bot-auth | vi-sd-jwt | ap2 | acp | ucp | mpp | x402 */\n protocol: string;\n artifacts: CommerceArtifactsPayload;\n /** Light detection detail for beacons/audit — never secrets or full credentials. */\n evidence: Record<string, unknown>;\n}\n\n/** Compact SD-JWT: JWT + `~`-separated disclosures. */\nconst SD_JWT_PATTERN = /^eyJ[\\w-]+\\.[\\w-]*\\.[\\w-]+~/;\n\n/** Decode a JWT header segment without verifying anything. */\nfunction sniffJwtHeader(compact: string): Record<string, unknown> | undefined {\n try {\n const seg = compact.split('.')[0];\n return JSON.parse(Buffer.from(seg, 'base64url').toString('utf8')) as Record<string, unknown>;\n } catch {\n return undefined;\n }\n}\n\nfunction parseJsonBody(body: DecodedBody): Record<string, unknown> | undefined {\n if (!body.text) return undefined;\n try {\n const parsed: unknown = JSON.parse(body.text);\n return typeof parsed === 'object' && parsed !== null\n ? (parsed as Record<string, unknown>)\n : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * §7.4.2 order (after the X-Astra native check, which classify.ts owns):\n * SD-JWT/VI → RFC 9421 (Agent Pay / TAP / Web Bot Auth by kid namespace or\n * Signature-Agent) → ACP HMAC → UCP session → AP2 body triple → MPP → x402.\n * Returns undefined when nothing commerce-shaped is on the wire.\n *\n * When the body was truncated by CloudFront (`inputTruncated`), body-bound\n * artifacts still forward what arrived but carry a `bodyTruncated` evidence\n * flag — the backend downgrades those signatures rather than hard-failing.\n */\nexport function detectCommerce(\n request: CloudFrontRequest,\n host: string,\n body: DecodedBody\n): DetectedCommerce | undefined {\n const url = requestUrl(request, host);\n const method = request.method;\n const headers = flattenHeaders(request.headers);\n const jsonBody = parseJsonBody(body);\n const truncated = body.truncated ? { bodyTruncated: true } : {};\n\n // --- VI / SD-JWT credential in a header ------------------------------\n const authHeader = getHeader(request, 'authorization');\n const bearer = authHeader?.replace(/^Bearer\\s+/i, '');\n const mandateHeader =\n getHeader(request, 'x-payment-mandate') ?? getHeader(request, 'payment-mandate');\n const sdJwtCandidate = [mandateHeader, bearer].find((v) => v && SD_JWT_PATTERN.test(v));\n if (sdJwtCandidate) {\n const typ = sniffJwtHeader(sdJwtCandidate)?.typ;\n return {\n protocol: 'vi-sd-jwt',\n artifacts: { viSdJwt: sdJwtCandidate },\n evidence: { typ, ...truncated },\n };\n }\n\n // --- RFC 9421 (Agent Pay / TAP / Web Bot Auth) ------------------------\n const signature = getHeader(request, 'signature');\n const signatureInput = getHeader(request, 'signature-input');\n if (signature && signatureInput) {\n const signatureAgent = getHeader(request, 'signature-agent');\n const registryHint = getHeader(request, 'x-agent-registry');\n const lowerInput = signatureInput.toLowerCase();\n const protocol = signatureAgent\n ? 'rfc9421-web-bot-auth'\n : registryHint?.toLowerCase().includes('visa') || lowerInput.includes('visa')\n ? 'rfc9421-tap'\n : registryHint?.toLowerCase().includes('mastercard') || lowerInput.includes('mastercard')\n ? 'rfc9421-agent-pay'\n : 'rfc9421';\n return {\n protocol,\n artifacts: {\n rfc9421: { headers, method, url, ...(body.text && { body: body.text }) },\n },\n evidence: {\n ...(signatureAgent && { signatureAgent }),\n ...(registryHint && { registryHint }),\n keyid: signatureInput.match(/keyid=\"([^\"]+)\"/)?.[1],\n ...truncated,\n },\n };\n }\n\n // --- ACP (HMAC-signed webhook/checkout: signature WITHOUT signature-input)\n const acpTimestamp = getHeader(request, 'timestamp');\n if (signature && !signatureInput && (acpTimestamp || getHeader(request, 'idempotency-key'))) {\n return {\n protocol: 'acp',\n artifacts: {\n acpRequest: {\n method,\n url,\n headers,\n ...(body.text && { rawBody: body.text }),\n ...(jsonBody && { body: jsonBody }),\n },\n },\n evidence: { hasTimestamp: Boolean(acpTimestamp), ...truncated },\n };\n }\n\n // --- UCP checkout session ---------------------------------------------\n if (/\\/checkout[-_]sessions(\\/|$)/.test(request.uri)) {\n return {\n protocol: 'ucp',\n artifacts: { ucpRequest: { method, url, ...(jsonBody && { body: jsonBody }) } },\n evidence: { path: request.uri, ...truncated },\n };\n }\n\n // --- AP2 mandate triple in the body -----------------------------------\n if (jsonBody) {\n const intent = jsonBody.intent_mandate ?? jsonBody.intentMandate;\n const cart = jsonBody.cart_mandate ?? jsonBody.cartMandate;\n const payment = jsonBody.payment_mandate ?? jsonBody.paymentMandate;\n if (typeof intent === 'string' || typeof cart === 'string' || typeof payment === 'string') {\n return {\n protocol: 'ap2',\n artifacts: {\n ap2Mandates: {\n ...(typeof intent === 'string' && { intent }),\n ...(typeof cart === 'string' && { cart }),\n ...(typeof payment === 'string' && { payment }),\n },\n },\n evidence: {\n mandatesPresent: [\n typeof intent === 'string' && 'intent',\n typeof cart === 'string' && 'cart',\n typeof payment === 'string' && 'payment',\n ].filter(Boolean),\n ...truncated,\n },\n };\n }\n }\n\n // --- MPP (`Authorization: Payment <credential>`) -----------------------\n if (authHeader && /^Payment\\s+/i.test(authHeader)) {\n return {\n protocol: 'mpp',\n artifacts: {\n mppRequest: {\n method,\n url,\n headers,\n ...(body.text && { rawBody: body.text }),\n ...(jsonBody && { body: jsonBody }),\n },\n },\n evidence: truncated,\n };\n }\n\n // --- x402 (X-PAYMENT header) ------------------------------------------\n if (getHeader(request, 'x-payment')) {\n return {\n protocol: 'x402',\n artifacts: {\n x402Request: { method, url, headers, ...(jsonBody && { body: jsonBody }) },\n },\n evidence: truncated,\n };\n }\n\n return undefined;\n}\n","/**\n * Depth-controlled verification per tier. The edge never verifies\n * credentials itself — it forwards what it detected to verify-access, the\n * canonical sole verification sink (backend Step 0.5 runs the commerce\n * pipeline, records events, provisions orphans, persists sessions). What\n * the depth setting controls is how much the edge LOOKS and how much it\n * FORWARDS:\n *\n * classify — what is it? UA tiers only. Zero verify-access calls;\n * beacons only.\n * authenticate — who is it? + protocol detection. X-Astra agents get a\n * verify-access identity check; commerce/platform traffic\n * is beaconed with protocol + evidence (no signature\n * verification anywhere).\n * authorize — are they allowed? + artifact forwarding. X-Astra verify\n * calls carry commerceArtifacts; identified traffic gets an\n * anonymous verify-access call with artifacts +\n * callerMetadata so the backend cryptographically proves\n * and policy-evaluates once.\n */\n\nimport type { CloudFrontRequest } from 'aws-lambda';\nimport { verify, extractCredentials } from '@astrasyncai/verification-gateway/verify';\nimport { resolveHttpPdlss } from '@astrasyncai/verification-gateway/http-pdlss';\nimport type { GatewayConfig, VerificationRequest } from '@astrasyncai/verification-gateway';\nimport { flattenHeaders, getHeader } from './cf';\nimport { withBudget, emitBeacon, sampled } from './events';\nimport type { Classification, EdgeAdapterOptions, EffectivePolicy, TierOutcome } from './types';\n\nfunction baseOutcome(classification: Classification): TierOutcome {\n return {\n tier: classification.tier,\n decision: 'allow',\n reasons: [],\n protocol: classification.protocol,\n };\n}\n\nfunction buildVerificationRequest(\n options: EdgeAdapterOptions,\n request: CloudFrontRequest,\n classification: Classification,\n includeArtifacts: boolean\n): VerificationRequest {\n const headers = flattenHeaders(request.headers);\n const clientIp = getHeader(request, 'cloudfront-viewer-address')?.split(':')[0];\n // verify-access REQUIRES a purpose. Resolve via the shared §4.6 chain:\n // the agent's X-Astra-Purpose/-Action declarations, else the pinned\n // method table (GET → data/data.read etc.) — a transport verb never\n // travels as a PDLSS action.\n const pdlss = resolveHttpPdlss({\n method: request.method,\n astraPurpose: getHeader(request, 'x-astra-purpose'),\n astraAction: getHeader(request, 'x-astra-action'),\n });\n return {\n credentials: extractCredentials(headers, {}),\n purpose: pdlss.purpose,\n action: pdlss.action,\n resource: request.uri,\n createSession: true,\n counterpartyType: 'website',\n counterpartyUrl: options.counterpartyUrl,\n callerMetadata: {\n sourceIp: clientIp,\n userAgent: getHeader(request, 'user-agent'),\n referer: getHeader(request, 'referer'),\n host: getHeader(request, 'host'),\n },\n ...(includeArtifacts &&\n classification.artifacts && { commerceArtifacts: classification.artifacts }),\n };\n}\n\nfunction outcomeFromVerifyResult(\n classification: Classification,\n result: Awaited<ReturnType<typeof verify>>\n): TierOutcome {\n const outcome = baseOutcome(classification);\n outcome.sessionId = (result as { sessionId?: string }).sessionId;\n outcome.correlationId = result.correlationId;\n outcome.guidance = result.guidance;\n\n if (result.requiresStepUp || result.stepUpApproval) {\n outcome.decision = 'manual_review';\n outcome.reasons = ['step-up approval required'];\n outcome.stepUp = {\n pollUrl: (result.stepUpApproval as { pollUrl?: string } | undefined)?.pollUrl,\n expiresAt: (result.stepUpApproval as { expiresAt?: string } | undefined)?.expiresAt,\n };\n return outcome;\n }\n\n if (!result.identityVerified || !result.policyAllowed) {\n outcome.decision = 'deny';\n outcome.reasons = result.denialReasons?.length\n ? result.denialReasons\n : [!result.identityVerified ? 'identity not verified' : 'denied by access policy'];\n return outcome;\n }\n\n outcome.asat = {\n trustScore: result.agent?.trustScore,\n agentId: result.agent?.astraId,\n developerId: result.developer?.astradId,\n accessLevel: result.accessLevel,\n };\n return outcome;\n}\n\n/**\n * Run the tier-appropriate verification/telemetry for one classified\n * request. NEVER throws; on any failure returns an `allow` outcome with the\n * failure recorded in `reasons` (infra failures fail open — a presented\n * credential the BACKEND rejected is a deny, but an unreachable backend is\n * not a rejection).\n */\nexport async function runTier(\n options: EdgeAdapterOptions,\n request: CloudFrontRequest,\n classification: Classification,\n policy: EffectivePolicy,\n apiKey: string | undefined,\n sampling: { anonymousBeaconRate: number }\n): Promise<TierOutcome> {\n const budgets = options.budgets ?? {};\n const beaconMs = budgets.beaconMs ?? 300;\n const verifyMs =\n policy.mode === 'enforce'\n ? (budgets.verifyEnforceMs ?? 3000)\n : (budgets.verifyObserveMs ?? 1500);\n\n const gatewayConfig: GatewayConfig = {\n apiBaseUrl: options.apiBaseUrl,\n ...(apiKey && { apiKey }),\n counterpartyId: options.counterpartyId,\n // The shell handles its own error semantics; init self-probes don't\n // belong in a per-request edge function.\n disableInitChecks: true,\n } as GatewayConfig;\n\n try {\n switch (classification.tier) {\n case 'verified': {\n // classify depth = zero API calls, even for credentialed agents.\n if (policy.depth === 'classify') {\n return baseOutcome(classification);\n }\n const result = await withBudget(\n verify(\n gatewayConfig,\n buildVerificationRequest(options, request, classification, policy.depth === 'authorize')\n ),\n verifyMs\n );\n if (!result) {\n const outcome = baseOutcome(classification);\n outcome.reasons = ['verify-access unreachable within budget — fail-open'];\n return outcome;\n }\n return outcomeFromVerifyResult(classification, result);\n }\n\n case 'identified': {\n if (policy.depth === 'authorize' && classification.artifacts) {\n // Anonymous verify-access call WITH artifacts: the backend runs\n // the commerce pipeline, records unverified events, and\n // provisions orphan platform agents — one sink, recorded once.\n const result = await withBudget(\n verify(gatewayConfig, buildVerificationRequest(options, request, classification, true)),\n verifyMs\n );\n if (!result) {\n const outcome = baseOutcome(classification);\n outcome.reasons = ['verify-access unreachable within budget — fail-open'];\n return outcome;\n }\n return outcomeFromVerifyResult(classification, result);\n }\n // classify/credentials depth (or no artifacts): lightweight beacon.\n await emitBeacon(options, request, classification, beaconMs);\n const outcome = baseOutcome(classification);\n if (policy.mode === 'enforce' && policy.depth !== 'classify') {\n // Unregistered agent on an enforced path: deny with guidance.\n outcome.decision = 'deny';\n outcome.reasons = ['agent is not registered with AstraSync'];\n }\n return outcome;\n }\n\n case 'anonymous-bot': {\n if (sampled(sampling.anonymousBeaconRate, options.random)) {\n await emitBeacon(\n options,\n request,\n { ...classification, protocol: classification.protocol ?? 'ua-heuristic' },\n beaconMs\n );\n }\n // Anonymous bots pass through even in enforce mode — enforce gates\n // AGENT traffic; generic bot management stays the CDN/WAF's job\n // (mixed-traffic classification §5.1.7 is the enforce-mode\n // prerequisite tracked as §33.5 #9).\n return baseOutcome(classification);\n }\n\n default:\n return baseOutcome(classification);\n }\n } catch (err) {\n const outcome = baseOutcome(classification);\n outcome.reasons = [\n `edge pipeline error — fail-open: ${err instanceof Error ? err.message : String(err)}`,\n ];\n return outcome;\n }\n}\n","/**\n * Time-budgeted event emission.\n *\n * Lambda@Edge has no `waitUntil` — anything not awaited before the handler\n * returns may never run (the container freezes). So every network call is\n * awaited under an explicit budget and DROPPED on timeout: latency to the\n * customer's traffic is bounded, and a slow AstraSync API costs telemetry,\n * never page loads.\n */\n\nimport { reportUnregisteredAttempt } from '@astrasyncai/verification-gateway/verify';\nimport type { CloudFrontRequest } from 'aws-lambda';\nimport { getHeader } from './cf';\nimport type { Classification, EdgeAdapterOptions } from './types';\n\n/** Await `promise` for at most `ms`; resolve `undefined` on timeout/error. */\nexport async function withBudget<T>(promise: Promise<T>, ms: number): Promise<T | undefined> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n promise,\n new Promise<undefined>((resolve) => {\n timer = setTimeout(() => resolve(undefined), ms);\n }),\n ]);\n } catch {\n return undefined;\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n\n/**\n * Emit an unregistered-attempt beacon for `identified` (non-crypto depths)\n * and sampled `anonymous-bot` traffic. Unauthenticated by design\n * (CSRF-exempt on the backend); the backend fingerprints the UA and\n * find-or-provisions orphan platform agents server-side.\n */\nexport async function emitBeacon(\n options: EdgeAdapterOptions,\n request: CloudFrontRequest,\n classification: Classification,\n budgetMs: number\n): Promise<void> {\n const clientIp = getHeader(request, 'cloudfront-viewer-address')?.split(':')[0];\n await withBudget(\n reportUnregisteredAttempt(\n { apiBaseUrl: options.apiBaseUrl, counterpartyId: options.counterpartyId },\n {\n counterpartyUrl: options.counterpartyUrl,\n counterpartyType: 'website',\n sourceIp: clientIp,\n userAgent: getHeader(request, 'user-agent'),\n requestPath: request.uri,\n requestMethod: request.method,\n // 3.9.0 evidence fields (backend persists them into eventData).\n protocol: classification.protocol,\n evidence: classification.evidence,\n }\n ),\n budgetMs\n );\n}\n\n/** Deterministic-in-tests sampling gate. */\nexport function sampled(rate: number, random: () => number = Math.random): boolean {\n if (rate <= 0) return false;\n if (rate >= 1) return true;\n return random() < rate;\n}\n","/**\n * §7.4.6 — protocol-specific machine-readable messaging for enforce-mode\n * responses. Agents (not humans) consume these bodies: stable error codes,\n * the failure list, and registration guidance with real URLs.\n */\n\nimport type { TierOutcome } from './types';\n\nconst PROTOCOL_MESSAGES: Record<string, string> = {\n 'vi-sd-jwt':\n '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.',\n 'rfc9421-agent-pay':\n '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.',\n 'rfc9421-tap':\n '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.',\n 'rfc9421-web-bot-auth':\n '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.',\n rfc9421:\n '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.',\n acp: 'This request used the Agentic Commerce Protocol, but the agent is not verified with AstraSync. Register the agent to transact on this property.',\n ucp: 'This request used a UCP checkout session, but the agent is not verified with AstraSync. Register the agent to transact on this property.',\n 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.',\n mpp: 'This request presented MPP payment credentials, but the agent is not verified with AstraSync. Register the agent to transact on this property.',\n x402: 'This request used x402 payment headers, but the agent is not verified with AstraSync. Register the agent to transact on this property.',\n 'platform-ua':\n 'This traffic was identified as a platform AI agent without AstraSync credentials. Register the agent to access this property with a verified identity.',\n 'x-astra':\n 'The presented AstraSync credentials failed verification or were denied by this property’s access policy.',\n};\n\nexport interface DenyBody {\n success: false;\n error: {\n code: 'UNAUTHORIZED' | 'INSUFFICIENT_ACCESS';\n message: string;\n protocol?: string;\n failures: string[];\n correlationId?: string;\n guidance: {\n message?: string;\n registrationUrl?: string;\n documentationUrl?: string;\n };\n };\n}\n\nexport function buildDenyBody(outcome: TierOutcome, apiBaseUrl: string): DenyBody {\n const origin = apiBaseUrl.replace(/\\/api\\/?$/, '');\n const protocolMessage =\n (outcome.protocol && PROTOCOL_MESSAGES[outcome.protocol]) ??\n 'This request could not be verified by AstraSync.';\n return {\n success: false,\n error: {\n // UNAUTHORIZED = identity failed (register/re-authenticate helps);\n // INSUFFICIENT_ACCESS = identity fine, policy denied (fix the mandate).\n code: outcome.tier === 'verified' ? 'INSUFFICIENT_ACCESS' : 'UNAUTHORIZED',\n message: protocolMessage,\n ...(outcome.protocol && { protocol: outcome.protocol }),\n failures: outcome.reasons,\n ...(outcome.correlationId && { correlationId: outcome.correlationId }),\n guidance: {\n // `||` not `??`: verify() fills these with EMPTY STRINGS when the\n // well-known cache is cold — empty means \"use the fallback\".\n message:\n outcome.guidance?.message ||\n 'Register this agent with AstraSync to receive verifiable credentials.',\n registrationUrl: outcome.guidance?.registrationUrl || `${origin}/register`,\n documentationUrl: outcome.guidance?.documentationUrl || `${origin}/docs/edge-adapter`,\n },\n },\n };\n}\n\nexport interface ManualReviewBody {\n success: false;\n status: 'manual_review';\n message: string;\n stepUpApproval?: { pollUrl?: string; expiresAt?: string };\n correlationId?: string;\n}\n\nexport function buildManualReviewBody(outcome: TierOutcome): ManualReviewBody {\n return {\n success: false,\n status: 'manual_review',\n message:\n 'This action requires human approval. Poll the step-up approval endpoint and retry once approved.',\n ...(outcome.stepUp && { stepUpApproval: outcome.stepUp }),\n ...(outcome.correlationId && { correlationId: outcome.correlationId }),\n };\n}\n","/**\n * Decision → CloudFront result wiring (§7.4 enforcement, §7.4.7 ASAT\n * headers). Executed in BOTH modes so observe mode records exactly what\n * enforce mode would have done — but only enforce mode is allowed to return\n * anything other than the origin-bound request.\n */\n\nimport type { CloudFrontRequest, CloudFrontRequestResult } from 'aws-lambda';\nimport { jsonResponse, setHeader, stripHeadersByPrefix } from './cf';\nimport { buildDenyBody, buildManualReviewBody } from './messaging';\nimport type { EdgeAdapterOptions, EffectivePolicy, TierOutcome } from './types';\n\n/** §7.4.7 ASAT trust-attestation headers injected on allowed requests. */\nexport const ASAT_HEADERS = {\n trustScore: 'X-AstraSync-Trust-Score',\n agentId: 'X-AstraSync-Agent-Id',\n developerId: 'X-AstraSync-Developer-Id',\n permissions: 'X-AstraSync-Permissions',\n observedDecision: 'X-AstraSync-Observed-Decision',\n} as const;\n\n/**\n * Apply the outcome. Always strips inbound spoofed `x-astrasync-*` headers\n * first (both modes — trust headers must only ever originate here).\n *\n * Observe mode: returns the request untouched apart from header hygiene and\n * an `X-AstraSync-Observed-Decision` stamp for origin-side log correlation.\n *\n * Enforce mode: ALLOW → request + ASAT headers; DENY → 403 machine-readable\n * body; MANUAL_REVIEW → 202 with step-up poll info.\n */\nexport function applyOutcome(\n options: EdgeAdapterOptions,\n request: CloudFrontRequest,\n outcome: TierOutcome,\n policy: EffectivePolicy\n): CloudFrontRequestResult {\n stripHeadersByPrefix(request, 'x-astrasync-');\n\n if (policy.mode !== 'enforce') {\n // Shadow stamp: what enforce WOULD have done, visible in origin logs.\n if (outcome.decision !== 'allow') {\n setHeader(request, ASAT_HEADERS.observedDecision, outcome.decision);\n }\n injectAsat(request, outcome);\n return request;\n }\n\n switch (outcome.decision) {\n case 'deny':\n return jsonResponse(403, buildDenyBody(outcome, options.apiBaseUrl));\n case 'manual_review':\n return jsonResponse(202, buildManualReviewBody(outcome), {\n 'Retry-After': '30',\n });\n default:\n injectAsat(request, outcome);\n return request;\n }\n}\n\nfunction injectAsat(request: CloudFrontRequest, outcome: TierOutcome): void {\n if (!outcome.asat) return;\n const { trustScore, agentId, developerId, accessLevel } = outcome.asat;\n if (trustScore !== undefined) {\n setHeader(request, ASAT_HEADERS.trustScore, String(trustScore));\n }\n if (agentId) setHeader(request, ASAT_HEADERS.agentId, agentId);\n if (developerId) setHeader(request, ASAT_HEADERS.developerId, developerId);\n if (accessLevel) setHeader(request, ASAT_HEADERS.permissions, accessLevel);\n}\n","/**\n * Commerce Shield edge shell — Lambda@Edge origin-request handler factory\n * (§7.4 / §33.5 #1).\n *\n * Composition per request:\n * config (cached) → path policy → classify → tier pipeline → apply outcome\n *\n * THE invariant (tested): outside enforce mode the handler ALWAYS returns\n * the origin-bound request — any error, timeout, or misconfiguration\n * results in pass-through. A top-level catch guarantees it even against\n * bugs in the shell itself.\n */\n\nimport type { CloudFrontRequestEvent, CloudFrontRequestResult } from 'aws-lambda';\nimport { getRequest, getHeader } from './cf';\nimport { resolveApiKey, loadEdgeConfig } from './config';\nimport { classify, resolvePolicy } from './classify';\nimport { runTier } from './pipeline';\nimport { applyOutcome } from './enforce';\nimport type { EdgeAdapterOptions } from './types';\n\nexport type EdgeHandler = (event: CloudFrontRequestEvent) => Promise<CloudFrontRequestResult>;\n\nexport function createEdgeHandler(options: EdgeAdapterOptions): EdgeHandler {\n const log =\n options.log ??\n ((level, message, data) => {\n // Lambda@Edge writes console output to the regional CloudWatch log\n // group of whichever edge location served the request.\n console[level === 'info' ? 'log' : level](`[astrasync-edge] ${message}`, data ?? '');\n });\n\n return async function handler(event) {\n const request = getRequest(event);\n try {\n const apiKey = await resolveApiKey({ ...options, log });\n const config = await loadEdgeConfig(options, apiKey);\n const policy = resolvePolicy(config, request.uri);\n\n // Skipped paths (static assets / skip rules): untouched, zero work.\n if (policy.skip) return request;\n\n const host =\n getHeader(request, 'x-forwarded-host') ??\n getHeader(request, 'host') ??\n new URL(options.counterpartyUrl).host;\n\n const classification = classify(request, host, policy.depth);\n\n // Humans: get out of the way. No calls, no logs, no header changes\n // beyond nothing at all.\n if (classification.tier === 'human') return request;\n\n const outcome = await runTier(\n { ...options, log },\n request,\n classification,\n policy,\n apiKey,\n config.sampling\n );\n\n if (outcome.decision !== 'allow') {\n log(\n 'info',\n policy.mode === 'enforce'\n ? `${outcome.decision.toUpperCase()}: ${request.method} ${request.uri}`\n : `[OBSERVE] would have been ${outcome.decision.toUpperCase()}: ${request.method} ${request.uri}`,\n { tier: outcome.tier, protocol: outcome.protocol, reasons: outcome.reasons }\n );\n }\n\n return applyOutcome(options, request, outcome, policy);\n } catch (err) {\n // Fail-open, unconditionally: the shell must never take the site down.\n log('error', 'edge handler error — passing request through', {\n error: err instanceof Error ? err.message : String(err),\n });\n return request;\n }\n };\n}\n"],"mappings":"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","names":["extractCredentials","extractCredentials","outcome"]}
@@ -0,0 +1 @@
1
+ "use strict";var he=Object.create;var S=Object.defineProperty;var ve=Object.getOwnPropertyDescriptor;var Ae=Object.getOwnPropertyNames;var we=Object.getPrototypeOf,Re=Object.prototype.hasOwnProperty;var Ce=(e,t)=>{for(var r in t)S(e,r,{get:t[r],enumerable:!0})},D=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of Ae(t))!Re.call(e,a)&&a!==r&&S(e,a,{get:()=>t[a],enumerable:!(n=ve(t,a))||n.enumerable});return e};var Te=(e,t,r)=>(r=e!=null?he(we(e)):{},D(t||!e||!e.__esModule?S(r,"default",{value:e,enumerable:!0}):r,e)),Se=e=>D(S({},"__esModule",{value:!0}),e);var at={};Ce(at,{handler:()=>nt});module.exports=Se(at);function F(e){return e.Records[0].cf.request}function c(e,t){return e.headers[t.toLowerCase()]?.[0]?.value}function w(e){let t={};for(let[r,n]of Object.entries(e))n?.length&&(t[r]=n.length===1?n[0].value:n.map(a=>a.value));return t}function k(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 M(e,t){let r=e.querystring?`?${e.querystring}`:"";return`https://${t}${e.uri}${r}`}function R(e,t,r){e.headers[t.toLowerCase()]=[{key:t,value:r}]}function N(e,t){let r=t.toLowerCase();for(let n of Object.keys(e.headers))n.startsWith(r)&&delete e.headers[n]}function U(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 P=Object.freeze({version:1,mode:"observe",depth:"classify",pathRules:[],sampling:Object.freeze({anonymousBeaconRate:.1}),failurePosture:"open"}),H=["observe","enforce"],L=["classify","authenticate","authorize"];function be(e){if(typeof e!="object"||e===null)return!1;let t=e;if(t.version!==1||!H.includes(t.mode)||!L.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&&!H.includes(a.mode)||a.depth!==void 0&&!L.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 Ie(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 fetch(`${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 be(o)?{edgeConfig:o,etag:a.headers.get("etag")??void 0}:null}catch{return null}}var Ue=60*1e3,Ee=1440*60*1e3,C=new Map,E=new Map;function V(e,t){return`${e}|${t}`}function Pe(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 $(e,t){let r=V(e.apiBaseUrl,t),n=E.get(r);if(n)return n;let a=Ie(e,t,{etag:C.get(r)?.etag}).then(i=>{if(i===null)return;let o=Date.now();if("notModified"in i){let s=C.get(r);s&&(s.lastSuccessAt=o);return}C.set(r,{config:i.edgeConfig,etag:i.etag,lastSuccessAt:o})}).finally(()=>{E.delete(r)});return E.set(r,a),a}async function K(e,t,r){let n=r?.ttlMs??Ue,a=r?.maxStaleMs??Ee,i=V(e.apiBaseUrl,t),o=C.get(i);if(o){let s=Date.now()-o.lastSuccessAt;return s>n&&$(e,t).catch(()=>{}),s>a?Pe(o.config):o.config}return await $(e,t).catch(()=>{}),C.get(i)?.config??P}function j(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 _e=900*1e3,G=new Map;async function Oe(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 q(e){if(e.apiKey)return e.apiKey;let t=e.apiKeySecretName;if(!t)return;let r=G.get(t);if(r&&Date.now()-r.fetchedAt<_e)return r.value;try{let a=await(e.fetchSecret??Oe)(t);return G.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 z(e,t){try{return await K({apiBaseUrl:e.apiBaseUrl,apiKey:t},e.counterpartyId,{ttlMs:e.configTtlMs})}catch{return e.fallbackConfig??P}}function Be(e){return e>=80?"PLATINUM":e>=60?"GOLD":e>=40?"SILVER":"BRONZE"}var De="3.9.0",ut=3600*1e3,Fe=new Map;function ke(e){return Fe.get(e)?.data}var Y={apiBaseUrl:"https://astrasync.ai/api",defaultAccessLevel:"none",debug:!1},W=!1,X=!1;async function J(e,t,r){W=!0;try{let n=`${e}/agents/verify-access`,i=(await fetch(n,{method:"HEAD"})).headers.get("content-type")??"";if(i.startsWith("text/html")){let o=`[VerificationGateway] apiBaseUrl '${e}' returned HTML (content-type: ${i}). 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(`${o} (strictInit=true)`);console.warn(`${o} Set disableInitChecks: true on GatewayConfig to silence.`)}else t&&console.log(`[VerificationGateway] init check passed for ${e} (content-type: ${i})`)}catch(n){if(r)throw n;t&&console.log(`[VerificationGateway] init check failed (non-blocking): ${String(n)}`)}}var x=new Map;function Z(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 Me(e,t){let r=Z(e,t),n=x.get(r);return n&&n.expiresAt>Date.now()?n.result:(n&&x.delete(r),null)}var Ne=60;function He(e,t,r,n){let a=r&&r>0?r:Ne,i=Z(e,n);x.set(i,{result:t,expiresAt:Date.now()+a*1e3})}function b(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 Le(e,t,r={}){let a=(r.source??"no_credentials")==="api_error",i=r.urls,o=a?{message:"Verification is temporarily unavailable. Retry with exponential backoff; if the issue persists, contact support with the correlationId.",registrationUrl:i?.registrationUrl??"",documentationUrl:i?.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:i?.registrationUrl??"",documentationUrl:i?.documentationUrl??"",steps:["Register for an AstraSync account","Create and register your agent","Add your ASTRA-ID to request headers","Retry your request"]};return{identityVerified:!1,policyAllowed:!1,accessLevel:"none",guidance:o,denialReasons:t?[t]:["No valid agent credentials provided"],failures:a?[{dimension:"verify_access.api_error",message:t??"Verification temporarily unavailable",guidance:o.message}]:void 0,correlationId:r.correlationId,verifiedAt:new Date}}async function $e(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),a.sdkVersion=De,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 fetch(`${e.apiBaseUrl}/agents/verify-access`,{method:"POST",headers:i,body:JSON.stringify(a)}),s=await o.json();return o.status===410?{success:!0,access:{allowed:!1,accessLevel:"none",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:{success:!1,error:s.message||s.error||`API returned ${o.status}`,correlationId:typeof s?.correlationId=="string"?s.correlationId:void 0}}catch(o){return{success:!1,error:`Failed to call verify-access API: ${o instanceof Error?o.message:"Unknown error"}`}}}async function _(e,t,r){let n={...Y,...e},a=n.apiBaseUrl?ke(n.apiBaseUrl):void 0;if(!W&&!n.disableInitChecks&&n.apiBaseUrl&&(n.strictInit?await J(n.apiBaseUrl,n.debug,!0):J(n.apiBaseUrl,n.debug,!1)),!X&&(e.minTrustScore!==void 0||e.minTrustScoreForFull!==void 0)&&(X=!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-level decisions (the SDK reads access.accessLevel from the verify-access response). To gate access to an endpoint, configure the endpoint's trust_score_requirement server-side.")),n.cacheTtl!==0&&!r?.bypassCache){let l=Me(t,n.counterpartyId);if(l)return n.debug&&console.log("[VerificationGateway] Returning cached result"),l}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 $e(n,i),s=o.denialReasons,f=Array.isArray(s)&&s.length>0?s:void 0;if(!o.success)return Le(n,o.error,{source:"api_error",correlationId:o.correlationId,urls:a});if(!o.access?.allowed){let l=o.access?.failures;return{identityVerified:o.verificationContext?.idVerified===!0,policyAllowed:!1,accessLevel:"none",denialReasons:f??(l&&l.length>0?l.map(me=>me.message):o.access?.reason?[o.access.reason]:["Access denied"]),failures:l,requiresStepUp:o.access?.requiresStepUp,requiresApproval:o.access?.requiresApproval,guidance:{message:o.access?.reason||"Access denied by PDLSS policy",registrationUrl:a?.registrationUrl??"",documentationUrl:a?.documentationUrl??""},verifiedAt:new Date,sessionId:o.sessionId,correlationId:o.correlationId,recommendation:o.recommendation,recommendationReasons:o.recommendationReasons,stepUpApproval:o.stepUpApproval,settlement:o.settlement}}let y=o.agent?{astraId:o.agent.astraId,name:o.agent.name,trustScore:o.agent.trustScore,trustLevel:Be(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,g=o.organization?{name:o.organization.name,verified:o.organization.verified,trustScore:o.organization.trustScore}:void 0,v=o.verificationContext,A=o.access?.accessLevel??"standard",d={identityVerified:o.verificationContext?.idVerified!==!1,policyAllowed:!0,accessLevel:A,agent:y,developer:u,organization:g,appliedPolicy:o.access?.appliedPolicy,verificationContext:v,requiresStepUp:o.access?.requiresStepUp,requiresApproval:o.access?.requiresApproval,verifiedAt:new Date,cacheTtl:n.cacheTtl,sessionId:o.sessionId,correlationId:o.correlationId,runtimeChallenge:o.runtimeChallenge,tokenGuidance:o.tokenGuidance,recommendation:o.recommendation,recommendationReasons:o.recommendationReasons,warningHeader:o.warningHeader,stepUpApproval:o.stepUpApproval,settlement:o.settlement};d.recommendation==="deny"?(d.policyAllowed=!1,d.accessLevel="none",d.denialReasons=f??d.recommendationReasons??["Access denied by AstraSync recommendation"],d.guidance=d.runtimeChallenge?{message:`Verification failed: ${d.runtimeChallenge.reason||"runtime challenge failed"}`,registrationUrl:a?.registrationUrl??"",documentationUrl:a?.documentationUrl??""}:{message:d.recommendationReasons?.[0]||"Access denied by AstraSync recommendation",registrationUrl:a?.registrationUrl??"",documentationUrl:a?.documentationUrl??""}):d.recommendation==="step_up_required"&&(d.requiresStepUp=!0,d.denialReasons=f??d.recommendationReasons??["Step-up verification required"]);let p=d.requiresStepUp===!0||d.requiresApproval===!0||d.recommendation==="step_up_required";return n.cacheTtl!==0&&d.recommendation!=="deny"&&!p&&He(t,d,n.cacheTtl,n.counterpartyId),d}async function Q(e,t){let r=e.apiBaseUrl||Y.apiBaseUrl,{counterpartyUrl:n,...a}=t,i={...a,...n&&{counterpartyUrl:n},...e.counterpartyId&&{counterpartyId:e.counterpartyId}};await fetch(`${r}/verification-activity/unregistered-attempt`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)}).catch(()=>{})}var Ve=[{vendor:"claude",displayName:"Anthropic Claude",uaPatterns:[/claude/i,/anthropic/i],agentCardPatterns:[/anthropic\.com/i,/claude\.ai/i]},{vendor:"chatgpt",displayName:"OpenAI ChatGPT",uaPatterns:[/chatgpt/i,/openai/i,/gpt-?\d/i],agentCardPatterns:[/openai\.com/i,/chatgpt\.com/i]},{vendor:"gemini",displayName:"Google Gemini",uaPatterns:[/gemini/i,/google-gemini/i,/bard/i],agentCardPatterns:[/gemini\.google\.com/i,/ai\.google\.dev/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]}];function O(e){let t=e.userAgent??"",r=e.agentCardUrl??"";for(let n of Ve){let a=n.uaPatterns?.some(o=>o.test(t)),i=n.agentCardPatterns?.some(o=>o.test(r));if(a||i){let o=t.split(/[\s/]/)[0]?.toLowerCase()??"",s=(()=>{try{return r?new URL(r).host:""}catch{return""}})(),f=`${n.vendor}:${o||s||"unknown"}`;return{vendor:n.vendor,fingerprintKey:f,displayName:n.displayName}}}}var Ke=/^eyJ[\w-]+\.[\w-]*\.[\w-]+~/;function je(e){try{let t=e.split(".")[0];return JSON.parse(Buffer.from(t,"base64url").toString("utf8"))}catch{return}}function Ge(e){if(e.text)try{let t=JSON.parse(e.text);return typeof t=="object"&&t!==null?t:void 0}catch{return}}function ee(e,t,r){let n=M(e,t),a=e.method,i=w(e.headers),o=Ge(r),s=r.truncated?{bodyTruncated:!0}:{},f=c(e,"authorization"),y=f?.replace(/^Bearer\s+/i,""),g=[c(e,"x-payment-mandate")??c(e,"payment-mandate"),y].find(p=>p&&Ke.test(p));if(g){let p=je(g)?.typ;return{protocol:"vi-sd-jwt",artifacts:{viSdJwt:g},evidence:{typ:p,...s}}}let v=c(e,"signature"),A=c(e,"signature-input");if(v&&A){let p=c(e,"signature-agent"),l=c(e,"x-agent-registry"),m=A.toLowerCase();return{protocol:p?"rfc9421-web-bot-auth":l?.toLowerCase().includes("visa")||m.includes("visa")?"rfc9421-tap":l?.toLowerCase().includes("mastercard")||m.includes("mastercard")?"rfc9421-agent-pay":"rfc9421",artifacts:{rfc9421:{headers:i,method:a,url:n,...r.text&&{body:r.text}}},evidence:{...p&&{signatureAgent:p},...l&&{registryHint:l},keyid:A.match(/keyid="([^"]+)"/)?.[1],...s}}}let d=c(e,"timestamp");if(v&&!A&&(d||c(e,"idempotency-key")))return{protocol:"acp",artifacts:{acpRequest:{method:a,url:n,headers:i,...r.text&&{rawBody:r.text},...o&&{body:o}}},evidence:{hasTimestamp:!!d,...s}};if(/\/checkout[-_]sessions(\/|$)/.test(e.uri))return{protocol:"ucp",artifacts:{ucpRequest:{method:a,url:n,...o&&{body:o}}},evidence:{path:e.uri,...s}};if(o){let p=o.intent_mandate??o.intentMandate,l=o.cart_mandate??o.cartMandate,m=o.payment_mandate??o.paymentMandate;if(typeof p=="string"||typeof l=="string"||typeof m=="string")return{protocol:"ap2",artifacts:{ap2Mandates:{...typeof p=="string"&&{intent:p},...typeof l=="string"&&{cart:l},...typeof m=="string"&&{payment:m}}},evidence:{mandatesPresent:[typeof p=="string"&&"intent",typeof l=="string"&&"cart",typeof m=="string"&&"payment"].filter(Boolean),...s}}}if(f&&/^Payment\s+/i.test(f))return{protocol:"mpp",artifacts:{mppRequest:{method:a,url:n,headers:i,...r.text&&{rawBody:r.text},...o&&{body:o}}},evidence:s};if(c(e,"x-payment"))return{protocol:"x402",artifacts:{x402Request:{method:a,url:n,headers:i,...o&&{body:o}}},evidence:s}}var qe=/\.(css|js|mjs|map|png|jpe?g|gif|webp|avif|svg|ico|woff2?|ttf|otf|eot|mp4|webm|pdf|txt|xml)$/i,ze=/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,Xe=/mozilla\/\d/i;function te(e,t){if(qe.test(t))return{mode:e.mode,depth:e.depth,skip:!0};let r=j(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 re(e,t,r){let n=c(e,"user-agent")??"",a=b(w(e.headers),{});if(a.astraId||a.apiKey||a.jwt)return{tier:"verified",protocol:"x-astra"};if(r!=="classify"){let o=ee(e,t,k(e));if(o)return{tier:"identified",protocol:o.protocol,artifacts:o.artifacts,evidence:o.evidence,fingerprint:O({userAgent:n})}}let i=O({userAgent:n});return i?{tier:"identified",protocol:"platform-ua",fingerprint:i}:!n||ze.test(n)||!Xe.test(n)?{tier:"anonymous-bot",evidence:{userAgent:n||"(none)"}}:!c(e,"sec-fetch-mode")&&!c(e,"accept-language")?{tier:"anonymous-bot",evidence:{userAgent:n,spoofedBrowser:!0}}:{tier:"human"}}var Je={GET:"data.read",HEAD:"data.read",OPTIONS:"data.read",POST:"data.write",PUT:"data.write",PATCH:"data.write",DELETE:"data.delete"},Ye="data.write",We="data";function Ze(e){return Je[e.toUpperCase()]??Ye}function Qe(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 ne(e){let t=e.astraPurpose?Qe(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=Ze(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=We,i="transport_default")}return{purpose:a,action:r,purposeSource:i,actionSource:n}}async function I(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 B(e,t,r,n){let a=c(t,"cloudfront-viewer-address")?.split(":")[0];await I(Q({apiBaseUrl:e.apiBaseUrl,counterpartyId:e.counterpartyId},{counterpartyUrl:e.counterpartyUrl,counterpartyType:"website",sourceIp:a,userAgent:c(t,"user-agent"),requestPath:t.uri,requestMethod:t.method,protocol:r.protocol,evidence:r.evidence}),n)}function ae(e,t=Math.random){return e<=0?!1:e>=1?!0:t()<e}function h(e){return{tier:e.tier,decision:"allow",reasons:[],protocol:e.protocol}}function oe(e,t,r,n){let a=w(t.headers),i=c(t,"cloudfront-viewer-address")?.split(":")[0],o=ne({method:t.method,astraPurpose:c(t,"x-astra-purpose"),astraAction:c(t,"x-astra-action")});return{credentials:b(a,{}),purpose:o.purpose,action:o.action,resource:t.uri,createSession:!0,counterpartyType:"website",counterpartyUrl:e.counterpartyUrl,callerMetadata:{sourceIp:i,userAgent:c(t,"user-agent"),referer:c(t,"referer"),host:c(t,"host")},...n&&r.artifacts&&{commerceArtifacts:r.artifacts}}}function ie(e,t){let r=h(e);return r.sessionId=t.sessionId,r.correlationId=t.correlationId,r.guidance=t.guidance,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,accessLevel:t.accessLevel},r)}async function se(e,t,r,n,a,i){let o=e.budgets??{},s=o.beaconMs??300,f=n.mode==="enforce"?o.verifyEnforceMs??3e3:o.verifyObserveMs??1500,y={apiBaseUrl:e.apiBaseUrl,...a&&{apiKey:a},counterpartyId:e.counterpartyId,disableInitChecks:!0};try{switch(r.tier){case"verified":{if(n.depth==="classify")return h(r);let u=await I(_(y,oe(e,t,r,n.depth==="authorize")),f);if(!u){let g=h(r);return g.reasons=["verify-access unreachable within budget \u2014 fail-open"],g}return ie(r,u)}case"identified":{if(n.depth==="authorize"&&r.artifacts){let g=await I(_(y,oe(e,t,r,!0)),f);if(!g){let v=h(r);return v.reasons=["verify-access unreachable within budget \u2014 fail-open"],v}return ie(r,g)}await B(e,t,r,s);let u=h(r);return n.mode==="enforce"&&n.depth!=="classify"&&(u.decision="deny",u.reasons=["agent is not registered with AstraSync"]),u}case"anonymous-bot":return ae(i.anonymousBeaconRate,e.random)&&await B(e,t,{...r,protocol:r.protocol??"ua-heuristic"},s),h(r);default:return h(r)}}catch(u){let g=h(r);return g.reasons=[`edge pipeline error \u2014 fail-open: ${u instanceof Error?u.message:String(u)}`],g}}var et={"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 ce(e,t){let r=t.replace(/\/api\/?$/,""),n=(e.protocol&&et[e.protocol])??"This request could not be verified by AstraSync.";return{success:!1,error:{code:e.tier==="verified"?"INSUFFICIENT_ACCESS":"UNAUTHORIZED",message:n,...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`}}}}function de(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 T={trustScore:"X-AstraSync-Trust-Score",agentId:"X-AstraSync-Agent-Id",developerId:"X-AstraSync-Developer-Id",permissions:"X-AstraSync-Permissions",observedDecision:"X-AstraSync-Observed-Decision"};function le(e,t,r,n){if(N(t,"x-astrasync-"),n.mode!=="enforce")return r.decision!=="allow"&&R(t,T.observedDecision,r.decision),ue(t,r),t;switch(r.decision){case"deny":return U(403,ce(r,e.apiBaseUrl));case"manual_review":return U(202,de(r),{"Retry-After":"30"});default:return ue(t,r),t}}function ue(e,t){if(!t.asat)return;let{trustScore:r,agentId:n,developerId:a,accessLevel:i}=t.asat;r!==void 0&&R(e,T.trustScore,String(r)),n&&R(e,T.agentId,n),a&&R(e,T.developerId,a),i&&R(e,T.permissions,i)}function pe(e){let t=e.log??((r,n,a)=>{console[r==="info"?"log":r](`[astrasync-edge] ${n}`,a??"")});return async function(n){let a=F(n);try{let i=await q({...e,log:t}),o=await z(e,i),s=te(o,a.uri);if(s.skip)return a;let f=c(a,"x-forwarded-host")??c(a,"host")??new URL(e.counterpartyUrl).host,y=re(a,f,s.depth);if(y.tier==="human")return a;let u=await se({...e,log:t},a,y,s,i,o.sampling);return u.decision!=="allow"&&t("info",s.mode==="enforce"?`${u.decision.toUpperCase()}: ${a.method} ${a.uri}`:`[OBSERVE] would have been ${u.decision.toUpperCase()}: ${a.method} ${a.uri}`,{tier:u.tier,protocol:u.protocol,reasons:u.reasons}),le(e,a,u,s)}catch(i){return t("error","edge handler error \u2014 passing request through",{error:i instanceof Error?i.message:String(i)}),a}}}var tt="https://astrasync.ai/api",fe="",ge="",rt=void 0;(!fe||!ge)&&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 nt=pe({apiBaseUrl:tt,counterpartyId:fe,counterpartyUrl:ge,apiKeySecretName:rt});0&&(module.exports={handler});
@@ -0,0 +1,132 @@
1
+ # Edge adapter deployment runbook
2
+
3
+ Internal devops runbook for deploying the Commerce Shield edge shell
4
+ (Lambda@Edge + CloudFront) in front of an existing origin. Observe-only by
5
+ default — the deploy changes no site behaviour; it adds visibility.
6
+
7
+ ## Rollout order (decision 8 Jul 2026)
8
+
9
+ 1. **staging.astrasync.ai** — first install, our devops. Starts real data
10
+ collection and proves the shell against live mixed traffic.
11
+ 2. **astrasync.ai (production)** — rollover once staging is confirmed
12
+ stable: ≥1 week in observe mode with no origin 5xx/latency regression
13
+ attributable to the shell, events flowing in the dashboard, CloudWatch
14
+ error rate ~0.
15
+ 3. **Partner properties (e.g. astrasync.shop)** — partner-led. astrasync.shop
16
+ is run by a partner without access to this repo: they install from the
17
+ published npm package (`@astrasyncai/adapter-lambda`, which ships this
18
+ template + runbook) into **their** AWS account. We supply their ASTRAE
19
+ endpoint id and merchant API key; coordination happens outside GitHub.
20
+
21
+ ## Prerequisites (per property, one-time)
22
+
23
+ 1. **AWS account access** (us-east-1 — mandatory for Lambda@Edge), with
24
+ `aws` + `sam` CLIs authenticated.
25
+ 2. **ACM certificate** for the site domain in **us-east-1**:
26
+ `aws acm request-certificate --domain-name staging.astrasync.ai --validation-method DNS --region us-east-1`
27
+ then add the validation CNAME at the DNS host. CloudFront only accepts
28
+ us-east-1 certs.
29
+ 3. **Merchant API key secret** in Secrets Manager (us-east-1):
30
+ `aws secretsmanager create-secret --region us-east-1 --name astrasync/edge/staging-astrasync-ai --secret-string 'kya_<merchant API key>'`
31
+ The key belongs to the account that owns the property's ASTRAE endpoint
32
+ **on that environment's backend** (staging endpoint → staging API key).
33
+ Rotation: `put-secret-value` — the edge picks it up within 15 minutes,
34
+ no redeploy.
35
+ 4. **ASTRAE endpoint registered UNDER THE ASTRASYNC ORG ACCOUNT** for the
36
+ property URL (dashboard → Endpoints, on the matching environment) —
37
+ **never under a personal account**. The endpoint owner determines whose
38
+ dashboard receives the captured traffic and whose API key the edge
39
+ authenticates with; a personal-account registration strands the data
40
+ and couples the deployment to an individual. Devops are admins on the
41
+ AstraSync org (set up 8 Jul) — log in under the org context before
42
+ registering, and mint the API key (step 3) from the same org account.
43
+ Note the `ASTRAE-…` id. Optionally save an Edge verification config on
44
+ the endpoint page (defaults are observe-only/classify). For the
45
+ low-traffic staging install, set anonymous-beacon sampling to **100%**
46
+ — we want every event while validating.
47
+ 5. **A direct origin hostname.** CloudFront's origin cannot be the same
48
+ name it serves (loop). Our staging/prod sites run on manual EC2 —
49
+ create a DNS record that reaches the box directly (e.g.
50
+ `staging-origin.astrasync.ai` → EC2), and make sure nginx serves it
51
+ over HTTPS (add to the vhost/cert or serve as default vhost). The
52
+ original host travels to the origin as `X-Forwarded-Host`
53
+ (Managed-AllViewerExceptHostHeader). For partner installs on PaaS
54
+ hosting (e.g. Railway), the platform-issued domain
55
+ (`<service>.up.railway.app`) is the origin.
56
+
57
+ ## Deploy (staging example)
58
+
59
+ ```bash
60
+ export ASTRASYNC_COUNTERPARTY_ID="ASTRAE-…" # from step 4
61
+ export ASTRASYNC_COUNTERPARTY_URL="https://staging.astrasync.ai"
62
+ export ASTRASYNC_API_BASE_URL="https://staging.astrasync.ai/api" # match the environment
63
+ export ASTRASYNC_API_KEY_SECRET_NAME="astrasync/edge/staging-astrasync-ai"
64
+ export ORIGIN_DOMAIN="staging-origin.astrasync.ai" # from step 5
65
+ export SITE_DOMAIN="staging.astrasync.ai"
66
+ export ACM_CERT_ARN="arn:aws:acm:us-east-1:…" # from step 2
67
+ export STACK_NAME="astrasync-edge-shell-staging"
68
+ packages/adapter-lambda/infra/deploy.sh
69
+ ```
70
+
71
+ The build bakes the ASTRASYNC\_\* constants into the bundle (Lambda@Edge has
72
+ no environment variables). Redeploy with different values to change them.
73
+ Production rollover = the same commands with prod values
74
+ (`astrasync.ai`, `https://astrasync.ai/api`, its own secret + cert + stack
75
+ name) after the staging stability gate above.
76
+
77
+ ## DNS cutover
78
+
79
+ Point the site domain at the `DistributionDomainName` stack output:
80
+ ALIAS/ANAME (apex) or CNAME (subdomain). Keep the old record value noted
81
+ for rollback. CloudFront propagation: minutes; DNS: per TTL.
82
+
83
+ ## Smoke tests (observe mode)
84
+
85
+ ```bash
86
+ SITE=https://staging.astrasync.ai
87
+
88
+ # 1. Human path — site behaves identically, no AstraSync headers added:
89
+ curl -sI "$SITE/" -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/126.0" | head -5
90
+
91
+ # 2. Platform-agent UA — page still served (observe never blocks)…
92
+ curl -s "$SITE/" -A "Claude-User/1.0 (+https://anthropic.com)" -o /dev/null -w '%{http_code}\n'
93
+ # …and within ~1 min the visit appears in the dashboard activity feed /
94
+ # /admin/auto-provisioned (orphan "Auto-provisioned Anthropic Claude").
95
+
96
+ # 3. X-Astra credentialed agent — verify-access round trip:
97
+ curl -s "$SITE/" -H "X-Astra-Id: ASTRA-<test agent>" -H "X-Api-Key: <agent key>" -o /dev/null -w '%{http_code}\n'
98
+ # Check the verification appears in the dashboard activity feed.
99
+
100
+ # 4. Static asset — untouched, no events:
101
+ curl -sI "$SITE/favicon.ico" -o /dev/null -w '%{http_code}\n'
102
+ ```
103
+
104
+ Latency check: compare `curl -w '%{time_total}'` for the human path before
105
+ and after cutover — the human path makes zero AstraSync calls; added latency
106
+ should be CloudFront-hop only.
107
+
108
+ ## Observability
109
+
110
+ - Lambda@Edge logs land in the **regional** log group of whichever edge
111
+ location served the request: `/aws/lambda/us-east-1.astrasync-edge-shell`
112
+ (and sibling regions). Search for `[astrasync-edge]`.
113
+ - Observe-mode shadow decisions are logged as
114
+ `[OBSERVE] would have been DENY: …` and stamped on origin requests as
115
+ `X-AstraSync-Observed-Decision` (visible in origin/nginx logs).
116
+
117
+ ## Enforce mode (later — §33.5 #9)
118
+
119
+ Enforcement is enabled from the dashboard (endpoint → Edge verification →
120
+ mode: enforce; explicit confirmation + warning alert), never from infra.
121
+ The edge picks the change up within ~60s. Rollback = save observe again.
122
+ If the backend is unreachable the edge ALWAYS falls back to observe +
123
+ pass-through; a config stale for >24h auto-degrades enforce→observe.
124
+
125
+ ## Rollback
126
+
127
+ 1. **Fast**: repoint DNS back at the origin (the noted pre-cutover record).
128
+ The site serves exactly as before; the shell is simply out of the path.
129
+ 2. **Full teardown**: `aws cloudformation delete-stack --stack-name <stack> --region us-east-1`.
130
+ NOTE Lambda@Edge replica lag: function deletion fails until CloudFront
131
+ finishes disassociating replicas (can take a few hours). Delete the
132
+ distribution association first, wait, then delete the stack.
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env bash
2
+ # Commerce Shield edge adapter — build + deploy (devops-run, NOT CI).
3
+ # Prereqs: aws cli + sam cli authenticated against the AstraSync AWS account,
4
+ # us-east-1; the ACM cert and Secrets Manager secret already created
5
+ # (see RUNBOOK.md).
6
+ set -euo pipefail
7
+
8
+ # ---- Deployment constants (baked into the bundle: Lambda@Edge has no env vars)
9
+ export ASTRASYNC_API_BASE_URL="${ASTRASYNC_API_BASE_URL:-https://staging.astrasync.ai/api}"
10
+ export ASTRASYNC_COUNTERPARTY_ID="${ASTRASYNC_COUNTERPARTY_ID:?Set ASTRASYNC_COUNTERPARTY_ID to the property's ASTRAE-id}"
11
+ export ASTRASYNC_COUNTERPARTY_URL="${ASTRASYNC_COUNTERPARTY_URL:?Set ASTRASYNC_COUNTERPARTY_URL, e.g. https://staging.astrasync.ai}"
12
+ export ASTRASYNC_API_KEY_SECRET_NAME="${ASTRASYNC_API_KEY_SECRET_NAME:-astrasync/edge/staging-astrasync-ai}"
13
+
14
+ # ---- Template parameters
15
+ ORIGIN_DOMAIN="${ORIGIN_DOMAIN:?Set ORIGIN_DOMAIN to a hostname that reaches the origin directly, e.g. staging-origin.astrasync.ai}"
16
+ SITE_DOMAIN="${SITE_DOMAIN:-staging.astrasync.ai}"
17
+ ACM_CERT_ARN="${ACM_CERT_ARN:?Set ACM_CERT_ARN (us-east-1 certificate for ${SITE_DOMAIN})}"
18
+ STACK_NAME="${STACK_NAME:-astrasync-edge-shell-staging}"
19
+
20
+ cd "$(dirname "$0")/.."
21
+
22
+ echo ">> Building bundle with baked-in constants (counterparty ${ASTRASYNC_COUNTERPARTY_ID})"
23
+ npm run build
24
+
25
+ echo ">> Deploying ${STACK_NAME} to us-east-1"
26
+ sam deploy \
27
+ --template-file infra/template.yaml \
28
+ --stack-name "${STACK_NAME}" \
29
+ --region us-east-1 \
30
+ --capabilities CAPABILITY_IAM \
31
+ --resolve-s3 \
32
+ --no-fail-on-empty-changeset \
33
+ --parameter-overrides \
34
+ "OriginDomainName=${ORIGIN_DOMAIN}" \
35
+ "SiteDomainName=${SITE_DOMAIN}" \
36
+ "AcmCertificateArn=${ACM_CERT_ARN}" \
37
+ "ApiKeySecretName=${ASTRASYNC_API_KEY_SECRET_NAME}"
38
+
39
+ echo ">> Done. Outputs:"
40
+ aws cloudformation describe-stacks --stack-name "${STACK_NAME}" --region us-east-1 \
41
+ --query 'Stacks[0].Outputs' --output table
42
+ echo ">> Next: point ${SITE_DOMAIN} DNS at the DistributionDomainName above (see RUNBOOK.md)."
@@ -0,0 +1,119 @@
1
+ AWSTemplateFormatVersion: '2010-09-09'
2
+ Transform: AWS::Serverless-2016-10-31
3
+ Description: >
4
+ AstraSync Commerce Shield edge adapter (spec §7.4 / §33.5 #1) —
5
+ Lambda@Edge origin-request shell + CloudFront distribution in front of an
6
+ existing origin (first install: staging.astrasync.ai; prod rollover after
7
+ a stability gate; partner properties deploy from the npm package).
8
+ MUST be deployed to us-east-1 (Lambda@Edge home region).
9
+
10
+ Parameters:
11
+ OriginDomainName:
12
+ Type: String
13
+ Description: >
14
+ A hostname that reaches the EXISTING origin directly — e.g. a
15
+ dedicated origin record (staging-origin.astrasync.ai → the EC2), or a
16
+ PaaS-issued domain for partner installs. NEVER the public site domain:
17
+ pointing the origin at the domain CloudFront serves creates a loop.
18
+ SiteDomainName:
19
+ Type: String
20
+ Default: staging.astrasync.ai
21
+ Description: Public site domain served by CloudFront (alias / DNS target).
22
+ AcmCertificateArn:
23
+ Type: String
24
+ Description: >
25
+ ACM certificate ARN for SiteDomainName. Must live in us-east-1
26
+ (CloudFront requirement).
27
+ ApiKeySecretName:
28
+ Type: String
29
+ Default: astrasync/edge/staging-astrasync-ai
30
+ Description: >
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).
34
+
35
+ Resources:
36
+ EdgeFunctionRole:
37
+ Type: AWS::IAM::Role
38
+ Properties:
39
+ AssumeRolePolicyDocument:
40
+ Version: '2012-10-17'
41
+ Statement:
42
+ - Effect: Allow
43
+ Principal:
44
+ Service:
45
+ - lambda.amazonaws.com
46
+ - edgelambda.amazonaws.com
47
+ Action: sts:AssumeRole
48
+ ManagedPolicyArns:
49
+ - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
50
+ Policies:
51
+ - PolicyName: astrasync-edge-secret-read
52
+ PolicyDocument:
53
+ Version: '2012-10-17'
54
+ Statement:
55
+ - Effect: Allow
56
+ Action: secretsmanager:GetSecretValue
57
+ Resource: !Sub 'arn:aws:secretsmanager:us-east-1:${AWS::AccountId}:secret:${ApiKeySecretName}*'
58
+
59
+ EdgeFunction:
60
+ Type: AWS::Serverless::Function
61
+ Properties:
62
+ FunctionName: !Sub '${AWS::StackName}-fn'
63
+ Description: Commerce Shield edge interception shell (observe-only by default)
64
+ # Lambda@Edge constraints: no env vars, us-east-1, versioned ARN
65
+ # association. AutoPublishAlias gives us EdgeFunction.Version.
66
+ Runtime: nodejs20.x
67
+ Handler: index.handler
68
+ CodeUri: ../dist/lambda
69
+ MemorySize: 512
70
+ Timeout: 15
71
+ AutoPublishAlias: live
72
+ Role: !GetAtt EdgeFunctionRole.Arn
73
+
74
+ Distribution:
75
+ Type: AWS::CloudFront::Distribution
76
+ Properties:
77
+ DistributionConfig:
78
+ Comment: !Sub 'AstraSync Commerce Shield edge — ${SiteDomainName}'
79
+ Enabled: true
80
+ Aliases:
81
+ - !Ref SiteDomainName
82
+ ViewerCertificate:
83
+ AcmCertificateArn: !Ref AcmCertificateArn
84
+ SslSupportMethod: sni-only
85
+ MinimumProtocolVersion: TLSv1.2_2021
86
+ HttpVersion: http2and3
87
+ Origins:
88
+ - Id: site-origin
89
+ DomainName: !Ref OriginDomainName
90
+ CustomOriginConfig:
91
+ OriginProtocolPolicy: https-only
92
+ OriginSSLProtocols: [TLSv1.2]
93
+ DefaultCacheBehavior:
94
+ TargetOriginId: site-origin
95
+ ViewerProtocolPolicy: redirect-to-https
96
+ AllowedMethods: [GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE]
97
+ # v1 runs CachingDisabled so EVERY request reaches the shell —
98
+ # observe-mode fidelity beats cache hit-rate while the Agent
99
+ # Traffic Audit is the product. Tighten per-behavior later.
100
+ CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad # Managed-CachingDisabled
101
+ # Forward all viewer headers/cookies/query EXCEPT Host — the
102
+ # origin must receive the hostname it actually serves (nginx
103
+ # vhost / PaaS routing); the original host travels as
104
+ # X-Forwarded-Host.
105
+ OriginRequestPolicyId: b689b0a8-53d0-40ab-baf2-68738e2966ac # Managed-AllViewerExceptHostHeader
106
+ LambdaFunctionAssociations:
107
+ - EventType: origin-request
108
+ IncludeBody: true
109
+ LambdaFunctionARN: !Ref EdgeFunction.Version
110
+
111
+ Outputs:
112
+ DistributionDomainName:
113
+ Description: Point the site's DNS (ALIAS/CNAME) at this CloudFront domain.
114
+ Value: !GetAtt Distribution.DomainName
115
+ DistributionId:
116
+ Value: !Ref Distribution
117
+ EdgeFunctionVersionArn:
118
+ Description: The versioned Lambda@Edge ARN associated with the distribution.
119
+ Value: !Ref EdgeFunction.Version
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@astrasyncai/adapter-lambda",
3
+ "version": "1.0.0",
4
+ "description": "AstraSync Commerce Shield edge adapter — Lambda@Edge/CloudFront interception shell that classifies and verifies inbound agent traffic against the AstraSync platform. Observe-only by default.",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "infra",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup && node scripts/check-bundle-size.mjs",
22
+ "lint": "eslint src --ext .ts",
23
+ "typecheck": "tsc --noEmit",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest watch",
26
+ "clean": "rm -rf dist",
27
+ "prepublishOnly": "npm run clean && npm run typecheck && npm run build"
28
+ },
29
+ "keywords": [
30
+ "astrasync",
31
+ "commerce-shield",
32
+ "kya",
33
+ "edge",
34
+ "lambda-edge",
35
+ "cloudfront",
36
+ "agent-verification",
37
+ "bot-detection"
38
+ ],
39
+ "author": "AstraSync",
40
+ "license": "MIT",
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/AstraSync-KYA/KYA-Platform.git",
44
+ "directory": "packages/adapter-lambda"
45
+ },
46
+ "dependencies": {
47
+ "@astrasyncai/verification-gateway": "^3.9.0",
48
+ "@aws-sdk/client-secrets-manager": "^3.632.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/aws-lambda": "^8.10.145",
52
+ "@types/node": "^20.10.0",
53
+ "eslint": "^8.56.0",
54
+ "tsup": "^8.0.1",
55
+ "typescript": "^5.3.3",
56
+ "vitest": "^4.0.18"
57
+ }
58
+ }