@astrasyncai/adapter-lambda 1.2.0 → 2.1.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,76 +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
- /** ASAT header material when a verify-access call succeeded. */
42
- asat?: {
43
- trustScore?: number;
44
- agentId?: string;
45
- developerId?: string;
46
- accessLevel?: string;
47
- };
48
- sessionId?: string;
49
- protocol?: string;
50
- guidance?: {
51
- message?: string;
52
- registrationUrl?: string;
53
- documentationUrl?: string;
54
- };
55
- stepUp?: {
56
- pollUrl?: string;
57
- expiresAt?: string;
58
- };
59
- correlationId?: string;
60
- }
61
- /** Per-request effective policy after path-rule resolution. */
62
- interface EffectivePolicy {
63
- mode: EdgeMode;
64
- depth: EdgeVerificationDepth;
65
- skip: boolean;
66
- }
67
- interface EdgeAdapterOptions {
68
- /** AstraSync API base, e.g. `https://astrasync.ai/api`. */
69
- apiBaseUrl: string;
70
- /** The protected property's ASTRAE endpoint id. */
71
- counterpartyId: string;
72
- /** Canonical public URL of the protected property, e.g. `https://astrasync.shop`. */
73
- counterpartyUrl: string;
17
+ interface EdgeAdapterOptions extends EdgeCoreOptions {
74
18
  /**
75
19
  * Merchant API key (`kya_*`). Provide directly (tests/local) or via
76
20
  * `apiKeySecretName` (production — AWS Secrets Manager us-east-1, since
@@ -85,33 +29,21 @@ interface EdgeAdapterOptions {
85
29
  fetchSecret?: (secretName: string) => Promise<string | undefined>;
86
30
  /** Edge-config cache TTL (ms). Default 60s. */
87
31
  configTtlMs?: number;
88
- /** Time budgets (ms). */
89
- budgets?: {
90
- /** Fire-and-forget beacon budget. Default 300. */
91
- beaconMs?: number;
92
- /** verify-access budget in observe mode. Default 1500. */
93
- verifyObserveMs?: number;
94
- /** verify-access budget in enforce mode. Default 3000. */
95
- verifyEnforceMs?: number;
96
- };
97
32
  /**
98
33
  * Compile-time fallback config used before the first successful
99
34
  * edge-config fetch and whenever the backend is unreachable with a cold
100
35
  * cache. Defaults to the SDK's DEFAULT_EDGE_CONFIG (observe/classify).
101
36
  */
102
37
  fallbackConfig?: EdgeConfig;
103
- /** Random source for beacon sampling — injectable for tests. */
104
- random?: () => number;
105
- /** Structured log sink. Defaults to console. */
106
- log?: (level: 'info' | 'warn' | 'error', message: string, data?: Record<string, unknown>) => void;
107
38
  }
108
39
 
109
40
  /**
110
- * Commerce Shield edge shell — Lambda@Edge origin-request handler factory
111
- * (§7.4 / §33.5 #1).
41
+ * Trusted Agent Gateway edge shell — Lambda@Edge origin-request handler
42
+ * factory.
112
43
  *
113
44
  * Composition per request:
114
- * 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
115
47
  *
116
48
  * THE invariant (tested): outside enforce mode the handler ALWAYS returns
117
49
  * the origin-bound request — any error, timeout, or misconfiguration
@@ -123,41 +55,27 @@ type EdgeHandler = (event: CloudFrontRequestEvent) => Promise<CloudFrontRequestR
123
55
  declare function createEdgeHandler(options: EdgeAdapterOptions): EdgeHandler;
124
56
 
125
57
  /**
126
- * Three-tier traffic classification (§33.5 #1: verified /
127
- * identified-but-unregistered / anonymous) plus the two non-tiers the shell
128
- * touches as little as possible: `human` (zero network calls, zero logging)
129
- * and `skipped` (static assets / excluded paths).
130
- *
131
- * Cheapest checks first — the human path must add microseconds, not
132
- * milliseconds. Platform signatures come from the SDK so the edge and the
133
- * 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.
134
63
  */
135
64
 
136
- /**
137
- * Resolve the effective mode/depth for a path from the EdgeConfig — ordered
138
- * first-match-wins rules with case-insensitive globs; no match falls through
139
- * to the config's top-level defaults. Static extensions are always skipped
140
- * regardless of rules (a rule can only skip MORE, never un-skip an asset).
141
- */
142
- declare function resolvePolicy(config: EdgeConfig, path: string): EffectivePolicy;
143
- /**
144
- * Classify one request. Order (cheapest sufficient evidence wins):
145
- * 1. X-Astra-* credentials → `verified` candidate
146
- * 2. commerce-protocol credentials on the wire → `identified`
147
- * 3. platform UA fingerprint (Claude/ChatGPT/Gemini/…) → `identified`
148
- * 4. bot-shaped UA / headerless non-browser → `anonymous-bot`
149
- * 5. everything browser-shaped → `human`
150
- *
151
- * `depth: 'classify'` skips step 2 (no body decode, no header sniffing
152
- * beyond UA) — that is the zero-friction setting.
153
- */
65
+ /** Classify one CloudFront origin-request. See the edge core for the tier order. */
154
66
  declare function classify(request: CloudFrontRequest, host: string, depth: 'classify' | 'authenticate' | 'authorize'): Classification;
155
67
 
156
68
  /**
157
- * CloudFront origin-request event helpers. The Lambda@Edge event shape puts
158
- * headers in `{ key, value }[]` arrays keyed by LOWERCASED header name, and
159
- * (with IncludeBody) the body arrives base64-encoded with an
160
- * `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.
161
79
  */
162
80
 
163
81
  declare function getRequest(event: CloudFrontRequestEvent): CloudFrontRequest;
@@ -190,55 +108,27 @@ declare function stripHeadersByPrefix(request: CloudFrontRequest, prefix: string
190
108
  declare function jsonResponse(status: number, body: unknown, extraHeaders?: Record<string, string>): CloudFrontResultResponse;
191
109
 
192
110
  /**
193
- * Crypto-free commerce-protocol detection (§7.4.2 detection order).
194
- *
195
- * The edge only SNIFFS — header shapes, compact-JWT patterns, body field
196
- * names — and packages what it saw as raw `CommerceArtifactsPayload` for
197
- * verify-access, whose Step 0.5 pipeline does the authoritative parsing and
198
- * cryptographic verification server-side. Nothing here imports jose/sd-jwt/
199
- * signature libraries: detection must stay cheap enough to run on every
200
- * non-human request, and verification must happen exactly once, in the
201
- * 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.
202
116
  */
203
117
 
204
- interface DetectedCommerce {
205
- /** Detection-order label: rfc9421-agent-pay | rfc9421-tap | rfc9421-web-bot-auth | vi-sd-jwt | ap2 | acp | ucp | mpp | x402 */
206
- protocol: string;
207
- artifacts: CommerceArtifactsPayload;
208
- /** Light detection detail for beacons/audit — never secrets or full credentials. */
209
- evidence: Record<string, unknown>;
210
- }
211
118
  /**
212
- * §7.4.2 order (after the X-Astra native check, which classify.ts owns):
213
- * SD-JWT/VI → RFC 9421 (Agent Pay / TAP / Web Bot Auth by kid namespace or
214
- * Signature-Agent) → ACP HMAC → UCP session → AP2 body triple → MPP → x402.
215
- * Returns undefined when nothing commerce-shaped is on the wire.
216
- *
217
- * When the body was truncated by CloudFront (`inputTruncated`), body-bound
218
- * artifacts still forward what arrived but carry a `bodyTruncated` evidence
219
- * 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.
220
122
  */
221
123
  declare function detectCommerce(request: CloudFrontRequest, host: string, body: DecodedBody): DetectedCommerce | undefined;
222
124
 
223
125
  /**
224
- * Depth-controlled verification per tier. The edge never verifies
225
- * credentials itself — it forwards what it detected to verify-access, the
226
- * canonical sole verification sink (backend Step 0.5 runs the commerce
227
- * pipeline, records events, provisions orphans, persists sessions). What
228
- * the depth setting controls is how much the edge LOOKS and how much it
229
- * FORWARDS:
230
- *
231
- * classify — what is it? UA tiers only. Zero verify-access calls;
232
- * beacons only.
233
- * authenticate — who is it? + protocol detection. X-Astra agents get a
234
- * verify-access identity check; commerce/platform traffic
235
- * is beaconed with protocol + evidence (no signature
236
- * verification anywhere).
237
- * authorize — are they allowed? + artifact forwarding. X-Astra verify
238
- * calls carry commerceArtifacts; identified traffic gets an
239
- * anonymous verify-access call with artifacts +
240
- * callerMetadata so the backend cryptographically proves
241
- * 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.
242
132
  */
243
133
 
244
134
  /**
@@ -253,20 +143,13 @@ declare function runTier(options: EdgeAdapterOptions, request: CloudFrontRequest
253
143
  }): Promise<TierOutcome>;
254
144
 
255
145
  /**
256
- * Decision → CloudFront result wiring (§7.4 enforcement, §7.4.7 ASAT
257
- * headers). Executed in BOTH modes so observe mode records exactly what
258
- * enforce mode would have done — but only enforce mode is allowed to return
259
- * 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.
260
151
  */
261
152
 
262
- /** §7.4.7 ASAT trust-attestation headers injected on allowed requests. */
263
- declare const ASAT_HEADERS: {
264
- readonly trustScore: "X-AstraSync-Trust-Score";
265
- readonly agentId: "X-AstraSync-Agent-Id";
266
- readonly developerId: "X-AstraSync-Developer-Id";
267
- readonly permissions: "X-AstraSync-Permissions";
268
- readonly observedDecision: "X-AstraSync-Observed-Decision";
269
- };
270
153
  /**
271
154
  * Apply the outcome. Always strips inbound spoofed `x-astrasync-*` headers
272
155
  * first (both modes — trust headers must only ever originate here).
@@ -280,51 +163,13 @@ declare const ASAT_HEADERS: {
280
163
  declare function applyOutcome(options: EdgeAdapterOptions, request: CloudFrontRequest, outcome: TierOutcome, policy: EffectivePolicy): CloudFrontRequestResult;
281
164
 
282
165
  /**
283
- * §7.4.6 — protocol-specific machine-readable messaging for enforce-mode
284
- * responses. Agents (not humans) consume these bodies: stable error codes,
285
- * the failure list, and registration guidance with real URLs.
286
- */
287
-
288
- interface DenyBody {
289
- success: false;
290
- error: {
291
- code: 'UNAUTHORIZED' | 'INSUFFICIENT_ACCESS';
292
- message: string;
293
- protocol?: string;
294
- failures: string[];
295
- correlationId?: string;
296
- guidance: {
297
- message?: string;
298
- registrationUrl?: string;
299
- documentationUrl?: string;
300
- };
301
- };
302
- }
303
- declare function buildDenyBody(outcome: TierOutcome, apiBaseUrl: string): DenyBody;
304
- interface ManualReviewBody {
305
- success: false;
306
- status: 'manual_review';
307
- message: string;
308
- stepUpApproval?: {
309
- pollUrl?: string;
310
- expiresAt?: string;
311
- };
312
- correlationId?: string;
313
- }
314
- declare function buildManualReviewBody(outcome: TierOutcome): ManualReviewBody;
315
-
316
- /**
317
- * Time-budgeted event emission.
318
- *
319
- * Lambda@Edge has no `waitUntil` — anything not awaited before the handler
320
- * returns may never run (the container freezes). So every network call is
321
- * awaited under an explicit budget and DROPPED on timeout: latency to the
322
- * customer's traffic is bounded, and a slow AstraSync API costs telemetry,
323
- * 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.
324
171
  */
325
172
 
326
- /** Await `promise` for at most `ms`; resolve `undefined` on timeout/error. */
327
- declare function withBudget<T>(promise: Promise<T>, ms: number): Promise<T | undefined>;
328
173
  /**
329
174
  * Emit an unregistered-attempt beacon for `identified` (non-crypto depths)
330
175
  * and sampled `anonymous-bot` traffic. Unauthenticated by design
@@ -332,8 +177,6 @@ declare function withBudget<T>(promise: Promise<T>, ms: number): Promise<T | und
332
177
  * find-or-provisions orphan platform agents server-side.
333
178
  */
334
179
  declare function emitBeacon(options: EdgeAdapterOptions, request: CloudFrontRequest, classification: Classification, budgetMs: number): Promise<void>;
335
- /** Deterministic-in-tests sampling gate. */
336
- declare function sampled(rate: number, random?: () => number): boolean;
337
180
 
338
181
  /**
339
182
  * Runtime configuration for the edge shell.
@@ -367,4 +210,4 @@ declare function loadEdgeConfig(options: EdgeAdapterOptions, apiKey: string | un
367
210
  /** Reset module caches — tests only. */
368
211
  declare function _resetConfigCaches(): void;
369
212
 
370
- 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 };