@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.
Files changed (134) hide show
  1. package/README.md +106 -29
  2. package/dist/adapter-interface/interface.d.mts +2 -2
  3. package/dist/adapter-interface/interface.d.ts +2 -2
  4. package/dist/adapters/express.d.mts +2 -2
  5. package/dist/adapters/express.d.ts +2 -2
  6. package/dist/adapters/express.js +398 -15
  7. package/dist/adapters/express.js.map +1 -1
  8. package/dist/adapters/express.mjs +398 -15
  9. package/dist/adapters/express.mjs.map +1 -1
  10. package/dist/adapters/http-pdlss.d.mts +3 -3
  11. package/dist/adapters/http-pdlss.d.ts +3 -3
  12. package/dist/adapters/http-pdlss.js.map +1 -1
  13. package/dist/adapters/http-pdlss.mjs.map +1 -1
  14. package/dist/adapters/mcp.d.mts +56 -36
  15. package/dist/adapters/mcp.d.ts +56 -36
  16. package/dist/adapters/mcp.js +220 -3
  17. package/dist/adapters/mcp.js.map +1 -1
  18. package/dist/adapters/mcp.mjs +220 -3
  19. package/dist/adapters/mcp.mjs.map +1 -1
  20. package/dist/adapters/nextjs.d.mts +2 -2
  21. package/dist/adapters/nextjs.d.ts +2 -2
  22. package/dist/adapters/nextjs.js +433 -18
  23. package/dist/adapters/nextjs.js.map +1 -1
  24. package/dist/adapters/nextjs.mjs +433 -18
  25. package/dist/adapters/nextjs.mjs.map +1 -1
  26. package/dist/adapters/sdk.d.mts +2 -2
  27. package/dist/adapters/sdk.d.ts +2 -2
  28. package/dist/adapters/sdk.js +2 -2
  29. package/dist/adapters/sdk.js.map +1 -1
  30. package/dist/adapters/sdk.mjs +2 -2
  31. package/dist/adapters/sdk.mjs.map +1 -1
  32. package/dist/agent/index.d.mts +2 -2
  33. package/dist/agent/index.d.ts +2 -2
  34. package/dist/agent/index.js.map +1 -1
  35. package/dist/agent/index.mjs.map +1 -1
  36. package/dist/bin/astrasync-claude-hook.js +13 -13
  37. package/dist/bin/astrasync-codex-hook.js +13 -13
  38. package/dist/bin/astrasync-guard.js +100 -13
  39. package/dist/bin/astrasync.js +168 -27
  40. package/dist/browser/background.js +13 -13
  41. package/dist/browser/background.js.map +1 -1
  42. package/dist/browser/background.mjs +13 -13
  43. package/dist/browser/background.mjs.map +1 -1
  44. package/dist/browser/browser-adapter.d.mts +2 -2
  45. package/dist/browser/browser-adapter.d.ts +2 -2
  46. package/dist/claude-code/claude-code-adapter.d.mts +2 -2
  47. package/dist/claude-code/claude-code-adapter.d.ts +2 -2
  48. package/dist/cli/index.d.mts +2 -2
  49. package/dist/cli/index.d.ts +2 -2
  50. package/dist/codex/index.d.mts +3 -3
  51. package/dist/codex/index.d.ts +3 -3
  52. package/dist/codex/index.js +24 -13
  53. package/dist/codex/index.js.map +1 -1
  54. package/dist/codex/index.mjs +24 -13
  55. package/dist/codex/index.mjs.map +1 -1
  56. package/dist/cursor/cursor-adapter.d.mts +2 -2
  57. package/dist/cursor/cursor-adapter.d.ts +2 -2
  58. package/dist/cursor/extension.d.mts +2 -2
  59. package/dist/cursor/extension.d.ts +2 -2
  60. package/dist/cursor/extension.js +13 -13
  61. package/dist/cursor/extension.js.map +1 -1
  62. package/dist/cursor/extension.mjs +13 -13
  63. package/dist/cursor/extension.mjs.map +1 -1
  64. package/dist/edge-config.d.mts +22 -7
  65. package/dist/edge-config.d.ts +22 -7
  66. package/dist/edge-config.js.map +1 -1
  67. package/dist/edge-config.mjs.map +1 -1
  68. package/dist/edge-core/index.d.mts +425 -0
  69. package/dist/edge-core/index.d.ts +425 -0
  70. package/dist/edge-core/index.js +1482 -0
  71. package/dist/edge-core/index.js.map +1 -0
  72. package/dist/edge-core/index.mjs +1437 -0
  73. package/dist/edge-core/index.mjs.map +1 -0
  74. package/dist/{express-BZajRs4i.d.mts → express-BVd1_3FE.d.ts} +9 -7
  75. package/dist/{express-CjCUB1k7.d.ts → express-D_4hTn5Z.d.mts} +9 -7
  76. package/dist/gateway/gateway.d.mts +2 -2
  77. package/dist/gateway/gateway.d.ts +2 -2
  78. package/dist/gateway/gateway.js +13 -13
  79. package/dist/gateway/gateway.js.map +1 -1
  80. package/dist/gateway/gateway.mjs +13 -13
  81. package/dist/gateway/gateway.mjs.map +1 -1
  82. package/dist/git-trigger/git-hooks.d.mts +2 -2
  83. package/dist/git-trigger/git-hooks.d.ts +2 -2
  84. package/dist/{index-adgKhujR.d.ts → index-B0YHu_SP.d.ts} +30 -27
  85. package/dist/{index-B0cyMZDL.d.mts → index-BPEBlOsE.d.mts} +30 -27
  86. package/dist/{index-BRYteOqO.d.mts → index-DQb5-_1X.d.mts} +1 -1
  87. package/dist/{index-BZQdVqNw.d.ts → index-T1aBoUcc.d.ts} +1 -1
  88. package/dist/index.d.mts +11 -11
  89. package/dist/index.d.ts +11 -11
  90. package/dist/index.js +477 -265
  91. package/dist/index.js.map +1 -1
  92. package/dist/index.mjs +474 -265
  93. package/dist/index.mjs.map +1 -1
  94. package/dist/local-evaluator/evaluator.d.mts +2 -2
  95. package/dist/local-evaluator/evaluator.d.ts +2 -2
  96. package/dist/metadata-capture.d.mts +63 -4
  97. package/dist/metadata-capture.d.ts +63 -4
  98. package/dist/metadata-capture.js +67 -0
  99. package/dist/metadata-capture.js.map +1 -1
  100. package/dist/metadata-capture.mjs +64 -0
  101. package/dist/metadata-capture.mjs.map +1 -1
  102. package/dist/{nextjs-DeUTnOBd.d.mts → nextjs-WyeVr2Kp.d.mts} +3 -3
  103. package/dist/{nextjs-D_iFf5k-.d.ts → nextjs-w7RTbP1P.d.ts} +3 -3
  104. package/dist/platform-signatures.d.mts +5 -6
  105. package/dist/platform-signatures.d.ts +5 -6
  106. package/dist/platform-signatures.js.map +1 -1
  107. package/dist/platform-signatures.mjs.map +1 -1
  108. package/dist/registration/index.d.mts +10 -11
  109. package/dist/registration/index.d.ts +10 -11
  110. package/dist/registration/index.js.map +1 -1
  111. package/dist/registration/index.mjs.map +1 -1
  112. package/dist/{sdk-BM3mwEAq.d.ts → sdk-CbTNIkAa.d.mts} +4 -4
  113. package/dist/{sdk-_il1Q41f.d.mts → sdk-QeX0Z8Ho.d.ts} +4 -4
  114. package/dist/transport/index.d.mts +2 -2
  115. package/dist/transport/index.d.ts +2 -2
  116. package/dist/transport/index.js.map +1 -1
  117. package/dist/transport/index.mjs.map +1 -1
  118. package/dist/{types-CHKCgDFC.d.ts → types-BLUx92FJ.d.ts} +1 -1
  119. package/dist/{types-DfnP7JiM.d.mts → types-DqfPU5Bl.d.mts} +1 -1
  120. package/dist/{types-BcDf9Kk0.d.mts → types-r850cOt0.d.mts} +106 -88
  121. package/dist/{types-fTQD448H.d.ts → types-sMxBT-nM.d.ts} +106 -88
  122. package/dist/ui/index.d.mts +11 -7
  123. package/dist/ui/index.d.ts +11 -7
  124. package/dist/ui/index.js +13 -9
  125. package/dist/ui/index.js.map +1 -1
  126. package/dist/ui/index.mjs +10 -8
  127. package/dist/ui/index.mjs.map +1 -1
  128. package/dist/verify.d.mts +8 -7
  129. package/dist/verify.d.ts +8 -7
  130. package/dist/verify.js +1 -1
  131. package/dist/verify.js.map +1 -1
  132. package/dist/verify.mjs +1 -1
  133. package/dist/verify.mjs.map +1 -1
  134. package/package.json +8 -2
@@ -0,0 +1,425 @@
1
+ import { EdgeMode, EdgeVerificationDepth, EdgeConfig } from '../edge-config.js';
2
+ import { PlatformFingerprint } from '../platform-signatures.js';
3
+ import { f as CommerceArtifactsPayload, w as VerificationRequest } from '../types-sMxBT-nM.js';
4
+ import { verify } from '../verify.js';
5
+ import { ObservedMetadata } from '../metadata-capture.js';
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 };