@astrasyncai/verification-gateway 4.0.0 → 4.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 +106 -29
- package/dist/adapter-interface/interface.d.mts +2 -2
- package/dist/adapter-interface/interface.d.ts +2 -2
- package/dist/adapters/express.d.mts +2 -2
- package/dist/adapters/express.d.ts +2 -2
- package/dist/adapters/express.js +398 -15
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +398 -15
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/http-pdlss.d.mts +3 -3
- package/dist/adapters/http-pdlss.d.ts +3 -3
- package/dist/adapters/http-pdlss.js.map +1 -1
- package/dist/adapters/http-pdlss.mjs.map +1 -1
- package/dist/adapters/mcp.d.mts +56 -36
- package/dist/adapters/mcp.d.ts +56 -36
- package/dist/adapters/mcp.js +220 -3
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +220 -3
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.d.mts +2 -2
- package/dist/adapters/nextjs.d.ts +2 -2
- package/dist/adapters/nextjs.js +433 -18
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +433 -18
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.d.mts +2 -2
- package/dist/adapters/sdk.d.ts +2 -2
- package/dist/adapters/sdk.js +2 -2
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +2 -2
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.d.mts +2 -2
- package/dist/agent/index.d.ts +2 -2
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs.map +1 -1
- package/dist/bin/astrasync-claude-hook.js +13 -13
- package/dist/bin/astrasync-codex-hook.js +13 -13
- package/dist/bin/astrasync-guard.js +100 -13
- package/dist/bin/astrasync.js +168 -27
- package/dist/browser/background.js +13 -13
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +13 -13
- package/dist/browser/background.mjs.map +1 -1
- package/dist/browser/browser-adapter.d.mts +2 -2
- package/dist/browser/browser-adapter.d.ts +2 -2
- package/dist/claude-code/claude-code-adapter.d.mts +2 -2
- package/dist/claude-code/claude-code-adapter.d.ts +2 -2
- package/dist/cli/index.d.mts +2 -2
- package/dist/cli/index.d.ts +2 -2
- package/dist/codex/index.d.mts +3 -3
- package/dist/codex/index.d.ts +3 -3
- package/dist/codex/index.js +24 -13
- package/dist/codex/index.js.map +1 -1
- package/dist/codex/index.mjs +24 -13
- package/dist/codex/index.mjs.map +1 -1
- package/dist/cursor/cursor-adapter.d.mts +2 -2
- package/dist/cursor/cursor-adapter.d.ts +2 -2
- package/dist/cursor/extension.d.mts +2 -2
- package/dist/cursor/extension.d.ts +2 -2
- package/dist/cursor/extension.js +13 -13
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +13 -13
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/edge-config.d.mts +22 -7
- package/dist/edge-config.d.ts +22 -7
- package/dist/edge-config.js.map +1 -1
- package/dist/edge-config.mjs.map +1 -1
- package/dist/edge-core/index.d.mts +425 -0
- package/dist/edge-core/index.d.ts +425 -0
- package/dist/edge-core/index.js +1482 -0
- package/dist/edge-core/index.js.map +1 -0
- package/dist/edge-core/index.mjs +1437 -0
- package/dist/edge-core/index.mjs.map +1 -0
- package/dist/{express-BZajRs4i.d.mts → express-BVd1_3FE.d.ts} +9 -7
- package/dist/{express-CjCUB1k7.d.ts → express-D_4hTn5Z.d.mts} +9 -7
- package/dist/gateway/gateway.d.mts +2 -2
- package/dist/gateway/gateway.d.ts +2 -2
- package/dist/gateway/gateway.js +13 -13
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +13 -13
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/git-trigger/git-hooks.d.mts +2 -2
- package/dist/git-trigger/git-hooks.d.ts +2 -2
- package/dist/{index-adgKhujR.d.ts → index-B0YHu_SP.d.ts} +30 -27
- package/dist/{index-B0cyMZDL.d.mts → index-BPEBlOsE.d.mts} +30 -27
- package/dist/{index-BRYteOqO.d.mts → index-DQb5-_1X.d.mts} +1 -1
- package/dist/{index-BZQdVqNw.d.ts → index-T1aBoUcc.d.ts} +1 -1
- package/dist/index.d.mts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.js +477 -265
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +474 -265
- package/dist/index.mjs.map +1 -1
- package/dist/local-evaluator/evaluator.d.mts +2 -2
- package/dist/local-evaluator/evaluator.d.ts +2 -2
- package/dist/metadata-capture.d.mts +63 -4
- package/dist/metadata-capture.d.ts +63 -4
- package/dist/metadata-capture.js +67 -0
- package/dist/metadata-capture.js.map +1 -1
- package/dist/metadata-capture.mjs +64 -0
- package/dist/metadata-capture.mjs.map +1 -1
- package/dist/{nextjs-DeUTnOBd.d.mts → nextjs-WyeVr2Kp.d.mts} +3 -3
- package/dist/{nextjs-D_iFf5k-.d.ts → nextjs-w7RTbP1P.d.ts} +3 -3
- package/dist/platform-signatures.d.mts +5 -6
- package/dist/platform-signatures.d.ts +5 -6
- package/dist/platform-signatures.js.map +1 -1
- package/dist/platform-signatures.mjs.map +1 -1
- package/dist/registration/index.d.mts +10 -11
- package/dist/registration/index.d.ts +10 -11
- package/dist/registration/index.js.map +1 -1
- package/dist/registration/index.mjs.map +1 -1
- package/dist/{sdk-BM3mwEAq.d.ts → sdk-CbTNIkAa.d.mts} +4 -4
- package/dist/{sdk-_il1Q41f.d.mts → sdk-QeX0Z8Ho.d.ts} +4 -4
- package/dist/transport/index.d.mts +2 -2
- package/dist/transport/index.d.ts +2 -2
- package/dist/transport/index.js.map +1 -1
- package/dist/transport/index.mjs.map +1 -1
- package/dist/{types-CHKCgDFC.d.ts → types-BLUx92FJ.d.ts} +1 -1
- package/dist/{types-DfnP7JiM.d.mts → types-DqfPU5Bl.d.mts} +1 -1
- package/dist/{types-BcDf9Kk0.d.mts → types-r850cOt0.d.mts} +106 -88
- package/dist/{types-fTQD448H.d.ts → types-sMxBT-nM.d.ts} +106 -88
- package/dist/ui/index.d.mts +11 -7
- package/dist/ui/index.d.ts +11 -7
- package/dist/ui/index.js +13 -9
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/index.mjs +10 -8
- package/dist/ui/index.mjs.map +1 -1
- package/dist/verify.d.mts +8 -7
- package/dist/verify.d.ts +8 -7
- package/dist/verify.js +1 -1
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +1 -1
- package/dist/verify.mjs.map +1 -1
- package/package.json +8 -2
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
import { EdgeMode, EdgeVerificationDepth, EdgeConfig } from '../edge-config.mjs';
|
|
2
|
+
import { PlatformFingerprint } from '../platform-signatures.mjs';
|
|
3
|
+
import { f as CommerceArtifactsPayload, w as VerificationRequest } from '../types-r850cOt0.mjs';
|
|
4
|
+
import { verify } from '../verify.mjs';
|
|
5
|
+
import { ObservedMetadata } from '../metadata-capture.mjs';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Trusted Agent Gateway edge core — shared types.
|
|
9
|
+
*
|
|
10
|
+
* The edge core is the platform-neutral heart of the AstraSync edge
|
|
11
|
+
* adapters (Lambda@Edge/CloudFront, Cloudflare Workers, Vercel Edge,
|
|
12
|
+
* Fastly Compute). It classifies inbound traffic into visibility tiers,
|
|
13
|
+
* applies the dashboard-configured EdgeConfig (mode/depth/path rules),
|
|
14
|
+
* forwards raw commerce artifacts to verify-access (which does ALL
|
|
15
|
+
* cryptographic verification server-side), and — only in enforce mode —
|
|
16
|
+
* turns decisions into responses. In observe mode it NEVER blocks and
|
|
17
|
+
* NEVER mutates responses.
|
|
18
|
+
*
|
|
19
|
+
* Platform packages implement {@link PlatformIo}: they normalize their
|
|
20
|
+
* native request shape into a {@link NormalizedRequest}, run the core, and
|
|
21
|
+
* apply the returned {@link OutcomeApplication} back onto their native
|
|
22
|
+
* request/response primitives.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The platform-neutral view of one inbound HTTP request.
|
|
27
|
+
*
|
|
28
|
+
* Invariants platform normalizers must uphold:
|
|
29
|
+
* - `headers` keys are LOWERCASED header names; multi-valued headers are
|
|
30
|
+
* joined with `", "` (standard HTTP field-value concatenation).
|
|
31
|
+
* - `uri` is the path only (no query string); `querystring` has no
|
|
32
|
+
* leading `?` and is empty when absent.
|
|
33
|
+
* - `bodyText` is the decoded UTF-8 body when one was available to the
|
|
34
|
+
* platform, with `bodyTruncated: true` when the platform capped it.
|
|
35
|
+
* - `connection` carries transport-layer signals only the platform can
|
|
36
|
+
* see (ip, country, asn, tlsVersion, httpVersion, city, …). Absent
|
|
37
|
+
* values are simply omitted — a partial block is fine.
|
|
38
|
+
*/
|
|
39
|
+
interface NormalizedRequest {
|
|
40
|
+
method: string;
|
|
41
|
+
uri: string;
|
|
42
|
+
querystring: string;
|
|
43
|
+
headers: Record<string, string>;
|
|
44
|
+
bodyText?: string;
|
|
45
|
+
bodyTruncated?: boolean;
|
|
46
|
+
/** Client IP as the platform reports it (used for telemetry only). */
|
|
47
|
+
clientIp?: string;
|
|
48
|
+
/** Connection-layer metadata (country, asn, tlsVersion, …). */
|
|
49
|
+
connection?: Record<string, string>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Contract between the core and a platform package: the platform converts
|
|
53
|
+
* its native request into a {@link NormalizedRequest} and applies the
|
|
54
|
+
* core's abstract {@link OutcomeApplication} back onto its native shapes.
|
|
55
|
+
*/
|
|
56
|
+
interface PlatformIo<NativeRequest = unknown, NativeResult = unknown> {
|
|
57
|
+
normalize(request: NativeRequest): NormalizedRequest | Promise<NormalizedRequest>;
|
|
58
|
+
apply(request: NativeRequest, application: OutcomeApplication): NativeResult;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* What the platform must do with the request after evaluation.
|
|
62
|
+
*
|
|
63
|
+
* - `pass`: forward the request to the origin. First strip every inbound
|
|
64
|
+
* header matching one of `stripHeaderPrefixes` (case-insensitive; a
|
|
65
|
+
* caller must never be able to smuggle trust headers past the origin),
|
|
66
|
+
* then set each header in `injectHeaders` (overwriting prior values).
|
|
67
|
+
* Both maps are empty for traffic the gateway leaves untouched.
|
|
68
|
+
* - `respond`: short-circuit with an HTTP response. `bodyJson` must be
|
|
69
|
+
* serialized as JSON and served with `Content-Type: application/json`;
|
|
70
|
+
* `headers` are additional response headers (e.g. `Retry-After`).
|
|
71
|
+
*/
|
|
72
|
+
type OutcomeApplication = {
|
|
73
|
+
action: 'pass';
|
|
74
|
+
injectHeaders: Record<string, string>;
|
|
75
|
+
stripHeaderPrefixes: string[];
|
|
76
|
+
} | {
|
|
77
|
+
action: 'respond';
|
|
78
|
+
status: number;
|
|
79
|
+
headers: Record<string, string>;
|
|
80
|
+
bodyJson: unknown;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* The visibility tiers of the live agent-traffic feed, plus `human`
|
|
84
|
+
* (which the gateway touches as little as possible) and `skipped`
|
|
85
|
+
* (path-filtered — static assets etc.).
|
|
86
|
+
*/
|
|
87
|
+
type TrafficTier = 'verified' | 'identified' | 'anonymous-bot' | 'human' | 'skipped';
|
|
88
|
+
interface Classification {
|
|
89
|
+
tier: TrafficTier;
|
|
90
|
+
/** Detected transport/credential protocol (tier `identified`/`verified`). */
|
|
91
|
+
protocol?: string;
|
|
92
|
+
/** Platform UA fingerprint when one matched. */
|
|
93
|
+
fingerprint?: PlatformFingerprint;
|
|
94
|
+
/** Raw commerce artifacts detected on the wire, ready to forward. */
|
|
95
|
+
artifacts?: CommerceArtifactsPayload;
|
|
96
|
+
/** Light, crypto-free detection detail for the beacon (kid namespace etc). */
|
|
97
|
+
evidence?: Record<string, unknown>;
|
|
98
|
+
}
|
|
99
|
+
/** What the gateway decided (observe mode records it; enforce mode acts on it). */
|
|
100
|
+
type EdgeDecision = 'allow' | 'deny' | 'manual_review';
|
|
101
|
+
interface TierOutcome {
|
|
102
|
+
tier: TrafficTier;
|
|
103
|
+
decision: EdgeDecision;
|
|
104
|
+
/** Why (deny/step-up reasons, or 'observe-passthrough'). */
|
|
105
|
+
reasons: string[];
|
|
106
|
+
/**
|
|
107
|
+
* The property's own API key was rejected by verify-access (a merchant
|
|
108
|
+
* misconfiguration — neither an agent deny nor an infra failure). The
|
|
109
|
+
* outcome is `allow` (fail-open in BOTH modes — agents must not be
|
|
110
|
+
* blocked by the property's dead key) but the flag stamps
|
|
111
|
+
* `X-AstraSync-Observed-Decision: misconfig` for origin-side logs; the
|
|
112
|
+
* owner is alerted server-side on every rejected call.
|
|
113
|
+
*/
|
|
114
|
+
misconfig?: boolean;
|
|
115
|
+
/** Trust-attestation header material when a verify-access call succeeded. */
|
|
116
|
+
asat?: {
|
|
117
|
+
trustScore?: number;
|
|
118
|
+
agentId?: string;
|
|
119
|
+
developerId?: string;
|
|
120
|
+
accessLevel?: string;
|
|
121
|
+
};
|
|
122
|
+
sessionId?: string;
|
|
123
|
+
protocol?: string;
|
|
124
|
+
guidance?: {
|
|
125
|
+
message?: string;
|
|
126
|
+
registrationUrl?: string;
|
|
127
|
+
documentationUrl?: string;
|
|
128
|
+
};
|
|
129
|
+
stepUp?: {
|
|
130
|
+
pollUrl?: string;
|
|
131
|
+
expiresAt?: string;
|
|
132
|
+
};
|
|
133
|
+
correlationId?: string;
|
|
134
|
+
}
|
|
135
|
+
/** Per-request effective policy after path-rule resolution. */
|
|
136
|
+
interface EffectivePolicy {
|
|
137
|
+
mode: EdgeMode;
|
|
138
|
+
depth: EdgeVerificationDepth;
|
|
139
|
+
skip: boolean;
|
|
140
|
+
}
|
|
141
|
+
/** Structured log sink shared by the core and the platform adapters. */
|
|
142
|
+
type EdgeLogger = (level: 'info' | 'warn' | 'error', message: string, data?: Record<string, unknown>) => void;
|
|
143
|
+
/**
|
|
144
|
+
* Options the edge core needs to evaluate a request. Platform adapter
|
|
145
|
+
* option types extend this with their platform-specific configuration
|
|
146
|
+
* (secret fetching, origin backends, …).
|
|
147
|
+
*/
|
|
148
|
+
interface EdgeCoreOptions {
|
|
149
|
+
/** AstraSync API base, e.g. `https://astrasync.ai/api`. */
|
|
150
|
+
apiBaseUrl: string;
|
|
151
|
+
/** The protected property's ASTRAE endpoint id. */
|
|
152
|
+
counterpartyId: string;
|
|
153
|
+
/** Canonical public URL of the protected property, e.g. `https://astrasync.shop`. */
|
|
154
|
+
counterpartyUrl: string;
|
|
155
|
+
/** Time budgets (ms). */
|
|
156
|
+
budgets?: {
|
|
157
|
+
/** Fire-and-forget beacon budget. Default 300. */
|
|
158
|
+
beaconMs?: number;
|
|
159
|
+
/** verify-access budget in observe mode. Default 1500. */
|
|
160
|
+
verifyObserveMs?: number;
|
|
161
|
+
/** verify-access budget in enforce mode. Default 3000. */
|
|
162
|
+
verifyEnforceMs?: number;
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* Background-work scheduler for runtimes that support it (e.g.
|
|
166
|
+
* `ctx.waitUntil` on Cloudflare Workers / Fastly Compute / Vercel Edge).
|
|
167
|
+
* When provided, telemetry beacons are scheduled through it instead of
|
|
168
|
+
* being awaited inline, removing them from the request's latency path
|
|
169
|
+
* entirely. Platforms without one (Lambda@Edge) leave this unset and
|
|
170
|
+
* beacons are awaited under their time budget.
|
|
171
|
+
*/
|
|
172
|
+
waitUntil?: (promise: Promise<unknown>) => void;
|
|
173
|
+
/** Random source for beacon sampling — injectable for tests. */
|
|
174
|
+
random?: () => number;
|
|
175
|
+
/** Structured log sink. */
|
|
176
|
+
log?: EdgeLogger;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Three-tier traffic classification (verified / identified-but-unregistered
|
|
181
|
+
* / anonymous) plus the two non-tiers the gateway touches as little as
|
|
182
|
+
* possible: `human` (zero network calls, zero logging) and `skipped`
|
|
183
|
+
* (static assets / excluded paths).
|
|
184
|
+
*
|
|
185
|
+
* Cheapest checks first — the human path must add microseconds, not
|
|
186
|
+
* milliseconds. Platform signatures are shared with the backend so the
|
|
187
|
+
* edge and verify-access's anonymous handler classify identically.
|
|
188
|
+
*/
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Resolve the effective mode/depth for a path from the EdgeConfig — ordered
|
|
192
|
+
* first-match-wins rules with case-insensitive globs; no match falls through
|
|
193
|
+
* to the config's top-level defaults. Static extensions are always skipped
|
|
194
|
+
* regardless of rules (a rule can only skip MORE, never un-skip an asset).
|
|
195
|
+
*/
|
|
196
|
+
declare function resolvePolicy(config: EdgeConfig, path: string): EffectivePolicy;
|
|
197
|
+
/**
|
|
198
|
+
* Classify one request. Order (cheapest sufficient evidence wins):
|
|
199
|
+
* 1. X-Astra-* credentials → `verified` candidate
|
|
200
|
+
* 2. commerce-protocol credentials on the wire → `identified`
|
|
201
|
+
* 3. platform UA fingerprint (Claude/ChatGPT/Gemini/…) → `identified`
|
|
202
|
+
* 4. bot-shaped UA / headerless non-browser → `anonymous-bot`
|
|
203
|
+
* 5. everything browser-shaped → `human`
|
|
204
|
+
*
|
|
205
|
+
* `depth: 'classify'` skips step 2 (no body inspection, no header sniffing
|
|
206
|
+
* beyond UA) — that is the zero-friction setting.
|
|
207
|
+
*/
|
|
208
|
+
declare function classify(req: NormalizedRequest, host: string, depth: 'classify' | 'authenticate' | 'authorize'): Classification;
|
|
209
|
+
/** Exported for tests. */
|
|
210
|
+
declare const _patterns: {
|
|
211
|
+
STATIC_EXTENSIONS: RegExp;
|
|
212
|
+
BOT_UA_PATTERN: RegExp;
|
|
213
|
+
BROWSER_UA_PATTERN: RegExp;
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Crypto-free commerce-protocol detection.
|
|
218
|
+
*
|
|
219
|
+
* The edge only SNIFFS — header shapes, compact-JWT patterns, body field
|
|
220
|
+
* names — and packages what it saw as raw `CommerceArtifactsPayload` for
|
|
221
|
+
* verify-access, whose server-side pipeline does the authoritative parsing
|
|
222
|
+
* and cryptographic verification. Nothing here imports jose/sd-jwt/
|
|
223
|
+
* signature libraries: detection must stay cheap enough to run on every
|
|
224
|
+
* non-human request, and verification must happen exactly once, in the
|
|
225
|
+
* canonical sink, where it is recorded.
|
|
226
|
+
*/
|
|
227
|
+
|
|
228
|
+
interface DetectedCommerce {
|
|
229
|
+
/** Detection-order label: rfc9421-agent-pay | rfc9421-tap | rfc9421-web-bot-auth | vi-sd-jwt | ap2 | acp | ucp | mpp | x402 */
|
|
230
|
+
protocol: string;
|
|
231
|
+
artifacts: CommerceArtifactsPayload;
|
|
232
|
+
/** Light detection detail for beacons/audit — never secrets or full credentials. */
|
|
233
|
+
evidence: Record<string, unknown>;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Detection order (after the native X-Astra check, which classify owns):
|
|
237
|
+
* SD-JWT/VI → RFC 9421 (Agent Pay / TAP / Web Bot Auth by kid namespace or
|
|
238
|
+
* Signature-Agent) → ACP HMAC → UCP session → AP2 body triple → MPP → x402.
|
|
239
|
+
* Returns undefined when nothing commerce-shaped is on the wire.
|
|
240
|
+
*
|
|
241
|
+
* When the platform truncated the body (`bodyTruncated`), body-bound
|
|
242
|
+
* artifacts still forward what arrived but carry a `bodyTruncated`
|
|
243
|
+
* evidence flag — the backend downgrades those signatures rather than
|
|
244
|
+
* hard-failing.
|
|
245
|
+
*/
|
|
246
|
+
declare function detectCommerce(req: NormalizedRequest, host: string): DetectedCommerce | undefined;
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* The platform-neutral evaluation pipeline for one request:
|
|
250
|
+
*
|
|
251
|
+
* path policy → classify → tier pipeline → outcome application
|
|
252
|
+
*
|
|
253
|
+
* Platform adapters own everything around this: config/secret loading,
|
|
254
|
+
* request normalization, and applying the returned application onto their
|
|
255
|
+
* native request/response shapes. `evaluateEdgeRequest` NEVER throws — any
|
|
256
|
+
* internal failure resolves to an untouched pass (the gateway must never
|
|
257
|
+
* take the site down).
|
|
258
|
+
*/
|
|
259
|
+
|
|
260
|
+
interface EdgeEvaluation {
|
|
261
|
+
application: OutcomeApplication;
|
|
262
|
+
policy: EffectivePolicy;
|
|
263
|
+
/** Absent when the path was skipped before classification. */
|
|
264
|
+
classification?: Classification;
|
|
265
|
+
/** Absent for skipped paths and human traffic (no pipeline run). */
|
|
266
|
+
outcome?: TierOutcome;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Evaluate one normalized request against the effective EdgeConfig.
|
|
270
|
+
*
|
|
271
|
+
* - Skipped paths (static assets / skip rules): untouched, zero work.
|
|
272
|
+
* - Humans: get out of the way. No calls, no logs, no header changes.
|
|
273
|
+
* - Everything else runs the tier pipeline and yields an application the
|
|
274
|
+
* platform must execute (pass with header hygiene, or an enforce-mode
|
|
275
|
+
* response).
|
|
276
|
+
*/
|
|
277
|
+
declare function evaluateEdgeRequest(options: EdgeCoreOptions, req: NormalizedRequest, config: EdgeConfig, apiKey: string | undefined): Promise<EdgeEvaluation>;
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Decision → abstract outcome-application wiring. Executed in BOTH modes
|
|
281
|
+
* so observe mode records exactly what enforce mode would have done — but
|
|
282
|
+
* only enforce mode is allowed to emit anything other than a pass.
|
|
283
|
+
*/
|
|
284
|
+
|
|
285
|
+
/** Trust-attestation headers injected on allowed requests. */
|
|
286
|
+
declare const ASAT_HEADERS: {
|
|
287
|
+
readonly trustScore: "X-AstraSync-Trust-Score";
|
|
288
|
+
readonly agentId: "X-AstraSync-Agent-Id";
|
|
289
|
+
readonly developerId: "X-AstraSync-Developer-Id";
|
|
290
|
+
readonly permissions: "X-AstraSync-Permissions";
|
|
291
|
+
readonly observedDecision: "X-AstraSync-Observed-Decision";
|
|
292
|
+
};
|
|
293
|
+
/**
|
|
294
|
+
* A pass that leaves the request completely untouched — used for skipped
|
|
295
|
+
* paths and human traffic, which the gateway must not modify at all.
|
|
296
|
+
*/
|
|
297
|
+
declare function passUntouched(): OutcomeApplication;
|
|
298
|
+
/**
|
|
299
|
+
* Turn a tier outcome into the abstract application the platform executes.
|
|
300
|
+
* Every evaluated pass strips inbound spoofed `x-astrasync-*` headers
|
|
301
|
+
* (both modes — trust headers must only ever originate at the gateway).
|
|
302
|
+
*
|
|
303
|
+
* Observe mode: always a pass — header hygiene plus an
|
|
304
|
+
* `X-AstraSync-Observed-Decision` stamp for origin-side log correlation.
|
|
305
|
+
*
|
|
306
|
+
* Enforce mode: ALLOW → pass with trust-attestation headers; DENY → 403
|
|
307
|
+
* machine-readable body; MANUAL_REVIEW → 202 with step-up poll info.
|
|
308
|
+
*/
|
|
309
|
+
declare function applyOutcome(options: {
|
|
310
|
+
apiBaseUrl: string;
|
|
311
|
+
}, outcome: TierOutcome, policy: EffectivePolicy): OutcomeApplication;
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Time-budgeted event emission.
|
|
315
|
+
*
|
|
316
|
+
* Some edge runtimes (Lambda@Edge) have no background-work scheduler —
|
|
317
|
+
* anything not awaited before the handler returns may never run. So every
|
|
318
|
+
* telemetry call is awaited under an explicit budget and DROPPED on
|
|
319
|
+
* timeout: latency to the customer's traffic is bounded, and a slow
|
|
320
|
+
* AstraSync API costs telemetry, never page loads. Runtimes that provide
|
|
321
|
+
* `waitUntil` (Cloudflare Workers, Vercel Edge, Fastly Compute) can pass
|
|
322
|
+
* it via {@link EdgeCoreOptions.waitUntil} to take beacons off the latency
|
|
323
|
+
* path entirely.
|
|
324
|
+
*/
|
|
325
|
+
|
|
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
|
+
/**
|
|
329
|
+
* Emit an unregistered-attempt beacon for `identified` (non-crypto depths)
|
|
330
|
+
* and sampled `anonymous-bot` traffic. Unauthenticated by design; the
|
|
331
|
+
* backend fingerprints the UA and find-or-provisions platform agents
|
|
332
|
+
* server-side.
|
|
333
|
+
*/
|
|
334
|
+
declare function emitBeacon(options: EdgeCoreOptions, req: NormalizedRequest, classification: Classification, budgetMs: number): Promise<void>;
|
|
335
|
+
/** Deterministic-in-tests sampling gate. */
|
|
336
|
+
declare function sampled(rate: number, random?: () => number): boolean;
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Protocol-specific machine-readable messaging for enforce-mode responses.
|
|
340
|
+
* Agents (not humans) consume these bodies: stable error codes, the
|
|
341
|
+
* failure list, and registration guidance with real URLs.
|
|
342
|
+
*/
|
|
343
|
+
|
|
344
|
+
interface DenyBody {
|
|
345
|
+
success: false;
|
|
346
|
+
error: {
|
|
347
|
+
code: 'UNAUTHORIZED' | 'INSUFFICIENT_ACCESS';
|
|
348
|
+
message: string;
|
|
349
|
+
protocol?: string;
|
|
350
|
+
failures: string[];
|
|
351
|
+
correlationId?: string;
|
|
352
|
+
guidance: {
|
|
353
|
+
message?: string;
|
|
354
|
+
registrationUrl?: string;
|
|
355
|
+
documentationUrl?: string;
|
|
356
|
+
};
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
declare function buildDenyBody(outcome: TierOutcome, apiBaseUrl: string): DenyBody;
|
|
360
|
+
interface ManualReviewBody {
|
|
361
|
+
success: false;
|
|
362
|
+
status: 'manual_review';
|
|
363
|
+
message: string;
|
|
364
|
+
stepUpApproval?: {
|
|
365
|
+
pollUrl?: string;
|
|
366
|
+
expiresAt?: string;
|
|
367
|
+
};
|
|
368
|
+
correlationId?: string;
|
|
369
|
+
}
|
|
370
|
+
declare function buildManualReviewBody(outcome: TierOutcome): ManualReviewBody;
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Depth-controlled verification per tier. The edge never verifies
|
|
374
|
+
* credentials itself — it forwards what it detected to verify-access, the
|
|
375
|
+
* canonical sole verification sink (the backend runs the commerce
|
|
376
|
+
* pipeline, records events, provisions unregistered platform agents,
|
|
377
|
+
* persists sessions). What the depth setting controls is how much the edge
|
|
378
|
+
* LOOKS and how much it FORWARDS:
|
|
379
|
+
*
|
|
380
|
+
* classify — what is it? UA tiers only. Zero verify-access calls;
|
|
381
|
+
* beacons only.
|
|
382
|
+
* authenticate — who is it? + protocol detection. X-Astra agents get a
|
|
383
|
+
* verify-access identity check; commerce/platform traffic
|
|
384
|
+
* is beaconed with protocol + evidence (no signature
|
|
385
|
+
* verification anywhere).
|
|
386
|
+
* authorize — are they allowed? + artifact forwarding. X-Astra verify
|
|
387
|
+
* calls carry commerceArtifacts; identified traffic gets an
|
|
388
|
+
* anonymous verify-access call with artifacts +
|
|
389
|
+
* callerMetadata so the backend cryptographically proves
|
|
390
|
+
* and policy-evaluates once.
|
|
391
|
+
*/
|
|
392
|
+
|
|
393
|
+
declare function buildVerificationRequest(options: EdgeCoreOptions, req: NormalizedRequest, classification: Classification, includeArtifacts: boolean): VerificationRequest;
|
|
394
|
+
declare function outcomeFromVerifyResult(classification: Classification, result: Awaited<ReturnType<typeof verify>>): TierOutcome;
|
|
395
|
+
/**
|
|
396
|
+
* Run the tier-appropriate verification/telemetry for one classified
|
|
397
|
+
* request. NEVER throws; on any failure returns an `allow` outcome with the
|
|
398
|
+
* failure recorded in `reasons` (infra failures fail open — a presented
|
|
399
|
+
* credential the BACKEND rejected is a deny, but an unreachable backend is
|
|
400
|
+
* not a rejection).
|
|
401
|
+
*/
|
|
402
|
+
declare function runTier(options: EdgeCoreOptions, req: NormalizedRequest, classification: Classification, policy: EffectivePolicy, apiKey: string | undefined, sampling: {
|
|
403
|
+
anonymousBeaconRate: number;
|
|
404
|
+
}): Promise<TierOutcome>;
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Helpers over {@link NormalizedRequest} — header access, URL
|
|
408
|
+
* reconstruction, and the full sanitized metadata capture.
|
|
409
|
+
*/
|
|
410
|
+
|
|
411
|
+
/** Value of a header (name matched case-insensitively), or undefined. */
|
|
412
|
+
declare function headerValue(req: NormalizedRequest, name: string): string | undefined;
|
|
413
|
+
/** Full request URL as the origin will see it (scheme fixed to https). */
|
|
414
|
+
declare function requestUrl(req: NormalizedRequest, host: string): string;
|
|
415
|
+
/**
|
|
416
|
+
* The FULL sanitized metadata capture for one request: every inbound
|
|
417
|
+
* header (secrets stripped, credential headers reduced to a safe format
|
|
418
|
+
* prefix) plus the connection-layer block the platform collected. The
|
|
419
|
+
* edge is the richest capture point — the headers are already in memory —
|
|
420
|
+
* and this is pure string work, so it adds no page latency. Forwarded on
|
|
421
|
+
* both the verify-access call and the telemetry beacon.
|
|
422
|
+
*/
|
|
423
|
+
declare function buildObservedMetadata(req: NormalizedRequest): ObservedMetadata;
|
|
424
|
+
|
|
425
|
+
export { ASAT_HEADERS, type Classification, type DenyBody, type DetectedCommerce, type EdgeCoreOptions, type EdgeDecision, type EdgeEvaluation, type EdgeLogger, type EffectivePolicy, type ManualReviewBody, type NormalizedRequest, type OutcomeApplication, type PlatformIo, type TierOutcome, type TrafficTier, _patterns, applyOutcome, buildDenyBody, buildManualReviewBody, buildObservedMetadata, buildVerificationRequest, classify, detectCommerce, emitBeacon, evaluateEdgeRequest, headerValue, outcomeFromVerifyResult, passUntouched, requestUrl, resolvePolicy, runTier, sampled, withBudget };
|