@belticlabs/agent-risk-sdk 0.1.0 → 0.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/dist/adapter-CF-cUYSA.d.ts +28 -0
- package/dist/ai/index.d.ts +6 -6
- package/dist/ai/index.js +4 -3
- package/dist/{chunk-GCKCAKHA.js → chunk-46QN2KEZ.js} +199 -33
- package/dist/chunk-GSH5APZW.js +39 -0
- package/dist/{chunk-U5Z5Z2BQ.js → chunk-LM4NIYE5.js} +26 -20
- package/dist/{chunk-YVMJ5CZX.js → chunk-SO6HPRJT.js} +10 -23
- package/dist/chunk-U7HM37CB.js +17 -0
- package/dist/client-C-mV_3A0.d.ts +91 -0
- package/dist/index-Bjs3BPPU.d.ts +547 -0
- package/dist/index.d.ts +10 -8
- package/dist/index.js +117 -16
- package/dist/mcp/index.d.ts +6 -5
- package/dist/mcp/index.js +11 -8
- package/dist/middleware-BwAYpBTl.d.ts +15 -0
- package/dist/protocol/index.d.ts +158 -0
- package/dist/protocol/index.js +152 -0
- package/dist/seller/anti-fraud-gateway.d.ts +14 -4
- package/dist/seller/anti-fraud-gateway.js +13 -14
- package/dist/{session-BMNB1N1g.d.ts → session-5TClPLI4.d.ts} +70 -4
- package/dist/verdict-BAahb5po.d.ts +26 -0
- package/dist/x402/express.d.ts +7 -6
- package/dist/x402/express.js +6 -5
- package/dist/x402/hono.d.ts +7 -6
- package/dist/x402/hono.js +6 -5
- package/dist/x402/index.d.ts +95 -19
- package/dist/x402/index.js +83 -32
- package/package.json +5 -1
- package/dist/chunk-5TWO73OD.js +0 -35
- package/dist/client-CVx9LgJC.d.ts +0 -63
- package/dist/middleware-_DSwvNIx.d.ts +0 -40
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { D as Decision } from './index-Bjs3BPPU.js';
|
|
2
|
+
import { x402ResourceServer, x402HTTPResourceServer } from '@x402/core/server';
|
|
3
|
+
import { B as Beltic } from './client-C-mV_3A0.js';
|
|
4
|
+
import { d as SessionBorn, S as Session } from './session-5TClPLI4.js';
|
|
5
|
+
|
|
6
|
+
interface CorrelationContext {
|
|
7
|
+
path: string;
|
|
8
|
+
method: string;
|
|
9
|
+
header: (name: string) => string | undefined;
|
|
10
|
+
}
|
|
11
|
+
interface AttachOptions {
|
|
12
|
+
/** A key the merchant will see again at verify time, for delegated flows (GAP-31). */
|
|
13
|
+
correlate?: ((ctx: CorrelationContext) => string | null) | undefined;
|
|
14
|
+
/** Called with every decision; the default logs nothing. */
|
|
15
|
+
onDecision?: ((d: {
|
|
16
|
+
sessionId: string;
|
|
17
|
+
decision: Decision;
|
|
18
|
+
reasonCodes: string[];
|
|
19
|
+
born: SessionBorn;
|
|
20
|
+
}) => void) | undefined;
|
|
21
|
+
}
|
|
22
|
+
interface AttachedX402 {
|
|
23
|
+
/** Sessions resolved at verify time, keyed by payment digest — for tests and settle hooks. */
|
|
24
|
+
readonly inFlight: ReadonlyMap<string, Session>;
|
|
25
|
+
}
|
|
26
|
+
declare function attachX402(beltic: Beltic, server: x402ResourceServer, http?: x402HTTPResourceServer, opts?: AttachOptions): AttachedX402;
|
|
27
|
+
|
|
28
|
+
export { type AttachOptions as A, type CorrelationContext as C, attachX402 as a, type AttachedX402 as b };
|
package/dist/ai/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { PaymentMomentPayload } from '
|
|
1
|
+
import { P as PaymentMomentPayload } from '../index-Bjs3BPPU.js';
|
|
2
2
|
import { LanguageModelMiddleware, Tool, ToolSet } from 'ai';
|
|
3
|
-
import { S as Session } from '../session-
|
|
4
|
-
import '
|
|
3
|
+
import { S as Session } from '../session-5TClPLI4.js';
|
|
4
|
+
import 'zod';
|
|
5
5
|
|
|
6
6
|
interface PaymentMoments {
|
|
7
7
|
requested?: PaymentMomentPayload;
|
|
@@ -12,8 +12,8 @@ interface WrapToolOptions<I = unknown, O = unknown> {
|
|
|
12
12
|
/** When the tool performs a purchase, map its input/output to the payment moments it produced. */
|
|
13
13
|
payment?: (input: I, output: O) => PaymentMoments | null;
|
|
14
14
|
}
|
|
15
|
-
declare function middleware(session: Session): LanguageModelMiddleware;
|
|
16
|
-
declare function wrapTool<T extends Tool>(session: Session, tool: T, opts?: WrapToolOptions): T;
|
|
17
|
-
declare function wrapTools<T extends ToolSet>(session: Session, tools: T, opts?: Record<string, WrapToolOptions>): T;
|
|
15
|
+
declare function middleware(session: Session | null | undefined): LanguageModelMiddleware;
|
|
16
|
+
declare function wrapTool<T extends Tool>(session: Session | null | undefined, tool: T, opts?: WrapToolOptions): T;
|
|
17
|
+
declare function wrapTools<T extends ToolSet>(session: Session | null | undefined, tools: T, opts?: Record<string, WrapToolOptions>): T;
|
|
18
18
|
|
|
19
19
|
export { type PaymentMoments, type WrapToolOptions, middleware, wrapTool, wrapTools };
|
package/dist/ai/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
recordCall
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-GSH5APZW.js";
|
|
4
4
|
import {
|
|
5
5
|
uuidv7
|
|
6
6
|
} from "../chunk-SFGM7KOG.js";
|
|
7
|
+
import "../chunk-46QN2KEZ.js";
|
|
7
8
|
import {
|
|
8
9
|
toJson,
|
|
9
10
|
toJsonObject
|
|
10
11
|
} from "../chunk-FQDHFTVR.js";
|
|
11
|
-
import "../chunk-GCKCAKHA.js";
|
|
12
12
|
|
|
13
13
|
// src/ai/index.ts
|
|
14
14
|
var PARAM_KEYS = [
|
|
@@ -24,6 +24,7 @@ var PARAM_KEYS = [
|
|
|
24
24
|
"stopSequences"
|
|
25
25
|
];
|
|
26
26
|
function middleware(session) {
|
|
27
|
+
if (!session) return {};
|
|
27
28
|
return {
|
|
28
29
|
wrapGenerate: ({ doGenerate, params, model }) => recordCall(
|
|
29
30
|
session,
|
|
@@ -73,7 +74,7 @@ function middleware(session) {
|
|
|
73
74
|
};
|
|
74
75
|
}
|
|
75
76
|
function wrapTool(session, tool, opts = {}) {
|
|
76
|
-
if (!tool.execute) return tool;
|
|
77
|
+
if (!session || !tool.execute) return tool;
|
|
77
78
|
const original = tool.execute;
|
|
78
79
|
const toolName = opts.name ?? tool.name ?? "tool";
|
|
79
80
|
const execute = (input, options) => recordCall(
|
|
@@ -1,39 +1,20 @@
|
|
|
1
|
-
// ../protocol/src/verdict.ts
|
|
2
|
-
var SEVERITY = { ALLOW: 0, REVIEW: 1, DENY: 2 };
|
|
3
|
-
var Verdict = class _Verdict {
|
|
4
|
-
constructor(value) {
|
|
5
|
-
this.value = value;
|
|
6
|
-
}
|
|
7
|
-
static ALLOW = new _Verdict("ALLOW");
|
|
8
|
-
static REVIEW = new _Verdict("REVIEW");
|
|
9
|
-
static DENY = new _Verdict("DENY");
|
|
10
|
-
static of(value) {
|
|
11
|
-
return value === "DENY" ? _Verdict.DENY : value === "REVIEW" ? _Verdict.REVIEW : _Verdict.ALLOW;
|
|
12
|
-
}
|
|
13
|
-
/** The more severe of the two. */
|
|
14
|
-
atLeast(other) {
|
|
15
|
-
const o = typeof other === "string" ? _Verdict.of(other) : other;
|
|
16
|
-
return SEVERITY[o.value] > SEVERITY[this.value] ? o : this;
|
|
17
|
-
}
|
|
18
|
-
/** Whether a synchronous gate must stop the call (GAP-52). */
|
|
19
|
-
blocks(onReview) {
|
|
20
|
-
return this.value === "DENY" || this.value === "REVIEW" && onReview === "abort";
|
|
21
|
-
}
|
|
22
|
-
/** What the gate effectively did: DENY when it blocked, else the verdict itself. */
|
|
23
|
-
effective(onReview) {
|
|
24
|
-
return this.blocks(onReview) ? "DENY" : this.value;
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// ../protocol/src/api.ts
|
|
29
|
-
import { z as z4 } from "zod";
|
|
30
|
-
|
|
31
1
|
// ../protocol/src/evidence.ts
|
|
32
2
|
import { z } from "zod";
|
|
33
3
|
var WIRE_SOURCES = ["AGENT_TRACE", "INTERNAL_NETWORK"];
|
|
34
4
|
var ALL_SOURCES = ["AGENT_TRACE", "INTERNAL_NETWORK", "PLATFORM"];
|
|
35
5
|
var EvidenceSourceSchema = z.enum(WIRE_SOURCES);
|
|
36
6
|
var EvidenceSourceAllSchema = z.enum(ALL_SOURCES);
|
|
7
|
+
var SOURCE_ORDER = {
|
|
8
|
+
AGENT_TRACE: 0,
|
|
9
|
+
INTERNAL_NETWORK: 1,
|
|
10
|
+
PLATFORM: 2
|
|
11
|
+
};
|
|
12
|
+
function compareBySourceSeq(a, b) {
|
|
13
|
+
return SOURCE_ORDER[a.source] - SOURCE_ORDER[b.source] || a.seq - b.seq;
|
|
14
|
+
}
|
|
15
|
+
function compareBySessionSource(a, b) {
|
|
16
|
+
return a.sessionId < b.sessionId ? -1 : a.sessionId > b.sessionId ? 1 : SOURCE_ORDER[a.source] - SOURCE_ORDER[b.source];
|
|
17
|
+
}
|
|
37
18
|
var WIRE_KINDS = [
|
|
38
19
|
"session.open",
|
|
39
20
|
"session.close",
|
|
@@ -76,11 +57,42 @@ var EvidenceEventSchema = z.strictObject({
|
|
|
76
57
|
prevHash: Hex64Schema,
|
|
77
58
|
sig: SigSchema.optional()
|
|
78
59
|
});
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
60
|
+
function isWireKind(kind) {
|
|
61
|
+
return WIRE_KINDS.includes(kind);
|
|
62
|
+
}
|
|
63
|
+
function isPlatformKind(kind) {
|
|
64
|
+
return PLATFORM_KINDS.includes(kind);
|
|
65
|
+
}
|
|
82
66
|
|
|
83
67
|
// ../protocol/src/reason-codes.ts
|
|
68
|
+
var INDICATOR_CODES = [
|
|
69
|
+
"CHAIN_BROKEN",
|
|
70
|
+
"EVIDENCE_MISMATCH",
|
|
71
|
+
"CREDENTIAL_REVOKED",
|
|
72
|
+
"SESSION_INVALID",
|
|
73
|
+
"PRINCIPAL_FLAGGED"
|
|
74
|
+
];
|
|
75
|
+
var ANNOTATION_CODES = ["NO_AGENT_TRACE", "NO_POLICY"];
|
|
76
|
+
var COLLECTOR_CODES = [
|
|
77
|
+
"SCHEMA_INVALID",
|
|
78
|
+
"SESSION_UNKNOWN",
|
|
79
|
+
"SESSION_CLOSED",
|
|
80
|
+
"SESSION_EXPIRED",
|
|
81
|
+
"SOURCE_FORBIDDEN",
|
|
82
|
+
"KIND_FORBIDDEN",
|
|
83
|
+
"SEQ_GAP",
|
|
84
|
+
"PREV_HASH_MISMATCH",
|
|
85
|
+
"SIG_MISSING",
|
|
86
|
+
"SIG_INVALID",
|
|
87
|
+
"PAYLOAD_INVALID",
|
|
88
|
+
"EVENT_TOO_LARGE"
|
|
89
|
+
];
|
|
90
|
+
var DEFAULT_RULE_CODES = [
|
|
91
|
+
"CAP_EXCEEDED",
|
|
92
|
+
"PAYEE_NOT_ALLOWED",
|
|
93
|
+
"NO_INTENT",
|
|
94
|
+
"INTENT_EXPIRED"
|
|
95
|
+
];
|
|
84
96
|
var REASON_CODE_PATTERN = /^[A-Z][A-Z0-9_]{1,63}$/;
|
|
85
97
|
|
|
86
98
|
// ../protocol/src/selector.ts
|
|
@@ -180,6 +192,40 @@ function parseSelector(input) {
|
|
|
180
192
|
"unknown root (payment | intent | session | signal[name=\u2026] | evidence[\u2026])"
|
|
181
193
|
);
|
|
182
194
|
}
|
|
195
|
+
function formatSelector(sel) {
|
|
196
|
+
const path = sel.path.map((p) => "key" in p ? `.${p.key}` : `[${p.index}]`).join("");
|
|
197
|
+
switch (sel.root) {
|
|
198
|
+
case "payment":
|
|
199
|
+
case "intent":
|
|
200
|
+
case "session":
|
|
201
|
+
return `${sel.root}${path}`;
|
|
202
|
+
case "signal":
|
|
203
|
+
return `signal[name=${sel.name}]${path}`;
|
|
204
|
+
case "evidence":
|
|
205
|
+
if (sel.kind === "*") return `evidence[*]${path}`;
|
|
206
|
+
return `evidence[kind=${sel.kind}${sel.source ? `,source=${sel.source}` : ""}]${sel.all ? "[*]" : ""}${path}`;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function isSelectorRef(value) {
|
|
210
|
+
return typeof value === "string" && value.startsWith("@") && value.length > 1;
|
|
211
|
+
}
|
|
212
|
+
function parseSelectorRef(ref) {
|
|
213
|
+
return parseSelector(ref.slice(1));
|
|
214
|
+
}
|
|
215
|
+
function walkPath(value, path) {
|
|
216
|
+
let cur = value;
|
|
217
|
+
for (const seg of path) {
|
|
218
|
+
if (cur === null || cur === void 0) return void 0;
|
|
219
|
+
if ("key" in seg) {
|
|
220
|
+
if (typeof cur !== "object" || Array.isArray(cur)) return void 0;
|
|
221
|
+
cur = cur[seg.key];
|
|
222
|
+
} else {
|
|
223
|
+
if (!Array.isArray(cur)) return void 0;
|
|
224
|
+
cur = cur[seg.index];
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return cur;
|
|
228
|
+
}
|
|
183
229
|
var SelectorStringSchema = z2.string().refine(
|
|
184
230
|
(s) => {
|
|
185
231
|
try {
|
|
@@ -193,6 +239,7 @@ var SelectorStringSchema = z2.string().refine(
|
|
|
193
239
|
);
|
|
194
240
|
|
|
195
241
|
// ../protocol/src/policy.ts
|
|
242
|
+
import { z as z3 } from "zod";
|
|
196
243
|
var PRIMITIVES = ["THRESHOLD", "MEMBERSHIP", "MATCH", "PRESENCE", "FRESHNESS"];
|
|
197
244
|
var PrimitiveSchema = z3.enum(PRIMITIVES);
|
|
198
245
|
var RuleVerdictSchema = z3.enum(["DENY", "REVIEW"]);
|
|
@@ -216,6 +263,7 @@ var PolicyRulesSchema = z3.strictObject({
|
|
|
216
263
|
});
|
|
217
264
|
|
|
218
265
|
// ../protocol/src/api.ts
|
|
266
|
+
import { z as z4 } from "zod";
|
|
219
267
|
var AmountSchema = z4.strictObject({
|
|
220
268
|
/** Decimal string — never a float. For x402 this is the atomic amount (GAP-49). */
|
|
221
269
|
value: z4.string().regex(/^\d+(\.\d+)?$/, "expected a decimal string"),
|
|
@@ -395,7 +443,125 @@ var PlatformAnomalyPayloadSchema = z5.looseObject({
|
|
|
395
443
|
seq: z5.number().int().min(0).nullable(),
|
|
396
444
|
detail: JsonRecord
|
|
397
445
|
});
|
|
446
|
+
var REGISTRY = {
|
|
447
|
+
"session.open": SessionOpenPayloadSchema,
|
|
448
|
+
"session.close": SessionClosePayloadSchema,
|
|
449
|
+
"intent.declared": IntentDeclaredPayloadSchema,
|
|
450
|
+
"llm_call.start": LlmCallStartPayloadSchema,
|
|
451
|
+
"llm_call.end": LlmCallEndPayloadSchema,
|
|
452
|
+
"tool_call.start": ToolCallStartPayloadSchema,
|
|
453
|
+
"tool_call.end": ToolCallEndPayloadSchema,
|
|
454
|
+
"payment.requested": PaymentMomentPayloadSchema,
|
|
455
|
+
"payment.presented": PaymentMomentPayloadSchema,
|
|
456
|
+
"gateway.decision": GatewayDecisionPayloadSchema,
|
|
457
|
+
"transport.gap": TransportGapPayloadSchema,
|
|
458
|
+
"platform.observation": PlatformObservationPayloadSchema,
|
|
459
|
+
"platform.anomaly": PlatformAnomalyPayloadSchema
|
|
460
|
+
};
|
|
461
|
+
function payloadSchemaFor(kind) {
|
|
462
|
+
return REGISTRY[kind];
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// ../protocol/src/verdict.ts
|
|
466
|
+
var SEVERITY = { ALLOW: 0, REVIEW: 1, DENY: 2 };
|
|
467
|
+
var Verdict = class _Verdict {
|
|
468
|
+
constructor(value) {
|
|
469
|
+
this.value = value;
|
|
470
|
+
}
|
|
471
|
+
static ALLOW = new _Verdict("ALLOW");
|
|
472
|
+
static REVIEW = new _Verdict("REVIEW");
|
|
473
|
+
static DENY = new _Verdict("DENY");
|
|
474
|
+
static of(value) {
|
|
475
|
+
return value === "DENY" ? _Verdict.DENY : value === "REVIEW" ? _Verdict.REVIEW : _Verdict.ALLOW;
|
|
476
|
+
}
|
|
477
|
+
/** The more severe of the two. */
|
|
478
|
+
atLeast(other) {
|
|
479
|
+
const o = typeof other === "string" ? _Verdict.of(other) : other;
|
|
480
|
+
return SEVERITY[o.value] > SEVERITY[this.value] ? o : this;
|
|
481
|
+
}
|
|
482
|
+
/** Whether a synchronous gate must stop the call (GAP-52). */
|
|
483
|
+
blocks(onReview) {
|
|
484
|
+
return this.value === "DENY" || this.value === "REVIEW" && onReview === "abort";
|
|
485
|
+
}
|
|
486
|
+
/** What the gate effectively did: DENY when it blocked, else the verdict itself. */
|
|
487
|
+
effective(onReview) {
|
|
488
|
+
return this.blocks(onReview) ? "DENY" : this.value;
|
|
489
|
+
}
|
|
490
|
+
};
|
|
398
491
|
|
|
399
492
|
export {
|
|
493
|
+
WIRE_SOURCES,
|
|
494
|
+
ALL_SOURCES,
|
|
495
|
+
EvidenceSourceSchema,
|
|
496
|
+
EvidenceSourceAllSchema,
|
|
497
|
+
SOURCE_ORDER,
|
|
498
|
+
compareBySourceSeq,
|
|
499
|
+
compareBySessionSource,
|
|
500
|
+
WIRE_KINDS,
|
|
501
|
+
PLATFORM_KINDS,
|
|
502
|
+
WireEvidenceKindSchema,
|
|
503
|
+
PlatformEvidenceKindSchema,
|
|
504
|
+
EvidenceKindSchema,
|
|
505
|
+
Hex64Schema,
|
|
506
|
+
SigSchema,
|
|
507
|
+
SessionIdSchema,
|
|
508
|
+
SeqSchema,
|
|
509
|
+
TimestampSchema,
|
|
510
|
+
JsonValueSchema,
|
|
511
|
+
EvidenceEventSchema,
|
|
512
|
+
isWireKind,
|
|
513
|
+
isPlatformKind,
|
|
514
|
+
INDICATOR_CODES,
|
|
515
|
+
ANNOTATION_CODES,
|
|
516
|
+
COLLECTOR_CODES,
|
|
517
|
+
DEFAULT_RULE_CODES,
|
|
518
|
+
REASON_CODE_PATTERN,
|
|
519
|
+
SelectorSyntaxError,
|
|
520
|
+
parseSelector,
|
|
521
|
+
formatSelector,
|
|
522
|
+
isSelectorRef,
|
|
523
|
+
parseSelectorRef,
|
|
524
|
+
walkPath,
|
|
525
|
+
SelectorStringSchema,
|
|
526
|
+
PRIMITIVES,
|
|
527
|
+
PrimitiveSchema,
|
|
528
|
+
RuleVerdictSchema,
|
|
529
|
+
RuleSchema,
|
|
530
|
+
PolicyRulesSchema,
|
|
531
|
+
AmountSchema,
|
|
532
|
+
DeclaredIntentSchema,
|
|
533
|
+
CreateSessionInputSchema,
|
|
534
|
+
CreateSessionOutputSchema,
|
|
535
|
+
MAX_BATCH_EVENTS,
|
|
536
|
+
EvidenceBatchInputSchema,
|
|
537
|
+
EventResultStatusSchema,
|
|
538
|
+
EventResultSchema,
|
|
539
|
+
ChainHeadSchema,
|
|
540
|
+
EvidenceAckSchema,
|
|
541
|
+
PaymentSummarySchema,
|
|
542
|
+
EvaluateInputSchema,
|
|
543
|
+
DecisionSchema,
|
|
544
|
+
EvaluateOutputSchema,
|
|
545
|
+
AnchorEntrySchema,
|
|
546
|
+
AnchorsOutputSchema,
|
|
547
|
+
CreatePolicyInputSchema,
|
|
548
|
+
CreatePolicyOutputSchema,
|
|
549
|
+
ApiErrorSchema,
|
|
550
|
+
SessionOpenPayloadSchema,
|
|
551
|
+
SESSION_CLOSE_REASONS,
|
|
552
|
+
SessionClosePayloadSchema,
|
|
553
|
+
IntentDeclaredPayloadSchema,
|
|
554
|
+
LlmCallStartPayloadSchema,
|
|
555
|
+
LlmCallEndPayloadSchema,
|
|
556
|
+
ToolCallStartPayloadSchema,
|
|
557
|
+
ToolCallEndPayloadSchema,
|
|
558
|
+
PAYMENT_ARTIFACTS,
|
|
559
|
+
PaymentMomentPayloadSchema,
|
|
560
|
+
GatewayDecisionPayloadSchema,
|
|
561
|
+
TransportGapPayloadSchema,
|
|
562
|
+
PlatformObservationPayloadSchema,
|
|
563
|
+
ANOMALY_TYPES,
|
|
564
|
+
PlatformAnomalyPayloadSchema,
|
|
565
|
+
payloadSchemaFor,
|
|
400
566
|
Verdict
|
|
401
567
|
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// src/core/record.ts
|
|
2
|
+
function errorOf(err) {
|
|
3
|
+
const e = err;
|
|
4
|
+
return { name: String(e?.name ?? "Error"), message: String(e?.message ?? err) };
|
|
5
|
+
}
|
|
6
|
+
function openCall(session, kind, callId, start) {
|
|
7
|
+
const started = Date.now();
|
|
8
|
+
const opened = session.emit(`${kind}.start`, { callId, ...start });
|
|
9
|
+
const close = async (outcome) => {
|
|
10
|
+
await opened;
|
|
11
|
+
return session.emit(
|
|
12
|
+
`${kind}.end`,
|
|
13
|
+
{ callId, ...outcome, durationMs: Date.now() - started }
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
return {
|
|
17
|
+
callId,
|
|
18
|
+
opened,
|
|
19
|
+
end: (outcome = {}) => close(outcome),
|
|
20
|
+
fail: (error, outcome = {}) => close({ error: errorOf(error), ...outcome })
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
async function recordCall(session, kind, callId, start, run, end = () => ({})) {
|
|
24
|
+
const span = openCall(session, kind, callId, start);
|
|
25
|
+
await span.opened;
|
|
26
|
+
try {
|
|
27
|
+
const result = await run();
|
|
28
|
+
await span.end(await end(result));
|
|
29
|
+
return result;
|
|
30
|
+
} catch (err) {
|
|
31
|
+
await span.fail(err);
|
|
32
|
+
throw err;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
openCall,
|
|
38
|
+
recordCall
|
|
39
|
+
};
|
|
@@ -6,20 +6,23 @@ import {
|
|
|
6
6
|
function x402Currency(network, asset) {
|
|
7
7
|
return `${network}/${asset}`;
|
|
8
8
|
}
|
|
9
|
-
function
|
|
9
|
+
function x402Summary(accepts, opts = {}) {
|
|
10
|
+
const payer = opts.payer?.toLowerCase();
|
|
10
11
|
return {
|
|
11
12
|
protocol: "x402",
|
|
12
|
-
payee:
|
|
13
|
+
payee: accepts?.payTo ?? "unknown",
|
|
13
14
|
amount: {
|
|
14
|
-
value:
|
|
15
|
-
currency:
|
|
15
|
+
value: accepts?.amount ?? accepts?.maxAmountRequired ?? "0",
|
|
16
|
+
currency: accepts ? x402Currency(accepts.network ?? "unknown", accepts.asset ?? "unknown") : "unknown"
|
|
16
17
|
},
|
|
17
|
-
|
|
18
|
-
raw
|
|
18
|
+
...payer ? { payer } : {}
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
|
+
function fromAccepts(a, artifact, raw, payer) {
|
|
22
|
+
return { ...x402Summary(a, { payer }), artifact, raw };
|
|
23
|
+
}
|
|
21
24
|
function payerOf(payload) {
|
|
22
|
-
const p = payload.payload;
|
|
25
|
+
const p = payload.payload ?? {};
|
|
23
26
|
const auth = p.authorization;
|
|
24
27
|
const candidates = [
|
|
25
28
|
auth?.from,
|
|
@@ -32,15 +35,13 @@ function payerOf(payload) {
|
|
|
32
35
|
return typeof hit === "string" ? hit.toLowerCase() : void 0;
|
|
33
36
|
}
|
|
34
37
|
var x402Moments = {
|
|
35
|
-
/** The 402 challenge as the buyer saw it. */
|
|
38
|
+
/** The 402 challenge as the buyer saw it, v2 header or v1 body. */
|
|
36
39
|
required(required) {
|
|
37
|
-
|
|
38
|
-
return fromAccepts(r.accepts[0], "http-402", toJsonObject(r));
|
|
40
|
+
return fromAccepts(required.accepts?.[0], "http-402", toJsonObject(required));
|
|
39
41
|
},
|
|
40
42
|
/** The requirements the seller's resource server resolved for a request. */
|
|
41
43
|
requirements(req) {
|
|
42
|
-
|
|
43
|
-
return fromAccepts(r, "http-402", toJsonObject(r));
|
|
44
|
+
return fromAccepts(req, "http-402", toJsonObject(req));
|
|
44
45
|
},
|
|
45
46
|
/** A route's static `accepts` config, before any payment header exists. */
|
|
46
47
|
route(route, raw) {
|
|
@@ -61,14 +62,18 @@ var x402Moments = {
|
|
|
61
62
|
ask(first, raw) {
|
|
62
63
|
return fromAccepts(first, "mrtr-input-required", raw);
|
|
63
64
|
},
|
|
64
|
-
/**
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
65
|
+
/**
|
|
66
|
+
* The signed payment the buyer presented. A v2 payload carries the
|
|
67
|
+
* requirement it accepted; a v1 payload does not, so the caller passes
|
|
68
|
+
* the `accepts` entry it answered.
|
|
69
|
+
*/
|
|
70
|
+
payload(payload, accepts) {
|
|
71
|
+
return fromAccepts(
|
|
72
|
+
accepts ?? payload.accepted,
|
|
73
|
+
"payment-signature",
|
|
74
|
+
toJsonObject(payload),
|
|
75
|
+
payerOf(payload)
|
|
76
|
+
);
|
|
72
77
|
}
|
|
73
78
|
};
|
|
74
79
|
function priceValue(price) {
|
|
@@ -81,6 +86,7 @@ function priceValue(price) {
|
|
|
81
86
|
|
|
82
87
|
export {
|
|
83
88
|
x402Currency,
|
|
89
|
+
x402Summary,
|
|
84
90
|
payerOf,
|
|
85
91
|
x402Moments
|
|
86
92
|
};
|
|
@@ -7,13 +7,7 @@ import {
|
|
|
7
7
|
} from "./chunk-SFGM7KOG.js";
|
|
8
8
|
import {
|
|
9
9
|
x402Moments
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import {
|
|
12
|
-
summaryOf
|
|
13
|
-
} from "./chunk-7G5EHNVW.js";
|
|
14
|
-
import {
|
|
15
|
-
Verdict
|
|
16
|
-
} from "./chunk-GCKCAKHA.js";
|
|
10
|
+
} from "./chunk-LM4NIYE5.js";
|
|
17
11
|
|
|
18
12
|
// src/x402/adapter.ts
|
|
19
13
|
function attachX402(beltic, server, http, opts = {}) {
|
|
@@ -56,16 +50,20 @@ function attachX402(beltic, server, http, opts = {}) {
|
|
|
56
50
|
const presented = x402Moments.payload(payload);
|
|
57
51
|
await session.emit("payment.presented", presented);
|
|
58
52
|
inFlight.set(payloadDigest(payload), session);
|
|
59
|
-
const out = await beltic.evaluate(session.id,
|
|
53
|
+
const out = await beltic.evaluate(session.id, presented);
|
|
54
|
+
if (!out) return;
|
|
60
55
|
opts.onDecision?.({
|
|
61
56
|
sessionId: session.id,
|
|
62
57
|
decision: out.decision,
|
|
63
58
|
reasonCodes: out.reasonCodes,
|
|
64
59
|
born: session.born
|
|
65
60
|
});
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
61
|
+
if (out.verdict.blocks(beltic.onReview)) {
|
|
62
|
+
return {
|
|
63
|
+
abort: true,
|
|
64
|
+
reason: `BELTIC_${out.verdict.value}`,
|
|
65
|
+
message: out.reasonCodes.join(",")
|
|
66
|
+
};
|
|
69
67
|
}
|
|
70
68
|
return;
|
|
71
69
|
});
|
|
@@ -79,17 +77,6 @@ function attachX402(beltic, server, http, opts = {}) {
|
|
|
79
77
|
return { inFlight };
|
|
80
78
|
}
|
|
81
79
|
|
|
82
|
-
// src/x402/middleware.ts
|
|
83
|
-
import {
|
|
84
|
-
x402HTTPResourceServer
|
|
85
|
-
} from "@x402/core/server";
|
|
86
|
-
function guardedPaymentMiddleware(fromHTTPServer, beltic, routes, server, opts = {}) {
|
|
87
|
-
const http = new x402HTTPResourceServer(server, routes);
|
|
88
|
-
attachX402(beltic, server, http, opts);
|
|
89
|
-
return fromHTTPServer(http, opts.paywall);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
80
|
export {
|
|
93
|
-
attachX402
|
|
94
|
-
guardedPaymentMiddleware
|
|
81
|
+
attachX402
|
|
95
82
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
attachX402
|
|
3
|
+
} from "./chunk-SO6HPRJT.js";
|
|
4
|
+
|
|
5
|
+
// src/x402/middleware.ts
|
|
6
|
+
import {
|
|
7
|
+
x402HTTPResourceServer
|
|
8
|
+
} from "@x402/core/server";
|
|
9
|
+
function guardedPaymentMiddleware(fromHTTPServer, beltic, routes, server, opts = {}) {
|
|
10
|
+
const http = new x402HTTPResourceServer(server, routes);
|
|
11
|
+
attachX402(beltic, server, http, opts);
|
|
12
|
+
return fromHTTPServer(http, opts.paywall);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
guardedPaymentMiddleware
|
|
17
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { a as PaymentSummary, P as PaymentMomentPayload, B as EvaluateOutput } from './index-Bjs3BPPU.js';
|
|
2
|
+
import { O as OnReview, V as Verdict } from './verdict-BAahb5po.js';
|
|
3
|
+
import { a as ApiClient, g as Transport, e as Sessions, A as AgentIdentity, b as ApiClientOptions, i as TransportOptions, R as RedactFn } from './session-5TClPLI4.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Correlation without binding (Fraud SDK RFC › Protocol Adapter — x402:
|
|
7
|
+
* "binding travels on the call that initiates the purchase, not
|
|
8
|
+
* necessarily on the payment artifact"). The merchant binds a key it will
|
|
9
|
+
* see again (a checkout session id, a challenge nonce) to the buyer's
|
|
10
|
+
* session; the adapter resolves it when the settlement arrives (GAP-31).
|
|
11
|
+
*/
|
|
12
|
+
interface CorrelationStore {
|
|
13
|
+
bind(key: string, sessionId: string, ttlMs?: number): Promise<void>;
|
|
14
|
+
resolve(key: string): Promise<string | null>;
|
|
15
|
+
}
|
|
16
|
+
declare class MemoryCorrelationStore implements CorrelationStore {
|
|
17
|
+
private readonly defaultTtlMs;
|
|
18
|
+
private readonly entries;
|
|
19
|
+
constructor(defaultTtlMs?: number);
|
|
20
|
+
bind(key: string, sessionId: string, ttlMs?: number): Promise<void>;
|
|
21
|
+
resolve(key: string): Promise<string | null>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* One SDK, two halves (Fraud SDK RFC › Summary). `Beltic` is the single
|
|
26
|
+
* client: sessions and evidence for both halves, `evaluate` for whichever
|
|
27
|
+
* half is about to let a payment through. Protocol integrations are plain
|
|
28
|
+
* functions behind subpath exports, each pulling exactly one optional peer:
|
|
29
|
+
*
|
|
30
|
+
* @belticlabs/agent-risk-sdk/ai → middleware(session), wrapTools(session, …)
|
|
31
|
+
* @belticlabs/agent-risk-sdk/x402 → belticFetch(session), x402Summary(…), attachX402(beltic, …)
|
|
32
|
+
* @belticlabs/agent-risk-sdk/hono → belticPaymentMiddleware(beltic, …) (and /express)
|
|
33
|
+
* @belticlabs/agent-risk-sdk/mcp → wrapClient(session, …), wrapServer(beltic, …)
|
|
34
|
+
*
|
|
35
|
+
* Neither half decides risk locally: verdicts are platform-side.
|
|
36
|
+
*
|
|
37
|
+
* Evidence is a side channel of the work it observes. With `failOpen`
|
|
38
|
+
* nothing the SDK does throws into that work: `Session.emit` reports and
|
|
39
|
+
* answers `false`, `sessions.open` answers `null`, `evaluate` answers
|
|
40
|
+
* `null` — never an invented verdict; the host decides what to do without
|
|
41
|
+
* one (GAP-70). `sessions.start` and `sessions.ensure` throw either way:
|
|
42
|
+
* they are the primitives the fail-open entries are built on.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
declare const SDK_VERSION = "0.2.0";
|
|
46
|
+
interface BelticOptions extends Omit<ApiClientOptions, 'userAgent'> {
|
|
47
|
+
/** Buyer half. Without it, `sessions.start` is unavailable; the seller half works. */
|
|
48
|
+
identity?: AgentIdentity | undefined;
|
|
49
|
+
transport?: Partial<TransportOptions> | undefined;
|
|
50
|
+
/** What a synchronous seller hook does with REVIEW (GAP-52). */
|
|
51
|
+
onReview?: OnReview | undefined;
|
|
52
|
+
correlation?: CorrelationStore | undefined;
|
|
53
|
+
redact?: RedactFn | undefined;
|
|
54
|
+
now?: (() => Date) | undefined;
|
|
55
|
+
/** Evidence never fails the work it observes; see the module note (GAP-70). */
|
|
56
|
+
failOpen?: boolean | undefined;
|
|
57
|
+
/** Where fail-open failures go (and transport delivery failures unless `transport` names its own). Default: `console.error`. */
|
|
58
|
+
onError?: ((err: Error) => void) | undefined;
|
|
59
|
+
/** Fail-open only: how long `sessions.open` answers null after the platform refused to open a session (GAP-71). */
|
|
60
|
+
openRetryMs?: number | undefined;
|
|
61
|
+
}
|
|
62
|
+
/** The platform's answer, with the verdict as a value the caller can ask `blocks(onReview)`. */
|
|
63
|
+
type Evaluation = EvaluateOutput & {
|
|
64
|
+
verdict: Verdict;
|
|
65
|
+
};
|
|
66
|
+
declare class Beltic {
|
|
67
|
+
readonly api: ApiClient;
|
|
68
|
+
readonly transport: Transport;
|
|
69
|
+
readonly sessions: Sessions;
|
|
70
|
+
readonly identity: AgentIdentity | undefined;
|
|
71
|
+
readonly correlation: CorrelationStore;
|
|
72
|
+
readonly onReview: OnReview;
|
|
73
|
+
readonly failOpen: boolean;
|
|
74
|
+
private readonly onError;
|
|
75
|
+
constructor(opts: BelticOptions);
|
|
76
|
+
/**
|
|
77
|
+
* The platform's verdict on a payment — the seller's before it verifies,
|
|
78
|
+
* the buyer's before it presents. Read-your-writes: the buffered evidence
|
|
79
|
+
* is flushed first so the platform judges what the caller already saw
|
|
80
|
+
* (GAP-16). A recorded moment is accepted as is: only its comparable core
|
|
81
|
+
* (payee, amount, payer) is sent. `null` only under `failOpen`, when the
|
|
82
|
+
* platform could not be asked.
|
|
83
|
+
*/
|
|
84
|
+
evaluate(sessionId: string, payment: PaymentSummary | PaymentMomentPayload): Promise<Evaluation | null>;
|
|
85
|
+
private decide;
|
|
86
|
+
flush(): Promise<void>;
|
|
87
|
+
shutdown(): Promise<void>;
|
|
88
|
+
}
|
|
89
|
+
declare function createBeltic(opts: BelticOptions): Beltic;
|
|
90
|
+
|
|
91
|
+
export { Beltic as B, type CorrelationStore as C, type Evaluation as E, MemoryCorrelationStore as M, SDK_VERSION as S, type BelticOptions as a, createBeltic as c };
|