@astrasyncai/adapter-lambda 2.0.0 → 2.2.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/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @astrasyncai/adapter-lambda
2
2
 
3
- **AstraSync Commerce Shield edge adapter** — a Lambda@Edge/CloudFront
4
- interception shell that classifies and verifies inbound AI-agent traffic in
5
- front of your existing site. Zero site changes; **observe-only by default**.
3
+ **AstraSync Trusted Agent Gateway (CloudFront adapter)** — a
4
+ Lambda@Edge/CloudFront interception shell that classifies and verifies
5
+ inbound AI-agent traffic in front of your existing site. Zero site changes; **observe-only by default**.
6
6
 
7
7
  Most of the web's traffic is now machines, and the analytics stack —
8
8
  GA4, session replay, attribution pixels, A/B tests — is structurally blind
@@ -13,12 +13,12 @@ adapter sits at your CDN edge and gives you the missing lens.
13
13
 
14
14
  Every request is classified into a visibility tier:
15
15
 
16
- | Tier | Signal | What happens |
17
- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
18
- | **Verified** | `X-Astra-*` AstraSync credentials | Full verify-access round trip: identity, trust score, PDLSS mandate |
19
- | **Identified (unregistered)** | Payment-rail / signed-agent credentials (Visa Intelligent Commerce SD-JWTs, Mastercard Agent Pay & Visa TAP RFC 9421 signatures, Web Bot Auth, ACP, UCP, AP2, MPP, x402) or a platform-agent UA (Claude, ChatGPT, Gemini, …) | Recorded with protocol evidence; platform agents surface in your dashboard automatically |
20
- | **Anonymous bot** | CLI/library/headless UA shapes | Sampled telemetry |
21
- | **Human** | Browser-shaped traffic | **Untouched — zero API calls, zero added latency** |
16
+ | Tier | Signal | What happens |
17
+ | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
18
+ | **Verified** | `X-Astra-*` AstraSync credentials | Full verify-access round trip: identity, trust score, PDLSS mandate |
19
+ | **Identified (unregistered)** | Payment-rail / signed-agent credentials (Visa Intelligent Commerce SD-JWTs, Mastercard Agent Pay & Visa TAP RFC 9421 signatures, Web Bot Auth, ACP, UCP, AP2, MPP, x402) or a platform-agent UA (Claude, ChatGPT, Gemini, …) | Recorded with protocol evidence; platform agents surface in your Visit Intelligence feed automatically |
20
+ | **Anonymous bot** | CLI/library/headless UA shapes | Sampled telemetry |
21
+ | **Human** | Browser-shaped traffic | **Untouched — zero API calls, zero added latency** |
22
22
 
23
23
  Static assets and any paths you configure are skipped entirely.
24
24
 
package/dist/index.d.mts CHANGED
@@ -1,83 +1,20 @@
1
1
  import { CloudFrontRequestEvent, CloudFrontRequestResult, CloudFrontRequest, CloudFrontHeaders, CloudFrontResultResponse } from 'aws-lambda';
2
- import { EdgeConfig, EdgeMode, EdgeVerificationDepth } from '@astrasyncai/verification-gateway/edge-config';
3
- import { PlatformFingerprint } from '@astrasyncai/verification-gateway/platform-signatures';
4
- import { CommerceArtifactsPayload } from '@astrasyncai/verification-gateway';
2
+ import { EdgeConfig } from '@astrasyncai/verification-gateway/edge-config';
3
+ import { EdgeCoreOptions, Classification, DetectedCommerce, EffectivePolicy, TierOutcome } from '@astrasyncai/verification-gateway/edge-core';
4
+ export { ASAT_HEADERS, Classification, DetectedCommerce, EdgeDecision, EffectivePolicy, TierOutcome, TrafficTier, buildDenyBody, buildManualReviewBody, resolvePolicy, sampled, withBudget } from '@astrasyncai/verification-gateway/edge-core';
5
5
 
6
6
  /**
7
- * Commerce Shield edge adapter (spec §7.4 / §33.5 #1) — shared types.
7
+ * Trusted Agent Gateway — CloudFront/Lambda@Edge adapter — shared types.
8
8
  *
9
- * The adapter is a thin interception shell: it classifies inbound traffic
10
- * into three visibility tiers, applies the dashboard-configured EdgeConfig
11
- * (mode/depth/path rules), forwards raw commerce artifacts to verify-access
12
- * (which does ALL cryptographic verification server-side, Step 0.5), and —
13
- * only in enforce mode — turns decisions into responses. In observe mode it
14
- * NEVER blocks and NEVER mutates responses.
9
+ * The adapter is a thin interception shell over the Trusted Agent Gateway
10
+ * edge core (`@astrasyncai/verification-gateway/edge-core`), which owns the
11
+ * platform-neutral classification/verification/enforcement pipeline. This
12
+ * package contributes the CloudFront platform I/O (event normalization,
13
+ * outcome application) plus Lambda@Edge-specific configuration (Secrets
14
+ * Manager, baked build-time constants).
15
15
  */
16
16
 
17
- /**
18
- * The three visibility tiers of the Commerce Shield live agent feed, plus
19
- * `human` (which the shell touches as little as possible) and `skipped`
20
- * (path-filtered — static assets etc.).
21
- */
22
- type TrafficTier = 'verified' | 'identified' | 'anonymous-bot' | 'human' | 'skipped';
23
- interface Classification {
24
- tier: TrafficTier;
25
- /** Detected transport/credential protocol (tier `identified`/`verified`). */
26
- protocol?: string;
27
- /** Platform UA fingerprint when one matched. */
28
- fingerprint?: PlatformFingerprint;
29
- /** Raw commerce artifacts detected on the wire, ready to forward. */
30
- artifacts?: CommerceArtifactsPayload;
31
- /** Light, crypto-free detection detail for the beacon (kid namespace etc). */
32
- evidence?: Record<string, unknown>;
33
- }
34
- /** What the shell decided (observe mode records it; enforce mode acts on it). */
35
- type EdgeDecision = 'allow' | 'deny' | 'manual_review';
36
- interface TierOutcome {
37
- tier: TrafficTier;
38
- decision: EdgeDecision;
39
- /** Why (deny/step-up reasons, or 'observe-passthrough'). */
40
- reasons: string[];
41
- /**
42
- * 2.0.0: the property's own API key was rejected by verify-access
43
- * (merchant misconfig). The outcome is `allow` (fail-open in BOTH modes —
44
- * agents must not be blocked by the property's dead key) but the flag
45
- * stamps X-AstraSync-Observed-Decision: misconfig for origin-side logs.
46
- */
47
- misconfig?: boolean;
48
- /** ASAT header material when a verify-access call succeeded. */
49
- asat?: {
50
- trustScore?: number;
51
- agentId?: string;
52
- developerId?: string;
53
- accessLevel?: string;
54
- };
55
- sessionId?: string;
56
- protocol?: string;
57
- guidance?: {
58
- message?: string;
59
- registrationUrl?: string;
60
- documentationUrl?: string;
61
- };
62
- stepUp?: {
63
- pollUrl?: string;
64
- expiresAt?: string;
65
- };
66
- correlationId?: string;
67
- }
68
- /** Per-request effective policy after path-rule resolution. */
69
- interface EffectivePolicy {
70
- mode: EdgeMode;
71
- depth: EdgeVerificationDepth;
72
- skip: boolean;
73
- }
74
- interface EdgeAdapterOptions {
75
- /** AstraSync API base, e.g. `https://astrasync.ai/api`. */
76
- apiBaseUrl: string;
77
- /** The protected property's ASTRAE endpoint id. */
78
- counterpartyId: string;
79
- /** Canonical public URL of the protected property, e.g. `https://astrasync.shop`. */
80
- counterpartyUrl: string;
17
+ interface EdgeAdapterOptions extends EdgeCoreOptions {
81
18
  /**
82
19
  * Merchant API key (`kya_*`). Provide directly (tests/local) or via
83
20
  * `apiKeySecretName` (production — AWS Secrets Manager us-east-1, since
@@ -92,33 +29,21 @@ interface EdgeAdapterOptions {
92
29
  fetchSecret?: (secretName: string) => Promise<string | undefined>;
93
30
  /** Edge-config cache TTL (ms). Default 60s. */
94
31
  configTtlMs?: number;
95
- /** Time budgets (ms). */
96
- budgets?: {
97
- /** Fire-and-forget beacon budget. Default 300. */
98
- beaconMs?: number;
99
- /** verify-access budget in observe mode. Default 1500. */
100
- verifyObserveMs?: number;
101
- /** verify-access budget in enforce mode. Default 3000. */
102
- verifyEnforceMs?: number;
103
- };
104
32
  /**
105
33
  * Compile-time fallback config used before the first successful
106
34
  * edge-config fetch and whenever the backend is unreachable with a cold
107
35
  * cache. Defaults to the SDK's DEFAULT_EDGE_CONFIG (observe/classify).
108
36
  */
109
37
  fallbackConfig?: EdgeConfig;
110
- /** Random source for beacon sampling — injectable for tests. */
111
- random?: () => number;
112
- /** Structured log sink. Defaults to console. */
113
- log?: (level: 'info' | 'warn' | 'error', message: string, data?: Record<string, unknown>) => void;
114
38
  }
115
39
 
116
40
  /**
117
- * Commerce Shield edge shell — Lambda@Edge origin-request handler factory
118
- * (§7.4 / §33.5 #1).
41
+ * Trusted Agent Gateway edge shell — Lambda@Edge origin-request handler
42
+ * factory.
119
43
  *
120
44
  * Composition per request:
121
- * config (cached) → path policy → classify → tier pipeline → apply outcome
45
+ * config (cached) → edge core evaluation (path policy → classify → tier
46
+ * pipeline) → apply outcome onto the CloudFront request
122
47
  *
123
48
  * THE invariant (tested): outside enforce mode the handler ALWAYS returns
124
49
  * the origin-bound request — any error, timeout, or misconfiguration
@@ -130,41 +55,27 @@ type EdgeHandler = (event: CloudFrontRequestEvent) => Promise<CloudFrontRequestR
130
55
  declare function createEdgeHandler(options: EdgeAdapterOptions): EdgeHandler;
131
56
 
132
57
  /**
133
- * Three-tier traffic classification (§33.5 #1: verified /
134
- * identified-but-unregistered / anonymous) plus the two non-tiers the shell
135
- * touches as little as possible: `human` (zero network calls, zero logging)
136
- * and `skipped` (static assets / excluded paths).
137
- *
138
- * Cheapest checks first — the human path must add microseconds, not
139
- * milliseconds. Platform signatures come from the SDK so the edge and the
140
- * backend's verify-access anonymous handler classify identically.
58
+ * Three-tier traffic classification — CloudFront wrapper over
59
+ * the edge core's classifier. The classification logic itself (tier order,
60
+ * UA patterns, path-rule resolution) lives in
61
+ * `@astrasyncai/verification-gateway/edge-core` and is shared with every
62
+ * edge platform adapter.
141
63
  */
142
64
 
143
- /**
144
- * Resolve the effective mode/depth for a path from the EdgeConfig — ordered
145
- * first-match-wins rules with case-insensitive globs; no match falls through
146
- * to the config's top-level defaults. Static extensions are always skipped
147
- * regardless of rules (a rule can only skip MORE, never un-skip an asset).
148
- */
149
- declare function resolvePolicy(config: EdgeConfig, path: string): EffectivePolicy;
150
- /**
151
- * Classify one request. Order (cheapest sufficient evidence wins):
152
- * 1. X-Astra-* credentials → `verified` candidate
153
- * 2. commerce-protocol credentials on the wire → `identified`
154
- * 3. platform UA fingerprint (Claude/ChatGPT/Gemini/…) → `identified`
155
- * 4. bot-shaped UA / headerless non-browser → `anonymous-bot`
156
- * 5. everything browser-shaped → `human`
157
- *
158
- * `depth: 'classify'` skips step 2 (no body decode, no header sniffing
159
- * beyond UA) — that is the zero-friction setting.
160
- */
65
+ /** Classify one CloudFront origin-request. See the edge core for the tier order. */
161
66
  declare function classify(request: CloudFrontRequest, host: string, depth: 'classify' | 'authenticate' | 'authorize'): Classification;
162
67
 
163
68
  /**
164
- * CloudFront origin-request event helpers. The Lambda@Edge event shape puts
165
- * headers in `{ key, value }[]` arrays keyed by LOWERCASED header name, and
166
- * (with IncludeBody) the body arrives base64-encoded with an
167
- * `inputTruncated` flag when it exceeded CloudFront's ~1MB exposure cap.
69
+ * CloudFront platform I/O — the Lambda@Edge side of the edge core's
70
+ * PlatformIo contract, plus origin-request event helpers.
71
+ *
72
+ * The Lambda@Edge event shape puts headers in `{ key, value }[]` arrays
73
+ * keyed by LOWERCASED header name, and (with IncludeBody) the body arrives
74
+ * base64-encoded with an `inputTruncated` flag when it exceeded
75
+ * CloudFront's ~1MB exposure cap. `toNormalizedRequest` converts that into
76
+ * the core's NormalizedRequest; `applyCoreOutcome` executes the core's
77
+ * abstract outcome application against the CloudFront request/response
78
+ * primitives.
168
79
  */
169
80
 
170
81
  declare function getRequest(event: CloudFrontRequestEvent): CloudFrontRequest;
@@ -197,55 +108,27 @@ declare function stripHeadersByPrefix(request: CloudFrontRequest, prefix: string
197
108
  declare function jsonResponse(status: number, body: unknown, extraHeaders?: Record<string, string>): CloudFrontResultResponse;
198
109
 
199
110
  /**
200
- * Crypto-free commerce-protocol detection (§7.4.2 detection order).
201
- *
202
- * The edge only SNIFFS — header shapes, compact-JWT patterns, body field
203
- * names — and packages what it saw as raw `CommerceArtifactsPayload` for
204
- * verify-access, whose Step 0.5 pipeline does the authoritative parsing and
205
- * cryptographic verification server-side. Nothing here imports jose/sd-jwt/
206
- * signature libraries: detection must stay cheap enough to run on every
207
- * non-human request, and verification must happen exactly once, in the
208
- * canonical sink, where it is recorded.
111
+ * Crypto-free commerce-protocol detection (fixed detection order) —
112
+ * CloudFront wrapper over the edge core's detector. The sniffing logic
113
+ * (header shapes, compact-JWT patterns, body field names) lives in
114
+ * `@astrasyncai/verification-gateway/edge-core`; this module adapts the
115
+ * CloudFront event shape (separately-decoded body) onto it.
209
116
  */
210
117
 
211
- interface DetectedCommerce {
212
- /** Detection-order label: rfc9421-agent-pay | rfc9421-tap | rfc9421-web-bot-auth | vi-sd-jwt | ap2 | acp | ucp | mpp | x402 */
213
- protocol: string;
214
- artifacts: CommerceArtifactsPayload;
215
- /** Light detection detail for beacons/audit — never secrets or full credentials. */
216
- evidence: Record<string, unknown>;
217
- }
218
118
  /**
219
- * §7.4.2 order (after the X-Astra native check, which classify.ts owns):
220
- * SD-JWT/VI → RFC 9421 (Agent Pay / TAP / Web Bot Auth by kid namespace or
221
- * Signature-Agent) → ACP HMAC → UCP session → AP2 body triple → MPP → x402.
222
- * Returns undefined when nothing commerce-shaped is on the wire.
223
- *
224
- * When the body was truncated by CloudFront (`inputTruncated`), body-bound
225
- * artifacts still forward what arrived but carry a `bodyTruncated` evidence
226
- * flag — the backend downgrades those signatures rather than hard-failing.
119
+ * Detect commerce-protocol credentials on a CloudFront origin-request.
120
+ * `body` is the caller-decoded request body (see `decodeBody`) — kept as an
121
+ * explicit parameter so callers that already decoded it don't pay twice.
227
122
  */
228
123
  declare function detectCommerce(request: CloudFrontRequest, host: string, body: DecodedBody): DetectedCommerce | undefined;
229
124
 
230
125
  /**
231
- * Depth-controlled verification per tier. The edge never verifies
232
- * credentials itself — it forwards what it detected to verify-access, the
233
- * canonical sole verification sink (backend Step 0.5 runs the commerce
234
- * pipeline, records events, provisions orphans, persists sessions). What
235
- * the depth setting controls is how much the edge LOOKS and how much it
236
- * FORWARDS:
237
- *
238
- * classify — what is it? UA tiers only. Zero verify-access calls;
239
- * beacons only.
240
- * authenticate — who is it? + protocol detection. X-Astra agents get a
241
- * verify-access identity check; commerce/platform traffic
242
- * is beaconed with protocol + evidence (no signature
243
- * verification anywhere).
244
- * authorize — are they allowed? + artifact forwarding. X-Astra verify
245
- * calls carry commerceArtifacts; identified traffic gets an
246
- * anonymous verify-access call with artifacts +
247
- * callerMetadata so the backend cryptographically proves
248
- * and policy-evaluates once.
126
+ * Depth-controlled verification per tier — CloudFront wrapper over the edge
127
+ * core's tier pipeline. The verification semantics (what each depth looks
128
+ * at and forwards, the fail-open rules, the verify-access request shape)
129
+ * live in `@astrasyncai/verification-gateway/edge-core`; the edge never
130
+ * verifies credentials itself — verify-access is the canonical sole
131
+ * verification sink.
249
132
  */
250
133
 
251
134
  /**
@@ -260,20 +143,13 @@ declare function runTier(options: EdgeAdapterOptions, request: CloudFrontRequest
260
143
  }): Promise<TierOutcome>;
261
144
 
262
145
  /**
263
- * Decision → CloudFront result wiring (§7.4 enforcement, §7.4.7 ASAT
264
- * headers). Executed in BOTH modes so observe mode records exactly what
265
- * enforce mode would have done — but only enforce mode is allowed to return
266
- * anything other than the origin-bound request.
146
+ * Decision → CloudFront result wiring (enforcement + ASAT trust-attestation
147
+ * headers). The decision logic (observe shadow stamps, misconfig fail-open,
148
+ * enforce-mode response bodies) lives in the edge core; this module
149
+ * executes the core's abstract outcome application against CloudFront
150
+ * request/response primitives.
267
151
  */
268
152
 
269
- /** §7.4.7 ASAT trust-attestation headers injected on allowed requests. */
270
- declare const ASAT_HEADERS: {
271
- readonly trustScore: "X-AstraSync-Trust-Score";
272
- readonly agentId: "X-AstraSync-Agent-Id";
273
- readonly developerId: "X-AstraSync-Developer-Id";
274
- readonly permissions: "X-AstraSync-Permissions";
275
- readonly observedDecision: "X-AstraSync-Observed-Decision";
276
- };
277
153
  /**
278
154
  * Apply the outcome. Always strips inbound spoofed `x-astrasync-*` headers
279
155
  * first (both modes — trust headers must only ever originate here).
@@ -287,51 +163,13 @@ declare const ASAT_HEADERS: {
287
163
  declare function applyOutcome(options: EdgeAdapterOptions, request: CloudFrontRequest, outcome: TierOutcome, policy: EffectivePolicy): CloudFrontRequestResult;
288
164
 
289
165
  /**
290
- * §7.4.6 — protocol-specific machine-readable messaging for enforce-mode
291
- * responses. Agents (not humans) consume these bodies: stable error codes,
292
- * the failure list, and registration guidance with real URLs.
293
- */
294
-
295
- interface DenyBody {
296
- success: false;
297
- error: {
298
- code: 'UNAUTHORIZED' | 'INSUFFICIENT_ACCESS';
299
- message: string;
300
- protocol?: string;
301
- failures: string[];
302
- correlationId?: string;
303
- guidance: {
304
- message?: string;
305
- registrationUrl?: string;
306
- documentationUrl?: string;
307
- };
308
- };
309
- }
310
- declare function buildDenyBody(outcome: TierOutcome, apiBaseUrl: string): DenyBody;
311
- interface ManualReviewBody {
312
- success: false;
313
- status: 'manual_review';
314
- message: string;
315
- stepUpApproval?: {
316
- pollUrl?: string;
317
- expiresAt?: string;
318
- };
319
- correlationId?: string;
320
- }
321
- declare function buildManualReviewBody(outcome: TierOutcome): ManualReviewBody;
322
-
323
- /**
324
- * Time-budgeted event emission.
325
- *
326
- * Lambda@Edge has no `waitUntil` — anything not awaited before the handler
327
- * returns may never run (the container freezes). So every network call is
328
- * awaited under an explicit budget and DROPPED on timeout: latency to the
329
- * customer's traffic is bounded, and a slow AstraSync API costs telemetry,
330
- * never page loads.
166
+ * Time-budgeted event emission — CloudFront wrapper over the edge core's
167
+ * telemetry. Lambda@Edge has no `waitUntil`, so every network call is
168
+ * awaited under an explicit budget and DROPPED on timeout (the core's
169
+ * default posture): latency to the customer's traffic is bounded, and a
170
+ * slow AstraSync API costs telemetry, never page loads.
331
171
  */
332
172
 
333
- /** Await `promise` for at most `ms`; resolve `undefined` on timeout/error. */
334
- declare function withBudget<T>(promise: Promise<T>, ms: number): Promise<T | undefined>;
335
173
  /**
336
174
  * Emit an unregistered-attempt beacon for `identified` (non-crypto depths)
337
175
  * and sampled `anonymous-bot` traffic. Unauthenticated by design
@@ -339,8 +177,6 @@ declare function withBudget<T>(promise: Promise<T>, ms: number): Promise<T | und
339
177
  * find-or-provisions orphan platform agents server-side.
340
178
  */
341
179
  declare function emitBeacon(options: EdgeAdapterOptions, request: CloudFrontRequest, classification: Classification, budgetMs: number): Promise<void>;
342
- /** Deterministic-in-tests sampling gate. */
343
- declare function sampled(rate: number, random?: () => number): boolean;
344
180
 
345
181
  /**
346
182
  * Runtime configuration for the edge shell.
@@ -374,4 +210,4 @@ declare function loadEdgeConfig(options: EdgeAdapterOptions, apiKey: string | un
374
210
  /** Reset module caches — tests only. */
375
211
  declare function _resetConfigCaches(): void;
376
212
 
377
- export { ASAT_HEADERS, type Classification, type DetectedCommerce, type EdgeAdapterOptions, type EdgeDecision, type EdgeHandler, type EffectivePolicy, type TierOutcome, type TrafficTier, _resetConfigCaches, applyOutcome, buildDenyBody, buildManualReviewBody, classify, createEdgeHandler, decodeBody, detectCommerce, emitBeacon, flattenHeaders, getHeader, getRequest, jsonResponse, loadEdgeConfig, requestUrl, resolveApiKey, resolvePolicy, runTier, sampled, setHeader, stripHeadersByPrefix, withBudget };
213
+ export { type EdgeAdapterOptions, type EdgeHandler, _resetConfigCaches, applyOutcome, classify, createEdgeHandler, decodeBody, detectCommerce, emitBeacon, flattenHeaders, getHeader, getRequest, jsonResponse, loadEdgeConfig, requestUrl, resolveApiKey, runTier, setHeader, stripHeadersByPrefix };